mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
feat(statsreporter): build a statsreporter service (#8177)
- build a new statsreporter service
This commit is contained in:
parent
decb660992
commit
a1fa2769e4
3
.github/workflows/build-community.yaml
vendored
3
.github/workflows/build-community.yaml
vendored
@ -74,7 +74,8 @@ jobs:
|
|||||||
-X github.com/SigNoz/signoz/pkg/version.variant=community
|
-X github.com/SigNoz/signoz/pkg/version.variant=community
|
||||||
-X github.com/SigNoz/signoz/pkg/version.hash=${{ needs.prepare.outputs.hash }}
|
-X github.com/SigNoz/signoz/pkg/version.hash=${{ needs.prepare.outputs.hash }}
|
||||||
-X github.com/SigNoz/signoz/pkg/version.time=${{ needs.prepare.outputs.time }}
|
-X github.com/SigNoz/signoz/pkg/version.time=${{ needs.prepare.outputs.time }}
|
||||||
-X github.com/SigNoz/signoz/pkg/version.branch=${{ needs.prepare.outputs.branch }}'
|
-X github.com/SigNoz/signoz/pkg/version.branch=${{ needs.prepare.outputs.branch }}
|
||||||
|
-X github.com/SigNoz/signoz/pkg/analytics.key=9kRrJ7oPCGPEJLF6QjMPLt5bljFhRQBr'
|
||||||
GO_CGO_ENABLED: 1
|
GO_CGO_ENABLED: 1
|
||||||
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
||||||
DOCKER_DOCKERFILE_PATH: ./pkg/query-service/Dockerfile.multi-arch
|
DOCKER_DOCKERFILE_PATH: ./pkg/query-service/Dockerfile.multi-arch
|
||||||
|
|||||||
3
.github/workflows/build-enterprise.yaml
vendored
3
.github/workflows/build-enterprise.yaml
vendored
@ -108,7 +108,8 @@ jobs:
|
|||||||
-X github.com/SigNoz/signoz/ee/zeus.url=https://api.signoz.cloud
|
-X github.com/SigNoz/signoz/ee/zeus.url=https://api.signoz.cloud
|
||||||
-X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.signoz.io
|
-X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.signoz.io
|
||||||
-X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.signoz.cloud
|
-X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.signoz.cloud
|
||||||
-X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.signoz.io/api/v1'
|
-X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.signoz.io/api/v1
|
||||||
|
-X github.com/SigNoz/signoz/pkg/analytics.key=9kRrJ7oPCGPEJLF6QjMPLt5bljFhRQBr'
|
||||||
GO_CGO_ENABLED: 1
|
GO_CGO_ENABLED: 1
|
||||||
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
||||||
DOCKER_DOCKERFILE_PATH: ./ee/query-service/Dockerfile.multi-arch
|
DOCKER_DOCKERFILE_PATH: ./ee/query-service/Dockerfile.multi-arch
|
||||||
|
|||||||
3
.github/workflows/build-staging.yaml
vendored
3
.github/workflows/build-staging.yaml
vendored
@ -107,7 +107,8 @@ jobs:
|
|||||||
-X github.com/SigNoz/signoz/ee/zeus.url=https://api.staging.signoz.cloud
|
-X github.com/SigNoz/signoz/ee/zeus.url=https://api.staging.signoz.cloud
|
||||||
-X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.staging.signoz.cloud
|
-X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.staging.signoz.cloud
|
||||||
-X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.staging.signoz.cloud
|
-X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.staging.signoz.cloud
|
||||||
-X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.staging.signoz.cloud/api/v1'
|
-X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.staging.signoz.cloud/api/v1
|
||||||
|
-X github.com/SigNoz/signoz/pkg/analytics.key=9kRrJ7oPCGPEJLF6QjMPLt5bljFhRQBr'
|
||||||
GO_CGO_ENABLED: 1
|
GO_CGO_ENABLED: 1
|
||||||
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
DOCKER_BASE_IMAGES: '{"alpine": "alpine:3.20.3"}'
|
||||||
DOCKER_DOCKERFILE_PATH: ./ee/query-service/Dockerfile.multi-arch
|
DOCKER_DOCKERFILE_PATH: ./ee/query-service/Dockerfile.multi-arch
|
||||||
|
|||||||
@ -165,12 +165,6 @@ alertmanager:
|
|||||||
# Retention of the notification logs.
|
# Retention of the notification logs.
|
||||||
retention: 120h
|
retention: 120h
|
||||||
|
|
||||||
|
|
||||||
##################### Analytics #####################
|
|
||||||
analytics:
|
|
||||||
# Whether to enable analytics.
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
##################### Emailing #####################
|
##################### Emailing #####################
|
||||||
emailing:
|
emailing:
|
||||||
# Whether to enable emailing.
|
# Whether to enable emailing.
|
||||||
@ -215,3 +209,18 @@ sharder:
|
|||||||
single:
|
single:
|
||||||
# The org id to which this instance belongs to.
|
# The org id to which this instance belongs to.
|
||||||
org_id: org_id
|
org_id: org_id
|
||||||
|
|
||||||
|
##################### Analytics #####################
|
||||||
|
analytics:
|
||||||
|
# Whether to enable analytics.
|
||||||
|
enabled: false
|
||||||
|
segment:
|
||||||
|
# The key to use for segment.
|
||||||
|
key: ""
|
||||||
|
|
||||||
|
##################### StatsReporter #####################
|
||||||
|
statsreporter:
|
||||||
|
# Whether to enable stats reporter. This is used to provide valuable insights to the SigNoz team. It does not collect any sensitive/PII data.
|
||||||
|
enabled: true
|
||||||
|
# The interval at which the stats are collected.
|
||||||
|
interval: 6h
|
||||||
|
|||||||
@ -211,3 +211,16 @@ func (provider *provider) GetFeatureFlags(ctx context.Context, organizationID va
|
|||||||
|
|
||||||
return license.Features, nil
|
return license.Features, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
activeLicense, err := provider.GetActive(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Ast(err, errors.TypeNotFound) {
|
||||||
|
return map[string]any{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return licensetypes.NewStatsFromLicense(activeLicense), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -39,6 +39,7 @@ builds:
|
|||||||
- -X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.signoz.io
|
- -X github.com/SigNoz/signoz/ee/zeus.deprecatedURL=https://license.signoz.io
|
||||||
- -X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.signoz.cloud
|
- -X github.com/SigNoz/signoz/ee/query-service/constants.ZeusURL=https://api.signoz.cloud
|
||||||
- -X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.signoz.io/api/v1
|
- -X github.com/SigNoz/signoz/ee/query-service/constants.LicenseSignozIo=https://license.signoz.io/api/v1
|
||||||
|
- -X github.com/SigNoz/signoz/pkg/analytics.key=9kRrJ7oPCGPEJLF6QjMPLt5bljFhRQBr
|
||||||
- >-
|
- >-
|
||||||
{{- if eq .Os "linux" }}-linkmode external -extldflags '-static'{{- end }}
|
{{- if eq .Os "linux" }}-linkmode external -extldflags '-static'{{- end }}
|
||||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
"github.com/SigNoz/signoz/pkg/types/alertmanagertypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
@ -53,4 +54,7 @@ type Alertmanager interface {
|
|||||||
|
|
||||||
// SetDefaultConfig sets the default config for the organization.
|
// SetDefaultConfig sets the default config for the organization.
|
||||||
SetDefaultConfig(context.Context, string) error
|
SetDefaultConfig(context.Context, string) error
|
||||||
|
|
||||||
|
// Collects stats for the organization.
|
||||||
|
statsreporter.StatsCollector
|
||||||
}
|
}
|
||||||
|
|||||||
@ -471,3 +471,12 @@ func (provider *provider) SetDefaultConfig(ctx context.Context, orgID string) er
|
|||||||
|
|
||||||
return provider.configStore.Set(ctx, config)
|
return provider.configStore.Set(ctx, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
channels, err := provider.configStore.ListChannels(ctx, orgID.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return alertmanagertypes.NewStatsFromChannels(channels), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -182,3 +182,12 @@ func (provider *provider) SetDefaultConfig(ctx context.Context, orgID string) er
|
|||||||
|
|
||||||
return provider.configStore.Set(ctx, config)
|
return provider.configStore.Set(ctx, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
channels, err := provider.configStore.ListChannels(ctx, orgID.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return alertmanagertypes.NewStatsFromChannels(channels), nil
|
||||||
|
}
|
||||||
|
|||||||
30
pkg/analytics/analyticstest/provider.go
Normal file
30
pkg/analytics/analyticstest/provider.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package analyticstest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types/analyticstypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ analytics.Analytics = (*Provider)(nil)
|
||||||
|
|
||||||
|
type Provider struct {
|
||||||
|
stopC chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Provider {
|
||||||
|
return &Provider{stopC: make(chan struct{})}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *Provider) Start(_ context.Context) error {
|
||||||
|
<-provider.stopC
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *Provider) Send(ctx context.Context, messages ...analyticstypes.Message) {}
|
||||||
|
|
||||||
|
func (provider *Provider) Stop(_ context.Context) error {
|
||||||
|
close(provider.stopC)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -1,8 +1,6 @@
|
|||||||
package analytics
|
package analytics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,6 +11,10 @@ var (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Enabled bool `mapstructure:"enabled"`
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Segment Segment `mapstructure:"segment"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Segment struct {
|
||||||
Key string `mapstructure:"key"`
|
Key string `mapstructure:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,14 +25,20 @@ func NewConfigFactory() factory.ConfigFactory {
|
|||||||
func newConfig() factory.Config {
|
func newConfig() factory.Config {
|
||||||
return Config{
|
return Config{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
Segment: Segment{
|
||||||
Key: key,
|
Key: key,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Config) Validate() error {
|
func (c Config) Validate() error {
|
||||||
if c.Key != key {
|
|
||||||
return fmt.Errorf("cannot override key set at build time with key: %s", c.Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) Provider() string {
|
||||||
|
if c.Enabled {
|
||||||
|
return "segment"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "noop"
|
||||||
|
}
|
||||||
|
|||||||
@ -9,31 +9,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type provider struct {
|
type provider struct {
|
||||||
settings factory.ScopedProviderSettings
|
stopC chan struct{}
|
||||||
startC chan struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProviderFactory() factory.ProviderFactory[analytics.Analytics, analytics.Config] {
|
func NewFactory() factory.ProviderFactory[analytics.Analytics, analytics.Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("noop"), New)
|
return factory.NewProviderFactory(factory.MustNewName("noop"), New)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, providerSettings factory.ProviderSettings, config analytics.Config) (analytics.Analytics, error) {
|
func New(ctx context.Context, providerSettings factory.ProviderSettings, config analytics.Config) (analytics.Analytics, error) {
|
||||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/analytics/noopanalytics")
|
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
settings: settings,
|
stopC: make(chan struct{}),
|
||||||
startC: make(chan struct{}),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Start(_ context.Context) error {
|
func (provider *provider) Start(_ context.Context) error {
|
||||||
<-provider.startC
|
<-provider.stopC
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Send(ctx context.Context, messages ...analyticstypes.Message) {}
|
func (provider *provider) Send(ctx context.Context, messages ...analyticstypes.Message) {}
|
||||||
|
|
||||||
func (provider *provider) Stop(_ context.Context) error {
|
func (provider *provider) Stop(_ context.Context) error {
|
||||||
close(provider.startC)
|
close(provider.stopC)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
28
pkg/analytics/segmentanalytics/logger.go
Normal file
28
pkg/analytics/segmentanalytics/logger.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package segmentanalytics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
segment "github.com/segmentio/analytics-go/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type logger struct {
|
||||||
|
settings factory.ScopedProviderSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSegmentLogger(settings factory.ScopedProviderSettings) segment.Logger {
|
||||||
|
return &logger{
|
||||||
|
settings: settings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *logger) Logf(format string, args ...interface{}) {
|
||||||
|
// the no lint directive is needed because the segmentlogger is not a slog.Logger
|
||||||
|
logger.settings.Logger().InfoContext(context.TODO(), format, args...) //nolint:sloglint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *logger) Errorf(format string, args ...interface{}) {
|
||||||
|
// the no lint directive is needed because the segment logger is not a slog.Logger
|
||||||
|
logger.settings.Logger().ErrorContext(context.TODO(), format, args...) //nolint:sloglint
|
||||||
|
}
|
||||||
@ -12,25 +12,32 @@ import (
|
|||||||
type provider struct {
|
type provider struct {
|
||||||
settings factory.ScopedProviderSettings
|
settings factory.ScopedProviderSettings
|
||||||
client segment.Client
|
client segment.Client
|
||||||
startC chan struct{}
|
stopC chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProviderFactory() factory.ProviderFactory[analytics.Analytics, analytics.Config] {
|
func NewFactory() factory.ProviderFactory[analytics.Analytics, analytics.Config] {
|
||||||
return factory.NewProviderFactory(factory.MustNewName("segment"), New)
|
return factory.NewProviderFactory(factory.MustNewName("segment"), New)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, providerSettings factory.ProviderSettings, config analytics.Config) (analytics.Analytics, error) {
|
func New(ctx context.Context, providerSettings factory.ProviderSettings, config analytics.Config) (analytics.Analytics, error) {
|
||||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/analytics/segmentanalytics")
|
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/analytics/segmentanalytics")
|
||||||
|
|
||||||
|
client, err := segment.NewWithConfig(config.Segment.Key, segment.Config{
|
||||||
|
Logger: newSegmentLogger(settings),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &provider{
|
return &provider{
|
||||||
settings: settings,
|
settings: settings,
|
||||||
client: segment.New(config.Key),
|
client: client,
|
||||||
startC: make(chan struct{}),
|
stopC: make(chan struct{}),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Start(_ context.Context) error {
|
func (provider *provider) Start(_ context.Context) error {
|
||||||
<-provider.startC
|
<-provider.stopC
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +50,11 @@ func (provider *provider) Send(ctx context.Context, messages ...analyticstypes.M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *provider) Stop(_ context.Context) error {
|
func (provider *provider) Stop(ctx context.Context) error {
|
||||||
close(provider.startC)
|
if err := provider.client.Close(); err != nil {
|
||||||
|
provider.settings.Logger().WarnContext(ctx, "unable to close segment client", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
close(provider.stopC)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,27 +24,12 @@ func (a *Analytics) Wrap(next http.Handler) http.Handler {
|
|||||||
route := mux.CurrentRoute(r)
|
route := mux.CurrentRoute(r)
|
||||||
path, _ := route.GetPathTemplate()
|
path, _ := route.GetPathTemplate()
|
||||||
|
|
||||||
queryRangeData, metadataExists := a.extractQueryRangeData(path, r)
|
_, _ = a.extractQueryRangeData(path, r)
|
||||||
a.getActiveLogs(path, r)
|
a.getActiveLogs(path, r)
|
||||||
|
|
||||||
badResponseBuffer := new(bytes.Buffer)
|
badResponseBuffer := new(bytes.Buffer)
|
||||||
writer := newBadResponseLoggingWriter(w, badResponseBuffer)
|
writer := newBadResponseLoggingWriter(w, badResponseBuffer)
|
||||||
next.ServeHTTP(writer, r)
|
next.ServeHTTP(writer, r)
|
||||||
|
|
||||||
data := map[string]interface{}{"path": path, "statusCode": writer.StatusCode()}
|
|
||||||
if metadataExists {
|
|
||||||
for key, value := range queryRangeData {
|
|
||||||
data[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := telemetry.EnabledPaths()[path]; ok {
|
|
||||||
claims, err := authtypes.ClaimsFromContext(r.Context())
|
|
||||||
if err == nil {
|
|
||||||
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_PATH, data, claims.Email, true, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
@ -32,6 +33,8 @@ type Licensing interface {
|
|||||||
Portal(ctx context.Context, organizationID valuer.UUID, postableSubscription *licensetypes.PostableSubscription) (*licensetypes.GettableSubscription, error)
|
Portal(ctx context.Context, organizationID valuer.UUID, postableSubscription *licensetypes.PostableSubscription) (*licensetypes.GettableSubscription, error)
|
||||||
// GetFeatureFlags fetches all the defined feature flags
|
// GetFeatureFlags fetches all the defined feature flags
|
||||||
GetFeatureFlags(ctx context.Context, organizationID valuer.UUID) ([]*licensetypes.Feature, error)
|
GetFeatureFlags(ctx context.Context, organizationID valuer.UUID) ([]*licensetypes.Feature, error)
|
||||||
|
|
||||||
|
statsreporter.StatsCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
type API interface {
|
type API interface {
|
||||||
|
|||||||
@ -62,3 +62,7 @@ func (provider *noopLicensing) GetActive(ctx context.Context, organizationID val
|
|||||||
func (provider *noopLicensing) GetFeatureFlags(_ context.Context, _ valuer.UUID) ([]*licensetypes.Feature, error) {
|
func (provider *noopLicensing) GetFeatureFlags(_ context.Context, _ valuer.UUID) ([]*licensetypes.Feature, error) {
|
||||||
return licensetypes.DefaultFeatureSet, nil
|
return licensetypes.DefaultFeatureSet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (provider *noopLicensing) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
return map[string]any{}, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -4,12 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Module interface {
|
type Module interface {
|
||||||
Create(ctx context.Context, orgID valuer.UUID, createdBy string, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error)
|
Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, data dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error)
|
||||||
|
|
||||||
Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error)
|
Get(ctx context.Context, orgID valuer.UUID, id valuer.UUID) (*dashboardtypes.Dashboard, error)
|
||||||
|
|
||||||
@ -22,6 +23,8 @@ type Module interface {
|
|||||||
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
Delete(ctx context.Context, orgID valuer.UUID, id valuer.UUID) error
|
||||||
|
|
||||||
GetByMetricNames(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string][]map[string]string, error)
|
GetByMetricNames(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string][]map[string]string, error)
|
||||||
|
|
||||||
|
statsreporter.StatsCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
|
|||||||
@ -46,7 +46,7 @@ func (handler *handler) Create(rw http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dashboard, err := handler.module.Create(ctx, orgID, claims.Email, req)
|
dashboard, err := handler.module.Create(ctx, orgID, claims.Email, valuer.MustNewUUID(claims.ID), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.Error(rw, err)
|
render.Error(rw, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -4,10 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
"github.com/SigNoz/signoz/pkg/modules/dashboard"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types/analyticstypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
@ -15,17 +17,19 @@ import (
|
|||||||
type module struct {
|
type module struct {
|
||||||
store dashboardtypes.Store
|
store dashboardtypes.Store
|
||||||
settings factory.ScopedProviderSettings
|
settings factory.ScopedProviderSettings
|
||||||
|
analytics analytics.Analytics
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewModule(sqlstore sqlstore.SQLStore, settings factory.ProviderSettings) dashboard.Module {
|
func NewModule(sqlstore sqlstore.SQLStore, settings factory.ProviderSettings, analytics analytics.Analytics) dashboard.Module {
|
||||||
scopedProviderSettings := factory.NewScopedProviderSettings(settings, "github.com/SigNoz/signoz/pkg/modules/impldashboard")
|
scopedProviderSettings := factory.NewScopedProviderSettings(settings, "github.com/SigNoz/signoz/pkg/modules/impldashboard")
|
||||||
return &module{
|
return &module{
|
||||||
store: NewStore(sqlstore),
|
store: NewStore(sqlstore),
|
||||||
settings: scopedProviderSettings,
|
settings: scopedProviderSettings,
|
||||||
|
analytics: analytics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, postableDashboard dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy string, creator valuer.UUID, postableDashboard dashboardtypes.PostableDashboard) (*dashboardtypes.Dashboard, error) {
|
||||||
dashboard, err := dashboardtypes.NewDashboard(orgID, createdBy, postableDashboard)
|
dashboard, err := dashboardtypes.NewDashboard(orgID, createdBy, postableDashboard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -35,11 +39,25 @@ func (module *module) Create(ctx context.Context, orgID valuer.UUID, createdBy s
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = module.store.Create(ctx, storableDashboard)
|
err = module.store.Create(ctx, storableDashboard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.analytics.Send(ctx,
|
||||||
|
analyticstypes.Track{
|
||||||
|
UserId: creator.String(),
|
||||||
|
Event: "Dashboard Created",
|
||||||
|
Properties: analyticstypes.NewPropertiesFromMap(dashboardtypes.NewStatsFromStorableDashboards([]*dashboardtypes.StorableDashboard{storableDashboard})),
|
||||||
|
Context: &analyticstypes.Context{
|
||||||
|
Extra: map[string]interface{}{
|
||||||
|
analyticstypes.KeyGroupID: orgID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return dashboard, nil
|
return dashboard, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,3 +225,12 @@ func (module *module) GetByMetricNames(ctx context.Context, orgID valuer.UUID, m
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
dashboards, err := module.store.List(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dashboardtypes.NewStatsFromStorableDashboards(dashboards), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -22,10 +22,6 @@ func (module *getter) Get(ctx context.Context, id valuer.UUID) (*types.Organizat
|
|||||||
return module.store.Get(ctx, id)
|
return module.store.Get(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (module *getter) List(ctx context.Context) ([]*types.Organization, error) {
|
|
||||||
return module.store.GetAll(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (module *getter) ListByOwnedKeyRange(ctx context.Context) ([]*types.Organization, error) {
|
func (module *getter) ListByOwnedKeyRange(ctx context.Context) ([]*types.Organization, error) {
|
||||||
start, end, err := module.sharder.GetMyOwnedKeyRange(ctx)
|
start, end, err := module.sharder.GetMyOwnedKeyRange(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -12,9 +12,6 @@ type Getter interface {
|
|||||||
// Get gets the organization based on the given id
|
// Get gets the organization based on the given id
|
||||||
Get(context.Context, valuer.UUID) (*types.Organization, error)
|
Get(context.Context, valuer.UUID) (*types.Organization, error)
|
||||||
|
|
||||||
// Lists all the organizations
|
|
||||||
List(context.Context) ([]*types.Organization, error)
|
|
||||||
|
|
||||||
// ListByOwnedKeyRange gets all the organizations owned by the instance
|
// ListByOwnedKeyRange gets all the organizations owned by the instance
|
||||||
ListByOwnedKeyRange(context.Context) ([]*types.Organization, error)
|
ListByOwnedKeyRange(context.Context) ([]*types.Organization, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,3 +169,20 @@ func (module *module) DeleteView(ctx context.Context, orgID string, uuid valuer.
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
savedViews := []*types.SavedView{}
|
||||||
|
|
||||||
|
err := module.
|
||||||
|
sqlstore.
|
||||||
|
BunDB().
|
||||||
|
NewSelect().
|
||||||
|
Model(&savedViews).
|
||||||
|
Where("org_id = ?", orgID).
|
||||||
|
Scan(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.NewStatsFromSavedViews(savedViews), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,6 +19,8 @@ type Module interface {
|
|||||||
UpdateView(ctx context.Context, orgID string, uuid valuer.UUID, view v3.SavedView) error
|
UpdateView(ctx context.Context, orgID string, uuid valuer.UUID, view v3.SavedView) error
|
||||||
|
|
||||||
DeleteView(ctx context.Context, orgID string, uuid valuer.UUID) error
|
DeleteView(ctx context.Context, orgID string, uuid valuer.UUID) error
|
||||||
|
|
||||||
|
statsreporter.StatsCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing"
|
"github.com/SigNoz/signoz/pkg/emailing"
|
||||||
"github.com/SigNoz/signoz/pkg/errors"
|
"github.com/SigNoz/signoz/pkg/errors"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
@ -17,6 +18,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/query-service/model"
|
"github.com/SigNoz/signoz/pkg/query-service/model"
|
||||||
"github.com/SigNoz/signoz/pkg/query-service/telemetry"
|
"github.com/SigNoz/signoz/pkg/query-service/telemetry"
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types/analyticstypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/types/emailtypes"
|
"github.com/SigNoz/signoz/pkg/types/emailtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
@ -29,10 +31,11 @@ type Module struct {
|
|||||||
emailing emailing.Emailing
|
emailing emailing.Emailing
|
||||||
settings factory.ScopedProviderSettings
|
settings factory.ScopedProviderSettings
|
||||||
orgSetter organization.Setter
|
orgSetter organization.Setter
|
||||||
|
analytics analytics.Analytics
|
||||||
}
|
}
|
||||||
|
|
||||||
// This module is a WIP, don't take inspiration from this.
|
// This module is a WIP, don't take inspiration from this.
|
||||||
func NewModule(store types.UserStore, jwt *authtypes.JWT, emailing emailing.Emailing, providerSettings factory.ProviderSettings, orgSetter organization.Setter) user.Module {
|
func NewModule(store types.UserStore, jwt *authtypes.JWT, emailing emailing.Emailing, providerSettings factory.ProviderSettings, orgSetter organization.Setter, analytics analytics.Analytics) user.Module {
|
||||||
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/modules/user/impluser")
|
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/modules/user/impluser")
|
||||||
return &Module{
|
return &Module{
|
||||||
store: store,
|
store: store,
|
||||||
@ -40,6 +43,7 @@ func NewModule(store types.UserStore, jwt *authtypes.JWT, emailing emailing.Emai
|
|||||||
emailing: emailing,
|
emailing: emailing,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
orgSetter: orgSetter,
|
orgSetter: orgSetter,
|
||||||
|
analytics: analytics,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,17 +130,80 @@ func (m *Module) GetInviteByEmailInOrg(ctx context.Context, orgID string, email
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) CreateUserWithPassword(ctx context.Context, user *types.User, password *types.FactorPassword) (*types.User, error) {
|
func (m *Module) CreateUserWithPassword(ctx context.Context, user *types.User, password *types.FactorPassword) (*types.User, error) {
|
||||||
|
|
||||||
user, err := m.store.CreateUserWithPassword(ctx, user, password)
|
user, err := m.store.CreateUserWithPassword(ctx, user, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m.analytics.Send(ctx,
|
||||||
|
analyticstypes.Identify{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
Traits: analyticstypes.
|
||||||
|
NewTraits().
|
||||||
|
SetName(user.DisplayName).
|
||||||
|
SetEmail(user.Email).
|
||||||
|
Set("role", user.Role).
|
||||||
|
SetCreatedAt(user.CreatedAt),
|
||||||
|
},
|
||||||
|
analyticstypes.Group{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
GroupId: user.OrgID,
|
||||||
|
},
|
||||||
|
analyticstypes.Track{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
Event: "User Created",
|
||||||
|
Properties: analyticstypes.NewPropertiesFromMap(map[string]any{
|
||||||
|
"role": user.Role,
|
||||||
|
"email": user.Email,
|
||||||
|
"name": user.DisplayName,
|
||||||
|
}),
|
||||||
|
Context: &analyticstypes.Context{
|
||||||
|
Extra: map[string]interface{}{
|
||||||
|
analyticstypes.KeyGroupID: user.OrgID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) CreateUser(ctx context.Context, user *types.User) error {
|
func (m *Module) CreateUser(ctx context.Context, user *types.User) error {
|
||||||
return m.store.CreateUser(ctx, user)
|
if err := m.store.CreateUser(ctx, user); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m.analytics.Send(ctx,
|
||||||
|
analyticstypes.Identify{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
Traits: analyticstypes.
|
||||||
|
NewTraits().
|
||||||
|
SetName(user.DisplayName).
|
||||||
|
SetEmail(user.Email).
|
||||||
|
Set("role", user.Role).
|
||||||
|
SetCreatedAt(user.CreatedAt),
|
||||||
|
},
|
||||||
|
analyticstypes.Group{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
GroupId: user.OrgID,
|
||||||
|
},
|
||||||
|
analyticstypes.Track{
|
||||||
|
UserId: user.ID.String(),
|
||||||
|
Event: "User Created",
|
||||||
|
Properties: analyticstypes.NewPropertiesFromMap(map[string]any{
|
||||||
|
"role": user.Role,
|
||||||
|
"email": user.Email,
|
||||||
|
"name": user.DisplayName,
|
||||||
|
}),
|
||||||
|
Context: &analyticstypes.Context{
|
||||||
|
Extra: map[string]interface{}{
|
||||||
|
analyticstypes.KeyGroupID: user.OrgID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) GetUserByID(ctx context.Context, orgID string, id string) (*types.GettableUser, error) {
|
func (m *Module) GetUserByID(ctx context.Context, orgID string, id string) (*types.GettableUser, error) {
|
||||||
@ -575,3 +642,12 @@ func (m *Module) Register(ctx context.Context, req *types.PostableRegisterOrgAnd
|
|||||||
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
count, err := m.store.CountByOrgID(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return map[string]any{"user.count": count}, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -809,3 +809,20 @@ func (store *store) DeleteDomain(ctx context.Context, id uuid.UUID) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (store *store) CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error) {
|
||||||
|
user := new(types.User)
|
||||||
|
|
||||||
|
count, err := store.
|
||||||
|
sqlstore.
|
||||||
|
BunDB().
|
||||||
|
NewSelect().
|
||||||
|
Model(user).
|
||||||
|
Where("org_id = ?", orgID).
|
||||||
|
Count(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int64(count), nil
|
||||||
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
@ -65,6 +66,8 @@ type Module interface {
|
|||||||
|
|
||||||
// Register
|
// Register
|
||||||
Register(ctx context.Context, req *types.PostableRegisterOrgAndAdmin) (*types.User, error)
|
Register(ctx context.Context, req *types.PostableRegisterOrgAndAdmin) (*types.User, error)
|
||||||
|
|
||||||
|
statsreporter.StatsCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler interface {
|
type Handler interface {
|
||||||
|
|||||||
@ -35,6 +35,7 @@ builds:
|
|||||||
- -X github.com/SigNoz/signoz/pkg/version.hash={{ .ShortCommit }}
|
- -X github.com/SigNoz/signoz/pkg/version.hash={{ .ShortCommit }}
|
||||||
- -X github.com/SigNoz/signoz/pkg/version.time={{ .CommitTimestamp }}
|
- -X github.com/SigNoz/signoz/pkg/version.time={{ .CommitTimestamp }}
|
||||||
- -X github.com/SigNoz/signoz/pkg/version.branch={{ .Branch }}
|
- -X github.com/SigNoz/signoz/pkg/version.branch={{ .Branch }}
|
||||||
|
- -X github.com/SigNoz/signoz/pkg/analytics.key=9kRrJ7oPCGPEJLF6QjMPLt5bljFhRQBr
|
||||||
- >-
|
- >-
|
||||||
{{- if eq .Os "linux" }}-linkmode external -extldflags '-static'{{- end }}
|
{{- if eq .Os "linux" }}-linkmode external -extldflags '-static'{{- end }}
|
||||||
mod_timestamp: "{{ .CommitTimestamp }}"
|
mod_timestamp: "{{ .CommitTimestamp }}"
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
@ -38,7 +39,8 @@ func TestRegenerateConnectionUrlWithUpdatedConfig(t *testing.T) {
|
|||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
||||||
require.Nil(apiErr)
|
require.Nil(apiErr)
|
||||||
|
|
||||||
@ -94,7 +96,8 @@ func TestAgentCheckIns(t *testing.T) {
|
|||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
||||||
require.Nil(apiErr)
|
require.Nil(apiErr)
|
||||||
|
|
||||||
@ -189,7 +192,8 @@ func TestCantDisconnectNonExistentAccount(t *testing.T) {
|
|||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
||||||
require.Nil(apiErr)
|
require.Nil(apiErr)
|
||||||
|
|
||||||
@ -216,7 +220,8 @@ func TestConfigureService(t *testing.T) {
|
|||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
||||||
require.Nil(apiErr)
|
require.Nil(apiErr)
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
||||||
@ -31,7 +32,8 @@ func TestIntegrationLifecycle(t *testing.T) {
|
|||||||
alertmanager, _ := signozalertmanager.New(context.TODO(), providerSettings, alertmanager.Config{Provider: "signoz", Signoz: alertmanager.Signoz{PollInterval: 10 * time.Second, Config: alertmanagerserver.NewConfig()}}, store, orgGetter)
|
alertmanager, _ := signozalertmanager.New(context.TODO(), providerSettings, alertmanager.Config{Provider: "signoz", Signoz: alertmanager.Signoz{PollInterval: 10 * time.Second, Config: alertmanagerserver.NewConfig()}}, store, orgGetter)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(store, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(store, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
user, apiErr := createTestUser(modules.OrgSetter, modules.User)
|
||||||
if apiErr != nil {
|
if apiErr != nil {
|
||||||
t.Fatalf("could not create test user: %v", apiErr)
|
t.Fatalf("could not create test user: %v", apiErr)
|
||||||
|
|||||||
@ -18,8 +18,10 @@ const (
|
|||||||
OpAmpWsEndpoint = "0.0.0.0:4320" // address for opamp websocket
|
OpAmpWsEndpoint = "0.0.0.0:4320" // address for opamp websocket
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Deprecated: Use the new analytics service instead
|
||||||
var DEFAULT_TELEMETRY_ANONYMOUS = false
|
var DEFAULT_TELEMETRY_ANONYMOUS = false
|
||||||
|
|
||||||
|
// Deprecated: Use the new analytics service instead
|
||||||
func IsOSSTelemetryEnabled() bool {
|
func IsOSSTelemetryEnabled() bool {
|
||||||
ossSegmentKey := GetOrDefaultEnv("OSS_TELEMETRY_ENABLED", "true")
|
ossSegmentKey := GetOrDefaultEnv("OSS_TELEMETRY_ENABLED", "true")
|
||||||
return ossSegmentKey == "true"
|
return ossSegmentKey == "true"
|
||||||
@ -27,6 +29,7 @@ func IsOSSTelemetryEnabled() bool {
|
|||||||
|
|
||||||
const MaxAllowedPointsInTimeSeries = 300
|
const MaxAllowedPointsInTimeSeries = 300
|
||||||
|
|
||||||
|
// Deprecated: Use the new analytics service instead
|
||||||
func IsTelemetryEnabled() bool {
|
func IsTelemetryEnabled() bool {
|
||||||
if testing.Testing() {
|
if testing.Testing() {
|
||||||
return false
|
return false
|
||||||
@ -48,8 +51,10 @@ const SpanSearchScopeRoot = "isroot"
|
|||||||
const SpanSearchScopeEntryPoint = "isentrypoint"
|
const SpanSearchScopeEntryPoint = "isentrypoint"
|
||||||
const OrderBySpanCount = "span_count"
|
const OrderBySpanCount = "span_count"
|
||||||
|
|
||||||
|
// Deprecated: Use the new statsreporter service instead
|
||||||
var TELEMETRY_HEART_BEAT_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_HEART_BEAT_DURATION_MINUTES", 720)
|
var TELEMETRY_HEART_BEAT_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_HEART_BEAT_DURATION_MINUTES", 720)
|
||||||
|
|
||||||
|
// Deprecated: Use the new statsreporter service instead
|
||||||
var TELEMETRY_ACTIVE_USER_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_ACTIVE_USER_DURATION_MINUTES", 360)
|
var TELEMETRY_ACTIVE_USER_DURATION_MINUTES = GetOrDefaultEnvInt("TELEMETRY_ACTIVE_USER_DURATION_MINUTES", 360)
|
||||||
|
|
||||||
// Deprecated: Use the new emailing service instead
|
// Deprecated: Use the new emailing service instead
|
||||||
|
|||||||
@ -195,7 +195,7 @@ func defaultPrepareTaskFunc(opts PrepareTaskOptions) (Task, error) {
|
|||||||
// by calling the Run method.
|
// by calling the Run method.
|
||||||
func NewManager(o *ManagerOptions) (*Manager, error) {
|
func NewManager(o *ManagerOptions) (*Manager, error) {
|
||||||
o = defaultOptions(o)
|
o = defaultOptions(o)
|
||||||
ruleStore := sqlrulestore.NewRuleStore(o.DBConn, o.SQLStore)
|
ruleStore := sqlrulestore.NewRuleStore(o.SQLStore)
|
||||||
maintenanceStore := sqlrulestore.NewMaintenanceStore(o.SQLStore)
|
maintenanceStore := sqlrulestore.NewMaintenanceStore(o.SQLStore)
|
||||||
|
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
|
|||||||
@ -1,13 +1,5 @@
|
|||||||
package telemetry
|
package telemetry
|
||||||
|
|
||||||
func EnabledPaths() map[string]struct{} {
|
|
||||||
enabledPaths := map[string]struct{}{
|
|
||||||
"/api/v1/channels": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return enabledPaths
|
|
||||||
}
|
|
||||||
|
|
||||||
func ignoreEvents(event string, attributes map[string]interface{}) bool {
|
func ignoreEvents(event string, attributes map[string]interface{}) bool {
|
||||||
|
|
||||||
if event == TELEMETRY_EVENT_ACTIVE_USER {
|
if event == TELEMETRY_EVENT_ACTIVE_USER {
|
||||||
|
|||||||
@ -613,7 +613,6 @@ func (a *Telemetry) SendIdentifyEvent(data map[string]interface{}, userEmail str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Telemetry) SendGroupEvent(data map[string]interface{}, userEmail string) {
|
func (a *Telemetry) SendGroupEvent(data map[string]interface{}, userEmail string) {
|
||||||
|
|
||||||
if !a.isTelemetryEnabled() || a.isTelemetryAnonymous() {
|
if !a.isTelemetryEnabled() || a.isTelemetryAnonymous() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder"
|
"github.com/SigNoz/signoz/pkg/sharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
||||||
@ -315,7 +316,8 @@ func NewFilterSuggestionsTestBed(t *testing.T) *FilterSuggestionsTestBed {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
handlers := signoz.NewHandlers(modules)
|
handlers := signoz.NewHandlers(modules)
|
||||||
|
|
||||||
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
||||||
@ -491,7 +492,8 @@ func NewTestbedWithoutOpamp(t *testing.T, sqlStore sqlstore.SQLStore) *LogPipeli
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(sqlStore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
handlers := signoz.NewHandlers(modules)
|
handlers := signoz.NewHandlers(modules)
|
||||||
|
|
||||||
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder"
|
"github.com/SigNoz/signoz/pkg/sharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
||||||
@ -376,7 +377,8 @@ func NewCloudIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *CloudI
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
handlers := signoz.NewHandlers(modules)
|
handlers := signoz.NewHandlers(modules)
|
||||||
|
|
||||||
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
"github.com/SigNoz/signoz/pkg/alertmanager/alertmanagerserver"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/analyticstest"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
"github.com/SigNoz/signoz/pkg/emailing/emailingtest"
|
||||||
"github.com/SigNoz/signoz/pkg/http/middleware"
|
"github.com/SigNoz/signoz/pkg/http/middleware"
|
||||||
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
"github.com/SigNoz/signoz/pkg/instrumentation/instrumentationtest"
|
||||||
@ -582,7 +583,8 @@ func NewIntegrationsTestBed(t *testing.T, testDB sqlstore.SQLStore) *Integration
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
analytics := analyticstest.New()
|
||||||
|
modules := signoz.NewModules(testDB, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
handlers := signoz.NewHandlers(modules)
|
handlers := signoz.NewHandlers(modules)
|
||||||
|
|
||||||
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
apiHandler, err := app.NewAPIHandler(app.APIHandlerOpts{
|
||||||
|
|||||||
20
pkg/ruler/config.go
Normal file
20
pkg/ruler/config.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package ruler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigFactory() factory.ConfigFactory {
|
||||||
|
return factory.NewConfigFactory(factory.MustNewName("ruler"), newConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig() factory.Config {
|
||||||
|
return Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
7
pkg/ruler/ruler.go
Normal file
7
pkg/ruler/ruler.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package ruler
|
||||||
|
|
||||||
|
import "github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
|
|
||||||
|
type Ruler interface {
|
||||||
|
statsreporter.StatsCollector
|
||||||
|
}
|
||||||
@ -6,16 +6,14 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
ruletypes "github.com/SigNoz/signoz/pkg/types/ruletypes"
|
ruletypes "github.com/SigNoz/signoz/pkg/types/ruletypes"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type rule struct {
|
type rule struct {
|
||||||
*sqlx.DB
|
|
||||||
sqlstore sqlstore.SQLStore
|
sqlstore sqlstore.SQLStore
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRuleStore(db *sqlx.DB, store sqlstore.SQLStore) ruletypes.RuleStore {
|
func NewRuleStore(store sqlstore.SQLStore) ruletypes.RuleStore {
|
||||||
return &rule{sqlstore: store, DB: db}
|
return &rule{sqlstore: store}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rule) CreateRule(ctx context.Context, storedRule *ruletypes.Rule, cb func(context.Context, valuer.UUID) error) (valuer.UUID, error) {
|
func (r *rule) CreateRule(ctx context.Context, storedRule *ruletypes.Rule, cb func(context.Context, valuer.UUID) error) (valuer.UUID, error) {
|
||||||
|
|||||||
35
pkg/ruler/signozruler/provider.go
Normal file
35
pkg/ruler/signozruler/provider.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package signozruler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler/rulestore/sqlrulestore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types/ruletypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
ruleStore ruletypes.RuleStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[ruler.Ruler, ruler.Config] {
|
||||||
|
return factory.NewProviderFactory(factory.MustNewName("signoz"), func(ctx context.Context, settings factory.ProviderSettings, config ruler.Config) (ruler.Ruler, error) {
|
||||||
|
return New(ctx, settings, config, sqlstore)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, settings factory.ProviderSettings, config ruler.Config, sqlstore sqlstore.SQLStore) (ruler.Ruler, error) {
|
||||||
|
return &provider{ruleStore: sqlrulestore.NewRuleStore(sqlstore)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
|
||||||
|
rules, err := provider.ruleStore.GetStoredRules(ctx, orgID.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ruletypes.NewStatsFromRules(rules), nil
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
"github.com/SigNoz/signoz/pkg/apiserver"
|
"github.com/SigNoz/signoz/pkg/apiserver"
|
||||||
"github.com/SigNoz/signoz/pkg/cache"
|
"github.com/SigNoz/signoz/pkg/cache"
|
||||||
"github.com/SigNoz/signoz/pkg/config"
|
"github.com/SigNoz/signoz/pkg/config"
|
||||||
@ -17,10 +18,12 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/instrumentation"
|
"github.com/SigNoz/signoz/pkg/instrumentation"
|
||||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder"
|
"github.com/SigNoz/signoz/pkg/sharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlmigration"
|
"github.com/SigNoz/signoz/pkg/sqlmigration"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlmigrator"
|
"github.com/SigNoz/signoz/pkg/sqlmigrator"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||||
"github.com/SigNoz/signoz/pkg/version"
|
"github.com/SigNoz/signoz/pkg/version"
|
||||||
"github.com/SigNoz/signoz/pkg/web"
|
"github.com/SigNoz/signoz/pkg/web"
|
||||||
@ -34,6 +37,9 @@ type Config struct {
|
|||||||
// Instrumentation config
|
// Instrumentation config
|
||||||
Instrumentation instrumentation.Config `mapstructure:"instrumentation"`
|
Instrumentation instrumentation.Config `mapstructure:"instrumentation"`
|
||||||
|
|
||||||
|
// Analytics config
|
||||||
|
Analytics analytics.Config `mapstructure:"analytics"`
|
||||||
|
|
||||||
// Web config
|
// Web config
|
||||||
Web web.Config `mapstructure:"web"`
|
Web web.Config `mapstructure:"web"`
|
||||||
|
|
||||||
@ -61,11 +67,17 @@ type Config struct {
|
|||||||
// Alertmanager config
|
// Alertmanager config
|
||||||
Alertmanager alertmanager.Config `mapstructure:"alertmanager" yaml:"alertmanager"`
|
Alertmanager alertmanager.Config `mapstructure:"alertmanager" yaml:"alertmanager"`
|
||||||
|
|
||||||
|
// Ruler config
|
||||||
|
Ruler ruler.Config `mapstructure:"ruler"`
|
||||||
|
|
||||||
// Emailing config
|
// Emailing config
|
||||||
Emailing emailing.Config `mapstructure:"emailing" yaml:"emailing"`
|
Emailing emailing.Config `mapstructure:"emailing" yaml:"emailing"`
|
||||||
|
|
||||||
// Sharder config
|
// Sharder config
|
||||||
Sharder sharder.Config `mapstructure:"sharder" yaml:"sharder"`
|
Sharder sharder.Config `mapstructure:"sharder" yaml:"sharder"`
|
||||||
|
|
||||||
|
// StatsReporter config
|
||||||
|
StatsReporter statsreporter.Config `mapstructure:"statsreporter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeprecatedFlags are the flags that are deprecated and scheduled for removal.
|
// DeprecatedFlags are the flags that are deprecated and scheduled for removal.
|
||||||
@ -81,6 +93,7 @@ func NewConfig(ctx context.Context, resolverConfig config.ResolverConfig, deprec
|
|||||||
configFactories := []factory.ConfigFactory{
|
configFactories := []factory.ConfigFactory{
|
||||||
version.NewConfigFactory(),
|
version.NewConfigFactory(),
|
||||||
instrumentation.NewConfigFactory(),
|
instrumentation.NewConfigFactory(),
|
||||||
|
analytics.NewConfigFactory(),
|
||||||
web.NewConfigFactory(),
|
web.NewConfigFactory(),
|
||||||
cache.NewConfigFactory(),
|
cache.NewConfigFactory(),
|
||||||
sqlstore.NewConfigFactory(),
|
sqlstore.NewConfigFactory(),
|
||||||
@ -89,8 +102,10 @@ func NewConfig(ctx context.Context, resolverConfig config.ResolverConfig, deprec
|
|||||||
telemetrystore.NewConfigFactory(),
|
telemetrystore.NewConfigFactory(),
|
||||||
prometheus.NewConfigFactory(),
|
prometheus.NewConfigFactory(),
|
||||||
alertmanager.NewConfigFactory(),
|
alertmanager.NewConfigFactory(),
|
||||||
|
ruler.NewConfigFactory(),
|
||||||
emailing.NewConfigFactory(),
|
emailing.NewConfigFactory(),
|
||||||
sharder.NewConfigFactory(),
|
sharder.NewConfigFactory(),
|
||||||
|
statsreporter.NewConfigFactory(),
|
||||||
}
|
}
|
||||||
|
|
||||||
conf, err := config.New(ctx, resolverConfig, configFactories)
|
conf, err := config.New(ctx, resolverConfig, configFactories)
|
||||||
@ -235,4 +250,14 @@ func mergeAndEnsureBackwardCompatibility(config *Config, deprecatedFlags Depreca
|
|||||||
fmt.Println("[Deprecated] env SMTP_FROM is deprecated and scheduled for removal. Please use SIGNOZ_EMAILING_FROM instead.")
|
fmt.Println("[Deprecated] env SMTP_FROM is deprecated and scheduled for removal. Please use SIGNOZ_EMAILING_FROM instead.")
|
||||||
config.Emailing.SMTP.From = os.Getenv("SMTP_FROM")
|
config.Emailing.SMTP.From = os.Getenv("SMTP_FROM")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("SIGNOZ_SAAS_SEGMENT_KEY") != "" {
|
||||||
|
fmt.Println("[Deprecated] env SIGNOZ_SAAS_SEGMENT_KEY is deprecated and scheduled for removal. Please use SIGNOZ_ANALYTICS_SEGMENT_KEY instead.")
|
||||||
|
config.Analytics.Segment.Key = os.Getenv("SIGNOZ_SAAS_SEGMENT_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("TELEMETRY_ENABLED") != "" {
|
||||||
|
fmt.Println("[Deprecated] env TELEMETRY_ENABLED is deprecated and scheduled for removal. Please use SIGNOZ_ANALYTICS_ENABLED instead.")
|
||||||
|
config.Analytics.Enabled = os.Getenv("TELEMETRY_ENABLED") == "true"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func TestNewHandlers(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager, nil)
|
||||||
|
|
||||||
handlers := NewHandlers(modules)
|
handlers := NewHandlers(modules)
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package signoz
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
"github.com/SigNoz/signoz/pkg/emailing"
|
"github.com/SigNoz/signoz/pkg/emailing"
|
||||||
"github.com/SigNoz/signoz/pkg/factory"
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/apdex"
|
"github.com/SigNoz/signoz/pkg/modules/apdex"
|
||||||
@ -44,17 +45,18 @@ func NewModules(
|
|||||||
providerSettings factory.ProviderSettings,
|
providerSettings factory.ProviderSettings,
|
||||||
orgGetter organization.Getter,
|
orgGetter organization.Getter,
|
||||||
alertmanager alertmanager.Alertmanager,
|
alertmanager alertmanager.Alertmanager,
|
||||||
|
analytics analytics.Analytics,
|
||||||
) Modules {
|
) Modules {
|
||||||
quickfilter := implquickfilter.NewModule(implquickfilter.NewStore(sqlstore))
|
quickfilter := implquickfilter.NewModule(implquickfilter.NewStore(sqlstore))
|
||||||
orgSetter := implorganization.NewSetter(implorganization.NewStore(sqlstore), alertmanager, quickfilter)
|
orgSetter := implorganization.NewSetter(implorganization.NewStore(sqlstore), alertmanager, quickfilter)
|
||||||
user := impluser.NewModule(impluser.NewStore(sqlstore, providerSettings), jwt, emailing, providerSettings, orgSetter)
|
user := impluser.NewModule(impluser.NewStore(sqlstore, providerSettings), jwt, emailing, providerSettings, orgSetter, analytics)
|
||||||
return Modules{
|
return Modules{
|
||||||
OrgGetter: orgGetter,
|
OrgGetter: orgGetter,
|
||||||
OrgSetter: orgSetter,
|
OrgSetter: orgSetter,
|
||||||
Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewAvailablePreference()),
|
Preference: implpreference.NewModule(implpreference.NewStore(sqlstore), preferencetypes.NewAvailablePreference()),
|
||||||
SavedView: implsavedview.NewModule(sqlstore),
|
SavedView: implsavedview.NewModule(sqlstore),
|
||||||
Apdex: implapdex.NewModule(sqlstore),
|
Apdex: implapdex.NewModule(sqlstore),
|
||||||
Dashboard: impldashboard.NewModule(sqlstore, providerSettings),
|
Dashboard: impldashboard.NewModule(sqlstore, providerSettings, analytics),
|
||||||
User: user,
|
User: user,
|
||||||
QuickFilter: quickfilter,
|
QuickFilter: quickfilter,
|
||||||
TraceFunnel: impltracefunnel.NewModule(impltracefunnel.NewStore(sqlstore)),
|
TraceFunnel: impltracefunnel.NewModule(impltracefunnel.NewStore(sqlstore)),
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func TestNewModules(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
jwt := authtypes.NewJWT("", 1*time.Hour, 1*time.Hour)
|
||||||
emailing := emailingtest.New()
|
emailing := emailingtest.New()
|
||||||
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager, nil)
|
||||||
|
|
||||||
reflectVal := reflect.ValueOf(modules)
|
reflectVal := reflect.ValueOf(modules)
|
||||||
for i := 0; i < reflectVal.NumField(); i++ {
|
for i := 0; i < reflectVal.NumField(); i++ {
|
||||||
|
|||||||
@ -4,6 +4,9 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/legacyalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/legacyalertmanager"
|
||||||
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
"github.com/SigNoz/signoz/pkg/alertmanager/signozalertmanager"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/noopanalytics"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/segmentanalytics"
|
||||||
"github.com/SigNoz/signoz/pkg/cache"
|
"github.com/SigNoz/signoz/pkg/cache"
|
||||||
"github.com/SigNoz/signoz/pkg/cache/memorycache"
|
"github.com/SigNoz/signoz/pkg/cache/memorycache"
|
||||||
"github.com/SigNoz/signoz/pkg/cache/rediscache"
|
"github.com/SigNoz/signoz/pkg/cache/rediscache"
|
||||||
@ -14,6 +17,8 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||||
"github.com/SigNoz/signoz/pkg/prometheus/clickhouseprometheus"
|
"github.com/SigNoz/signoz/pkg/prometheus/clickhouseprometheus"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler/signozruler"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder"
|
"github.com/SigNoz/signoz/pkg/sharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
"github.com/SigNoz/signoz/pkg/sharder/noopsharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder/singlesharder"
|
"github.com/SigNoz/signoz/pkg/sharder/singlesharder"
|
||||||
@ -21,14 +26,25 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore/sqlitesqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore/sqlitesqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore/sqlstorehook"
|
"github.com/SigNoz/signoz/pkg/sqlstore/sqlstorehook"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter/analyticsstatsreporter"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter/noopstatsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore/clickhousetelemetrystore"
|
"github.com/SigNoz/signoz/pkg/telemetrystore/clickhousetelemetrystore"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore/telemetrystorehook"
|
"github.com/SigNoz/signoz/pkg/telemetrystore/telemetrystorehook"
|
||||||
|
"github.com/SigNoz/signoz/pkg/version"
|
||||||
"github.com/SigNoz/signoz/pkg/web"
|
"github.com/SigNoz/signoz/pkg/web"
|
||||||
"github.com/SigNoz/signoz/pkg/web/noopweb"
|
"github.com/SigNoz/signoz/pkg/web/noopweb"
|
||||||
"github.com/SigNoz/signoz/pkg/web/routerweb"
|
"github.com/SigNoz/signoz/pkg/web/routerweb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewAnalyticsProviderFactories() factory.NamedMap[factory.ProviderFactory[analytics.Analytics, analytics.Config]] {
|
||||||
|
return factory.MustNewNamedMap(
|
||||||
|
noopanalytics.NewFactory(),
|
||||||
|
segmentanalytics.NewFactory(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func NewCacheProviderFactories() factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]] {
|
func NewCacheProviderFactories() factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]] {
|
||||||
return factory.MustNewNamedMap(
|
return factory.MustNewNamedMap(
|
||||||
memorycache.NewFactory(),
|
memorycache.NewFactory(),
|
||||||
@ -114,6 +130,12 @@ func NewAlertmanagerProviderFactories(sqlstore sqlstore.SQLStore, orgGetter orga
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRulerProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedMap[factory.ProviderFactory[ruler.Ruler, ruler.Config]] {
|
||||||
|
return factory.MustNewNamedMap(
|
||||||
|
signozruler.NewFactory(sqlstore),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func NewEmailingProviderFactories() factory.NamedMap[factory.ProviderFactory[emailing.Emailing, emailing.Config]] {
|
func NewEmailingProviderFactories() factory.NamedMap[factory.ProviderFactory[emailing.Emailing, emailing.Config]] {
|
||||||
return factory.MustNewNamedMap(
|
return factory.MustNewNamedMap(
|
||||||
noopemailing.NewFactory(),
|
noopemailing.NewFactory(),
|
||||||
@ -127,3 +149,10 @@ func NewSharderProviderFactories() factory.NamedMap[factory.ProviderFactory[shar
|
|||||||
noopsharder.NewFactory(),
|
noopsharder.NewFactory(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsReporterProviderFactories(telemetryStore telemetrystore.TelemetryStore, collectors []statsreporter.StatsCollector, orgGetter organization.Getter, build version.Build, analyticsConfig analytics.Config) factory.NamedMap[factory.ProviderFactory[statsreporter.StatsReporter, statsreporter.Config]] {
|
||||||
|
return factory.MustNewNamedMap(
|
||||||
|
analyticsstatsreporter.NewFactory(telemetryStore, collectors, orgGetter, build, analyticsConfig),
|
||||||
|
noopstatsreporter.NewFactory(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -4,11 +4,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/DATA-DOG/go-sqlmock"
|
"github.com/DATA-DOG/go-sqlmock"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore/sqlstoretest"
|
"github.com/SigNoz/signoz/pkg/sqlstore/sqlstoretest"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore/telemetrystoretest"
|
"github.com/SigNoz/signoz/pkg/telemetrystore/telemetrystoretest"
|
||||||
|
"github.com/SigNoz/signoz/pkg/version"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,6 +48,10 @@ func TestNewProviderFactories(t *testing.T) {
|
|||||||
NewAlertmanagerProviderFactories(sqlstoretest.New(sqlstore.Config{Provider: "sqlite"}, sqlmock.QueryMatcherEqual), orgGetter)
|
NewAlertmanagerProviderFactories(sqlstoretest.New(sqlstore.Config{Provider: "sqlite"}, sqlmock.QueryMatcherEqual), orgGetter)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
NewRulerProviderFactories(sqlstoretest.New(sqlstore.Config{Provider: "sqlite"}, sqlmock.QueryMatcherEqual))
|
||||||
|
})
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
NewEmailingProviderFactories()
|
NewEmailingProviderFactories()
|
||||||
})
|
})
|
||||||
@ -52,4 +59,10 @@ func TestNewProviderFactories(t *testing.T) {
|
|||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
NewSharderProviderFactories()
|
NewSharderProviderFactories()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
orgGetter := implorganization.NewGetter(implorganization.NewStore(sqlstoretest.New(sqlstore.Config{Provider: "sqlite"}, sqlmock.QueryMatcherEqual)), nil)
|
||||||
|
telemetryStore := telemetrystoretest.New(telemetrystore.Config{Provider: "clickhouse"}, sqlmock.QueryMatcherEqual)
|
||||||
|
NewStatsReporterProviderFactories(telemetryStore, []statsreporter.StatsCollector{}, orgGetter, version.Build{}, analytics.Config{Enabled: true})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,10 +12,12 @@ import (
|
|||||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
"github.com/SigNoz/signoz/pkg/modules/organization/implorganization"
|
||||||
"github.com/SigNoz/signoz/pkg/prometheus"
|
"github.com/SigNoz/signoz/pkg/prometheus"
|
||||||
|
"github.com/SigNoz/signoz/pkg/ruler"
|
||||||
"github.com/SigNoz/signoz/pkg/sharder"
|
"github.com/SigNoz/signoz/pkg/sharder"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlmigration"
|
"github.com/SigNoz/signoz/pkg/sqlmigration"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlmigrator"
|
"github.com/SigNoz/signoz/pkg/sqlmigrator"
|
||||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||||
"github.com/SigNoz/signoz/pkg/version"
|
"github.com/SigNoz/signoz/pkg/version"
|
||||||
@ -33,10 +35,12 @@ type SigNoz struct {
|
|||||||
TelemetryStore telemetrystore.TelemetryStore
|
TelemetryStore telemetrystore.TelemetryStore
|
||||||
Prometheus prometheus.Prometheus
|
Prometheus prometheus.Prometheus
|
||||||
Alertmanager alertmanager.Alertmanager
|
Alertmanager alertmanager.Alertmanager
|
||||||
|
Rules ruler.Ruler
|
||||||
Zeus zeus.Zeus
|
Zeus zeus.Zeus
|
||||||
Licensing licensing.Licensing
|
Licensing licensing.Licensing
|
||||||
Emailing emailing.Emailing
|
Emailing emailing.Emailing
|
||||||
Sharder sharder.Sharder
|
Sharder sharder.Sharder
|
||||||
|
StatsReporter statsreporter.StatsReporter
|
||||||
Modules Modules
|
Modules Modules
|
||||||
Handlers Handlers
|
Handlers Handlers
|
||||||
}
|
}
|
||||||
@ -48,7 +52,7 @@ func New(
|
|||||||
zeusConfig zeus.Config,
|
zeusConfig zeus.Config,
|
||||||
zeusProviderFactory factory.ProviderFactory[zeus.Zeus, zeus.Config],
|
zeusProviderFactory factory.ProviderFactory[zeus.Zeus, zeus.Config],
|
||||||
licenseConfig licensing.Config,
|
licenseConfig licensing.Config,
|
||||||
licenseProviderFactoryCb func(sqlstore.SQLStore, zeus.Zeus, organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config],
|
licenseProviderFactory func(sqlstore.SQLStore, zeus.Zeus, organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config],
|
||||||
emailingProviderFactories factory.NamedMap[factory.ProviderFactory[emailing.Emailing, emailing.Config]],
|
emailingProviderFactories factory.NamedMap[factory.ProviderFactory[emailing.Emailing, emailing.Config]],
|
||||||
cacheProviderFactories factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]],
|
cacheProviderFactories factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]],
|
||||||
webProviderFactories factory.NamedMap[factory.ProviderFactory[web.Web, web.Config]],
|
webProviderFactories factory.NamedMap[factory.ProviderFactory[web.Web, web.Config]],
|
||||||
@ -67,6 +71,18 @@ func New(
|
|||||||
// Get the provider settings from instrumentation
|
// Get the provider settings from instrumentation
|
||||||
providerSettings := instrumentation.ToProviderSettings()
|
providerSettings := instrumentation.ToProviderSettings()
|
||||||
|
|
||||||
|
// Initialize analytics just after instrumentation, as providers might require it
|
||||||
|
analytics, err := factory.NewProviderFromNamedMap(
|
||||||
|
ctx,
|
||||||
|
providerSettings,
|
||||||
|
config.Analytics,
|
||||||
|
NewAnalyticsProviderFactories(),
|
||||||
|
config.Analytics.Provider(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize zeus from the available zeus provider factory. This is not config controlled
|
// Initialize zeus from the available zeus provider factory. This is not config controlled
|
||||||
// and depends on the variant of the build.
|
// and depends on the variant of the build.
|
||||||
zeus, err := zeusProviderFactory.New(
|
zeus, err := zeusProviderFactory.New(
|
||||||
@ -193,7 +209,19 @@ func New(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
licensingProviderFactory := licenseProviderFactoryCb(sqlstore, zeus, orgGetter)
|
// Initialize ruler from the available ruler provider factories
|
||||||
|
ruler, err := factory.NewProviderFromNamedMap(
|
||||||
|
ctx,
|
||||||
|
providerSettings,
|
||||||
|
config.Ruler,
|
||||||
|
NewRulerProviderFactories(sqlstore),
|
||||||
|
"signoz",
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
licensingProviderFactory := licenseProviderFactory(sqlstore, zeus, orgGetter)
|
||||||
licensing, err := licensingProviderFactory.New(
|
licensing, err := licensingProviderFactory.New(
|
||||||
ctx,
|
ctx,
|
||||||
providerSettings,
|
providerSettings,
|
||||||
@ -204,16 +232,40 @@ func New(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all modules
|
// Initialize all modules
|
||||||
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager)
|
modules := NewModules(sqlstore, jwt, emailing, providerSettings, orgGetter, alertmanager, analytics)
|
||||||
|
|
||||||
// Initialize all handlers for the modules
|
// Initialize all handlers for the modules
|
||||||
handlers := NewHandlers(modules)
|
handlers := NewHandlers(modules)
|
||||||
|
|
||||||
|
// Create a list of all stats collectors
|
||||||
|
statsCollectors := []statsreporter.StatsCollector{
|
||||||
|
alertmanager,
|
||||||
|
ruler,
|
||||||
|
modules.Dashboard,
|
||||||
|
modules.SavedView,
|
||||||
|
modules.User,
|
||||||
|
licensing,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize stats reporter from the available stats reporter provider factories
|
||||||
|
statsReporter, err := factory.NewProviderFromNamedMap(
|
||||||
|
ctx,
|
||||||
|
providerSettings,
|
||||||
|
config.StatsReporter,
|
||||||
|
NewStatsReporterProviderFactories(telemetrystore, statsCollectors, orgGetter, version.Info, config.Analytics),
|
||||||
|
config.StatsReporter.Provider(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
registry, err := factory.NewRegistry(
|
registry, err := factory.NewRegistry(
|
||||||
instrumentation.Logger(),
|
instrumentation.Logger(),
|
||||||
factory.NewNamedService(factory.MustNewName("instrumentation"), instrumentation),
|
factory.NewNamedService(factory.MustNewName("instrumentation"), instrumentation),
|
||||||
|
factory.NewNamedService(factory.MustNewName("analytics"), analytics),
|
||||||
factory.NewNamedService(factory.MustNewName("alertmanager"), alertmanager),
|
factory.NewNamedService(factory.MustNewName("alertmanager"), alertmanager),
|
||||||
factory.NewNamedService(factory.MustNewName("licensing"), licensing),
|
factory.NewNamedService(factory.MustNewName("licensing"), licensing),
|
||||||
|
factory.NewNamedService(factory.MustNewName("statsreporter"), statsReporter),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
216
pkg/statsreporter/analyticsstatsreporter/provider.go
Normal file
216
pkg/statsreporter/analyticsstatsreporter/provider.go
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package analyticsstatsreporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics"
|
||||||
|
"github.com/SigNoz/signoz/pkg/analytics/segmentanalytics"
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
|
"github.com/SigNoz/signoz/pkg/telemetrystore"
|
||||||
|
"github.com/SigNoz/signoz/pkg/types/analyticstypes"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
"github.com/SigNoz/signoz/pkg/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
// settings
|
||||||
|
settings factory.ScopedProviderSettings
|
||||||
|
|
||||||
|
// config
|
||||||
|
config statsreporter.Config
|
||||||
|
|
||||||
|
// used to get telemetry details. srikanthcvv to move this to the querier layer
|
||||||
|
telemetryStore telemetrystore.TelemetryStore
|
||||||
|
|
||||||
|
// a list of collectors, used to collect stats from across the codebase
|
||||||
|
collectors []statsreporter.StatsCollector
|
||||||
|
|
||||||
|
// used to get organizations
|
||||||
|
orgGetter organization.Getter
|
||||||
|
|
||||||
|
// used to send stats to an analytics backend
|
||||||
|
analytics analytics.Analytics
|
||||||
|
|
||||||
|
// used to get build information
|
||||||
|
build version.Build
|
||||||
|
|
||||||
|
// used to get deployment information
|
||||||
|
deployment version.Deployment
|
||||||
|
|
||||||
|
// used to stop the provider
|
||||||
|
stopC chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFactory(telemetryStore telemetrystore.TelemetryStore, collectors []statsreporter.StatsCollector, orgGetter organization.Getter, build version.Build, analyticsConfig analytics.Config) factory.ProviderFactory[statsreporter.StatsReporter, statsreporter.Config] {
|
||||||
|
return factory.NewProviderFactory(factory.MustNewName("analytics"), func(ctx context.Context, settings factory.ProviderSettings, config statsreporter.Config) (statsreporter.StatsReporter, error) {
|
||||||
|
return New(ctx, settings, config, telemetryStore, collectors, orgGetter, build, analyticsConfig)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(
|
||||||
|
ctx context.Context,
|
||||||
|
providerSettings factory.ProviderSettings,
|
||||||
|
config statsreporter.Config,
|
||||||
|
telemetryStore telemetrystore.TelemetryStore,
|
||||||
|
collectors []statsreporter.StatsCollector,
|
||||||
|
orgGetter organization.Getter,
|
||||||
|
build version.Build,
|
||||||
|
analyticsConfig analytics.Config,
|
||||||
|
) (statsreporter.StatsReporter, error) {
|
||||||
|
settings := factory.NewScopedProviderSettings(providerSettings, "github.com/SigNoz/signoz/pkg/statsreporter/analyticsstatsreporter")
|
||||||
|
deployment := version.NewDeployment()
|
||||||
|
analytics, err := segmentanalytics.New(ctx, providerSettings, analyticsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &provider{
|
||||||
|
settings: settings,
|
||||||
|
config: config,
|
||||||
|
telemetryStore: telemetryStore,
|
||||||
|
collectors: collectors,
|
||||||
|
orgGetter: orgGetter,
|
||||||
|
analytics: analytics,
|
||||||
|
build: build,
|
||||||
|
deployment: deployment,
|
||||||
|
stopC: make(chan struct{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Start(ctx context.Context) error {
|
||||||
|
go func() {
|
||||||
|
if err := provider.analytics.Start(ctx); err != nil {
|
||||||
|
provider.settings.Logger().ErrorContext(ctx, "failed to start analytics", "error", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
ticker := time.NewTicker(provider.config.Interval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-provider.stopC:
|
||||||
|
return nil
|
||||||
|
case <-ticker.C:
|
||||||
|
err := provider.Report(ctx)
|
||||||
|
if err != nil {
|
||||||
|
provider.settings.Logger().ErrorContext(ctx, "failed to report stats", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Report(ctx context.Context) error {
|
||||||
|
orgs, err := provider.orgGetter.ListByOwnedKeyRange(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, org := range orgs {
|
||||||
|
stats := provider.collectOrg(ctx, org.ID)
|
||||||
|
if len(stats) == 0 {
|
||||||
|
provider.settings.Logger().WarnContext(ctx, "no stats collected", "org_id", org.ID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
stats["build.version"] = provider.build.Version()
|
||||||
|
stats["build.branch"] = provider.build.Branch()
|
||||||
|
stats["build.hash"] = provider.build.Hash()
|
||||||
|
stats["build.variant"] = provider.build.Variant()
|
||||||
|
stats["deployment.mode"] = provider.deployment.Mode()
|
||||||
|
stats["deployment.platform"] = provider.deployment.Platform()
|
||||||
|
stats["deployment.os"] = provider.deployment.OS()
|
||||||
|
stats["deployment.arch"] = provider.deployment.Arch()
|
||||||
|
|
||||||
|
provider.settings.Logger().DebugContext(ctx, "reporting stats", "stats", stats)
|
||||||
|
provider.analytics.Send(
|
||||||
|
ctx,
|
||||||
|
analyticstypes.Track{
|
||||||
|
UserId: org.ID.String(),
|
||||||
|
Event: "Stats Reported",
|
||||||
|
Properties: analyticstypes.NewPropertiesFromMap(stats),
|
||||||
|
Context: &analyticstypes.Context{
|
||||||
|
Extra: map[string]interface{}{
|
||||||
|
analyticstypes.KeyGroupID: org.ID.String(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
analyticstypes.Group{
|
||||||
|
UserId: org.ID.String(),
|
||||||
|
GroupId: org.ID.String(),
|
||||||
|
Traits: analyticstypes.
|
||||||
|
NewTraitsFromMap(stats).
|
||||||
|
SetName(org.DisplayName).
|
||||||
|
SetUsername(org.Name).
|
||||||
|
SetCreatedAt(org.CreatedAt),
|
||||||
|
},
|
||||||
|
analyticstypes.Identify{
|
||||||
|
UserId: org.ID.String(),
|
||||||
|
Traits: analyticstypes.
|
||||||
|
NewTraits().
|
||||||
|
SetName(org.DisplayName).
|
||||||
|
SetUsername(org.Name).
|
||||||
|
SetCreatedAt(org.CreatedAt),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Stop(ctx context.Context) error {
|
||||||
|
close(provider.stopC)
|
||||||
|
if err := provider.analytics.Stop(ctx); err != nil {
|
||||||
|
provider.settings.Logger().ErrorContext(ctx, "failed to stop analytics", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) collectOrg(ctx context.Context, orgID valuer.UUID) map[string]any {
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(provider.collectors))
|
||||||
|
|
||||||
|
stats := make(map[string]any, 0)
|
||||||
|
mtx := sync.Mutex{}
|
||||||
|
|
||||||
|
for _, collector := range provider.collectors {
|
||||||
|
go func(collector statsreporter.StatsCollector) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
collectorStats, err := collector.Collect(ctx, orgID)
|
||||||
|
if err != nil {
|
||||||
|
provider.settings.Logger().ErrorContext(ctx, "failed to collect stats", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mtx.Lock()
|
||||||
|
for k, v := range collectorStats {
|
||||||
|
stats[k] = v
|
||||||
|
}
|
||||||
|
mtx.Unlock()
|
||||||
|
}(collector)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
var traces uint64
|
||||||
|
if err := provider.telemetryStore.ClickhouseDB().QueryRow(ctx, "SELECT COUNT(*) FROM signoz_traces.distributed_signoz_index_v3").Scan(&traces); err == nil {
|
||||||
|
stats["telemetry.traces.count"] = traces
|
||||||
|
}
|
||||||
|
|
||||||
|
var logs uint64
|
||||||
|
if err := provider.telemetryStore.ClickhouseDB().QueryRow(ctx, "SELECT COUNT(*) FROM signoz_logs.distributed_logs_v2").Scan(&logs); err == nil {
|
||||||
|
stats["telemetry.logs.count"] = logs
|
||||||
|
}
|
||||||
|
|
||||||
|
var metrics uint64
|
||||||
|
if err := provider.telemetryStore.ClickhouseDB().QueryRow(ctx, "SELECT COUNT(*) FROM signoz_metrics.distributed_samples_v4").Scan(&metrics); err == nil {
|
||||||
|
stats["telemetry.metrics.count"] = metrics
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats
|
||||||
|
}
|
||||||
38
pkg/statsreporter/config.go
Normal file
38
pkg/statsreporter/config.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package statsreporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
// Enabled is a flag to enable or disable the stats reporter.
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
|
||||||
|
// Interval is the interval at which the stats are collected.
|
||||||
|
Interval time.Duration `mapstructure:"interval"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfigFactory() factory.ConfigFactory {
|
||||||
|
return factory.NewConfigFactory(factory.MustNewName("statsreporter"), newConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig() factory.Config {
|
||||||
|
return Config{
|
||||||
|
Enabled: true,
|
||||||
|
Interval: 6 * time.Hour,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Config) Provider() string {
|
||||||
|
if c.Enabled {
|
||||||
|
return "analytics"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "noop"
|
||||||
|
}
|
||||||
36
pkg/statsreporter/noopstatsreporter/provider.go
Normal file
36
pkg/statsreporter/noopstatsreporter/provider.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package noopstatsreporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/statsreporter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type provider struct {
|
||||||
|
stopC chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFactory() factory.ProviderFactory[statsreporter.StatsReporter, statsreporter.Config] {
|
||||||
|
return factory.NewProviderFactory(factory.MustNewName("noop"), New)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, providerSettings factory.ProviderSettings, config statsreporter.Config) (statsreporter.StatsReporter, error) {
|
||||||
|
return &provider{
|
||||||
|
stopC: make(chan struct{}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Start(ctx context.Context) error {
|
||||||
|
<-provider.stopC
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Report(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (provider *provider) Stop(ctx context.Context) error {
|
||||||
|
close(provider.stopC)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
18
pkg/statsreporter/statsreporter.go
Normal file
18
pkg/statsreporter/statsreporter.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package statsreporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/SigNoz/signoz/pkg/factory"
|
||||||
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StatsReporter interface {
|
||||||
|
factory.Service
|
||||||
|
|
||||||
|
Report(context.Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatsCollector interface {
|
||||||
|
Collect(context.Context, valuer.UUID) (map[string]any, error)
|
||||||
|
}
|
||||||
@ -146,6 +146,22 @@ func GetChannelByName(channels Channels, name string) (int, *Channel, error) {
|
|||||||
return 0, nil, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with name %s", name)
|
return 0, nil, errors.Newf(errors.TypeNotFound, ErrCodeAlertmanagerChannelNotFound, "cannot find channel with name %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsFromChannels(channels Channels) map[string]any {
|
||||||
|
stats := make(map[string]any)
|
||||||
|
for _, channel := range channels {
|
||||||
|
key := "alertmanager.channel.type." + channel.Type
|
||||||
|
|
||||||
|
if _, ok := stats[key]; !ok {
|
||||||
|
stats[key] = int64(1)
|
||||||
|
} else {
|
||||||
|
stats[key] = stats[key].(int64) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stats["alertmanager.channel.count"] = int64(len(channels))
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Channel) Update(receiver Receiver) error {
|
func (c *Channel) Update(receiver Receiver) error {
|
||||||
channel := NewChannelFromReceiver(receiver, c.OrgID)
|
channel := NewChannelFromReceiver(receiver, c.OrgID)
|
||||||
if channel == nil {
|
if channel == nil {
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
package analyticstypes
|
package analyticstypes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
segment "github.com/segmentio/analytics-go/v3"
|
segment "github.com/segmentio/analytics-go/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyGroupID string = "groupId"
|
||||||
|
)
|
||||||
|
|
||||||
type Message = segment.Message
|
type Message = segment.Message
|
||||||
type Group = segment.Group
|
type Group = segment.Group
|
||||||
type Identify = segment.Identify
|
type Identify = segment.Identify
|
||||||
@ -19,3 +25,21 @@ func NewTraits() Traits {
|
|||||||
func NewProperties() Properties {
|
func NewProperties() Properties {
|
||||||
return segment.NewProperties()
|
return segment.NewProperties()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPropertiesFromMap(m map[string]any) Properties {
|
||||||
|
properties := NewProperties()
|
||||||
|
for k, v := range m {
|
||||||
|
properties.Set(strings.ReplaceAll(k, ".", "_"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTraitsFromMap(m map[string]any) Traits {
|
||||||
|
traits := NewTraits()
|
||||||
|
for k, v := range m {
|
||||||
|
traits.Set(strings.ReplaceAll(k, ".", "_"), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return traits
|
||||||
|
}
|
||||||
|
|||||||
@ -145,6 +145,68 @@ func NewGettableDashboardFromDashboard(dashboard *Dashboard) (*GettableDashboard
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsFromStorableDashboards(dashboards []*StorableDashboard) map[string]any {
|
||||||
|
stats := make(map[string]any)
|
||||||
|
stats["dashboard.panels.count"] = int64(0)
|
||||||
|
stats["dashboard.panels.traces.count"] = int64(0)
|
||||||
|
stats["dashboard.panels.metrics.count"] = int64(0)
|
||||||
|
stats["dashboard.panels.logs.count"] = int64(0)
|
||||||
|
for _, dashboard := range dashboards {
|
||||||
|
addStatsFromStorableDashboard(dashboard, stats)
|
||||||
|
}
|
||||||
|
|
||||||
|
stats["dashboard.count"] = int64(len(dashboards))
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
|
func addStatsFromStorableDashboard(dashboard *StorableDashboard, stats map[string]any) {
|
||||||
|
if dashboard.Data == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if dashboard.Data["widgets"] == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
widgets, ok := dashboard.Data["widgets"]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data, ok := widgets.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, widget := range data {
|
||||||
|
sData, ok := widget.(map[string]interface{})
|
||||||
|
if ok && sData["query"] != nil {
|
||||||
|
stats["dashboard.panels.count"] = stats["dashboard.panels.count"].(int64) + 1
|
||||||
|
query, ok := sData["query"].(map[string]interface{})
|
||||||
|
if ok && query["queryType"] == "builder" && query["builder"] != nil {
|
||||||
|
builderData, ok := query["builder"].(map[string]interface{})
|
||||||
|
if ok && builderData["queryData"] != nil {
|
||||||
|
builderQueryData, ok := builderData["queryData"].([]interface{})
|
||||||
|
if ok {
|
||||||
|
for _, queryData := range builderQueryData {
|
||||||
|
data, ok := queryData.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
if data["dataSource"] == "traces" {
|
||||||
|
stats["dashboard.panels.traces.count"] = stats["dashboard.panels.traces.count"].(int64) + 1
|
||||||
|
} else if data["dataSource"] == "metrics" {
|
||||||
|
stats["dashboard.panels.metrics.count"] = stats["dashboard.panels.metrics.count"].(int64) + 1
|
||||||
|
} else if data["dataSource"] == "logs" {
|
||||||
|
stats["dashboard.panels.logs.count"] = stats["dashboard.panels.logs.count"].(int64) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (storableDashboardData *StorableDashboardData) GetWidgetIds() []string {
|
func (storableDashboardData *StorableDashboardData) GetWidgetIds() []string {
|
||||||
data := *storableDashboardData
|
data := *storableDashboardData
|
||||||
widgetIds := []string{}
|
widgetIds := []string{}
|
||||||
|
|||||||
@ -323,6 +323,13 @@ func NewLicenseFromStorableLicense(storableLicense *StorableLicense) (*License,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsFromLicense(license *License) map[string]any {
|
||||||
|
return map[string]any{
|
||||||
|
"license.plan": license.PlanName.StringValue(),
|
||||||
|
"license.id": license.ID.StringValue(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (license *License) UpdateFeatures(features []*Feature) {
|
func (license *License) UpdateFeatures(features []*Feature) {
|
||||||
license.Features = features
|
license.Features = features
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package ruletypes
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/SigNoz/signoz/pkg/types"
|
"github.com/SigNoz/signoz/pkg/types"
|
||||||
"github.com/SigNoz/signoz/pkg/valuer"
|
"github.com/SigNoz/signoz/pkg/valuer"
|
||||||
@ -18,6 +20,33 @@ type Rule struct {
|
|||||||
OrgID string `bun:"org_id,type:text"`
|
OrgID string `bun:"org_id,type:text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsFromRules(rules []*Rule) map[string]any {
|
||||||
|
stats := make(map[string]any)
|
||||||
|
for _, rule := range rules {
|
||||||
|
gettableRule := &GettableRule{}
|
||||||
|
if err := json.Unmarshal([]byte(rule.Data), gettableRule); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key := "rule.type." + strings.TrimSuffix(strings.ToLower(string(gettableRule.RuleType)), "_rule") + ".count"
|
||||||
|
if _, ok := stats[key]; !ok {
|
||||||
|
stats[key] = int64(1)
|
||||||
|
} else {
|
||||||
|
stats[key] = stats[key].(int64) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
key = "alert.type." + strings.TrimSuffix(strings.ToLower(string(gettableRule.AlertType)), "_based_alert") + ".count"
|
||||||
|
if _, ok := stats[key]; !ok {
|
||||||
|
stats[key] = int64(1)
|
||||||
|
} else {
|
||||||
|
stats[key] = stats[key].(int64) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stats["rule.count"] = int64(len(rules))
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|
||||||
type RuleStore interface {
|
type RuleStore interface {
|
||||||
CreateRule(context.Context, *Rule, func(context.Context, valuer.UUID) error) (valuer.UUID, error)
|
CreateRule(context.Context, *Rule, func(context.Context, valuer.UUID) error) (valuer.UUID, error)
|
||||||
EditRule(context.Context, *Rule, func(context.Context) error) error
|
EditRule(context.Context, *Rule, func(context.Context) error) error
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,3 +20,18 @@ type SavedView struct {
|
|||||||
Data string `json:"data" bun:"data,type:text,notnull"`
|
Data string `json:"data" bun:"data,type:text,notnull"`
|
||||||
ExtraData string `json:"extraData" bun:"extra_data,type:text"`
|
ExtraData string `json:"extraData" bun:"extra_data,type:text"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStatsFromSavedViews(savedViews []*SavedView) map[string]any {
|
||||||
|
stats := make(map[string]any)
|
||||||
|
for _, savedView := range savedViews {
|
||||||
|
key := "savedview.source." + strings.ToLower(string(savedView.SourcePage)) + ".count"
|
||||||
|
if _, ok := stats[key]; !ok {
|
||||||
|
stats[key] = int64(1)
|
||||||
|
} else {
|
||||||
|
stats[key] = stats[key].(int64) + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stats["savedview.count"] = int64(len(savedViews))
|
||||||
|
return stats
|
||||||
|
}
|
||||||
|
|||||||
@ -72,6 +72,8 @@ type UserStore interface {
|
|||||||
ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*StorableAPIKeyUser, error)
|
ListAPIKeys(ctx context.Context, orgID valuer.UUID) ([]*StorableAPIKeyUser, error)
|
||||||
RevokeAPIKey(ctx context.Context, id valuer.UUID, revokedByUserID valuer.UUID) error
|
RevokeAPIKey(ctx context.Context, id valuer.UUID, revokedByUserID valuer.UUID) error
|
||||||
GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*StorableAPIKeyUser, error)
|
GetAPIKey(ctx context.Context, orgID, id valuer.UUID) (*StorableAPIKeyUser, error)
|
||||||
|
|
||||||
|
CountByOrgID(ctx context.Context, orgID valuer.UUID) (int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GettableUser struct {
|
type GettableUser struct {
|
||||||
|
|||||||
155
pkg/version/deployment.go
Normal file
155
pkg/version/deployment.go
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
gotime "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
current = Deployment{mode: "unknown", platform: "unknown", os: "unknown", arch: "unknown"}
|
||||||
|
once = sync.Once{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Deployment struct {
|
||||||
|
// mode of deployment, e.g. kubernetes, binary, etc.
|
||||||
|
mode string
|
||||||
|
|
||||||
|
// platform of deployment, e.g. heroku, render, aws, gcp, azure, digitalocean, etc.
|
||||||
|
platform string
|
||||||
|
|
||||||
|
// os of deployment, e.g. linux, darwin, etc.
|
||||||
|
os string
|
||||||
|
|
||||||
|
// arch of deployment, e.g. amd64, arm64, etc.
|
||||||
|
arch string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeployment() Deployment {
|
||||||
|
once.Do(func() {
|
||||||
|
current.mode = detectMode()
|
||||||
|
current.platform = detectPlatform()
|
||||||
|
current.os = runtime.GOOS
|
||||||
|
current.arch = runtime.GOARCH
|
||||||
|
})
|
||||||
|
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Deployment) Mode() string {
|
||||||
|
return d.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Deployment) Platform() string {
|
||||||
|
return d.platform
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Deployment) OS() string {
|
||||||
|
return d.os
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Deployment) Arch() string {
|
||||||
|
return d.arch
|
||||||
|
}
|
||||||
|
|
||||||
|
func detectMode() string {
|
||||||
|
// Check if running in Kubernetes
|
||||||
|
if os.Getenv("KUBERNETES_SERVICE_HOST") != "" {
|
||||||
|
return "kubernetes"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if running in a container and identify the runtime
|
||||||
|
if data, err := os.ReadFile("/proc/self/cgroup"); err == nil {
|
||||||
|
cgroupData := string(data)
|
||||||
|
switch {
|
||||||
|
case strings.Contains(cgroupData, "docker"):
|
||||||
|
return "docker"
|
||||||
|
case strings.Contains(cgroupData, "containerd"):
|
||||||
|
return "containerd"
|
||||||
|
case strings.Contains(cgroupData, "libpod") || strings.Contains(cgroupData, "podman"):
|
||||||
|
return "podman"
|
||||||
|
case strings.Contains(cgroupData, "crio"):
|
||||||
|
return "cri-o"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if running as a binary
|
||||||
|
if exe, err := os.Executable(); err == nil {
|
||||||
|
// Check if the executable is in a standard binary location
|
||||||
|
exePath := filepath.Clean(exe)
|
||||||
|
if strings.HasPrefix(exePath, "/usr/local/bin/") ||
|
||||||
|
strings.HasPrefix(exePath, "/usr/bin/") ||
|
||||||
|
strings.HasPrefix(exePath, "/bin/") ||
|
||||||
|
strings.HasPrefix(exePath, "/opt/") {
|
||||||
|
return "binary"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the executable is in the current directory
|
||||||
|
if filepath.Dir(exePath) == "." || filepath.Dir(exePath) == filepath.Clean(os.Getenv("PWD")) {
|
||||||
|
return "binary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
func detectPlatform() string {
|
||||||
|
// Check for PaaS platforms first as they use environment variables
|
||||||
|
switch {
|
||||||
|
case os.Getenv("DYNO") != "" || os.Getenv("HEROKU_APP_ID") != "":
|
||||||
|
return "heroku"
|
||||||
|
case os.Getenv("RENDER") != "" || os.Getenv("RENDER_SERVICE_ID") != "":
|
||||||
|
return "render"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to detect cloud provider through metadata endpoints
|
||||||
|
client := &http.Client{Timeout: 1 * gotime.Second}
|
||||||
|
|
||||||
|
// AWS metadata
|
||||||
|
if req, err := http.NewRequest(http.MethodGet, "http://169.254.169.254/latest/meta-data/", nil); err == nil {
|
||||||
|
if resp, err := client.Do(req); err == nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode == 200 {
|
||||||
|
return "aws"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GCP metadata
|
||||||
|
if req, err := http.NewRequest(http.MethodGet, "http://169.254.169.254/computeMetadata/v1/", nil); err == nil {
|
||||||
|
req.Header.Add("Metadata-Flavor", "Google")
|
||||||
|
if resp, err := client.Do(req); err == nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode == 200 {
|
||||||
|
return "gcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Azure metadata
|
||||||
|
if req, err := http.NewRequest(http.MethodGet, "http://169.254.169.254/metadata/instance", nil); err == nil {
|
||||||
|
req.Header.Add("Metadata", "true")
|
||||||
|
if resp, err := client.Do(req); err == nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode == 200 {
|
||||||
|
return "azure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Digitalocean metadata
|
||||||
|
if req, err := http.NewRequest(http.MethodGet, "http://169.254.169.254/metadata/v1/", nil); err == nil {
|
||||||
|
if resp, err := client.Do(req); err == nil {
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode == 200 {
|
||||||
|
return "digitalocean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user