mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-17 15:36:48 +00:00
feat(licensing): add analytics (#8252)
This commit is contained in:
parent
d236b6ce1e
commit
59ff7ed1e1
@ -6,11 +6,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/ee/licensing/licensingstore/sqllicensingstore"
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/licensing"
|
||||
"github.com/SigNoz/signoz/pkg/modules/organization"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/analyticstypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/licensetypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/SigNoz/signoz/pkg/zeus"
|
||||
@ -23,16 +25,17 @@ type provider struct {
|
||||
config licensing.Config
|
||||
settings factory.ScopedProviderSettings
|
||||
orgGetter organization.Getter
|
||||
analytics analytics.Analytics
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
func NewProviderFactory(store sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
||||
func NewProviderFactory(store sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter, analytics analytics.Analytics) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
||||
return factory.NewProviderFactory(factory.MustNewName("http"), func(ctx context.Context, providerSettings factory.ProviderSettings, config licensing.Config) (licensing.Licensing, error) {
|
||||
return New(ctx, providerSettings, config, store, zeus, orgGetter)
|
||||
return New(ctx, providerSettings, config, store, zeus, orgGetter, analytics)
|
||||
})
|
||||
}
|
||||
|
||||
func New(ctx context.Context, ps factory.ProviderSettings, config licensing.Config, sqlstore sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter) (licensing.Licensing, error) {
|
||||
func New(ctx context.Context, ps factory.ProviderSettings, config licensing.Config, sqlstore sqlstore.SQLStore, zeus zeus.Zeus, orgGetter organization.Getter, analytics analytics.Analytics) (licensing.Licensing, error) {
|
||||
settings := factory.NewScopedProviderSettings(ps, "github.com/SigNoz/signoz/ee/licensing/httplicensing")
|
||||
licensestore := sqllicensingstore.New(sqlstore)
|
||||
return &provider{
|
||||
@ -42,6 +45,7 @@ func New(ctx context.Context, ps factory.ProviderSettings, config licensing.Conf
|
||||
settings: settings,
|
||||
orgGetter: orgGetter,
|
||||
stopChan: make(chan struct{}),
|
||||
analytics: analytics,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -159,6 +163,25 @@ func (provider *provider) Refresh(ctx context.Context, organizationID valuer.UUI
|
||||
return err
|
||||
}
|
||||
|
||||
stats := licensetypes.NewStatsFromLicense(activeLicense)
|
||||
provider.analytics.Send(ctx,
|
||||
analyticstypes.Track{
|
||||
UserId: "stats_" + organizationID.String(),
|
||||
Event: "License Updated",
|
||||
Properties: analyticstypes.NewPropertiesFromMap(stats),
|
||||
Context: &analyticstypes.Context{
|
||||
Extra: map[string]interface{}{
|
||||
analyticstypes.KeyGroupID: organizationID.String(),
|
||||
},
|
||||
},
|
||||
},
|
||||
analyticstypes.Group{
|
||||
UserId: "stats_" + organizationID.String(),
|
||||
GroupId: organizationID.String(),
|
||||
Traits: analyticstypes.NewTraitsFromMap(stats),
|
||||
},
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/SigNoz/signoz/ee/sqlstore/postgressqlstore"
|
||||
"github.com/SigNoz/signoz/ee/zeus"
|
||||
"github.com/SigNoz/signoz/ee/zeus/httpzeus"
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
"github.com/SigNoz/signoz/pkg/config"
|
||||
"github.com/SigNoz/signoz/pkg/config/envprovider"
|
||||
"github.com/SigNoz/signoz/pkg/config/fileprovider"
|
||||
@ -134,8 +135,8 @@ func main() {
|
||||
zeus.Config(),
|
||||
httpzeus.NewProviderFactory(),
|
||||
licensing.Config(24*time.Hour, 3),
|
||||
func(sqlstore sqlstore.SQLStore, zeus pkgzeus.Zeus, orgGetter organization.Getter) factory.ProviderFactory[pkglicensing.Licensing, pkglicensing.Config] {
|
||||
return httplicensing.NewProviderFactory(sqlstore, zeus, orgGetter)
|
||||
func(sqlstore sqlstore.SQLStore, zeus pkgzeus.Zeus, orgGetter organization.Getter, analytics analytics.Analytics) factory.ProviderFactory[pkglicensing.Licensing, pkglicensing.Config] {
|
||||
return httplicensing.NewProviderFactory(sqlstore, zeus, orgGetter, analytics)
|
||||
},
|
||||
signoz.NewEmailingProviderFactories(),
|
||||
signoz.NewCacheProviderFactories(),
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
"github.com/SigNoz/signoz/pkg/config"
|
||||
"github.com/SigNoz/signoz/pkg/config/envprovider"
|
||||
"github.com/SigNoz/signoz/pkg/config/fileprovider"
|
||||
@ -122,7 +123,7 @@ func main() {
|
||||
zeus.Config{},
|
||||
noopzeus.NewProviderFactory(),
|
||||
licensing.Config{},
|
||||
func(_ sqlstore.SQLStore, _ zeus.Zeus, _ organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
||||
func(_ sqlstore.SQLStore, _ zeus.Zeus, _ organization.Getter, _ analytics.Analytics) factory.ProviderFactory[licensing.Licensing, licensing.Config] {
|
||||
return nooplicensing.NewFactory()
|
||||
},
|
||||
signoz.NewEmailingProviderFactories(),
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/alertmanager"
|
||||
"github.com/SigNoz/signoz/pkg/analytics"
|
||||
"github.com/SigNoz/signoz/pkg/cache"
|
||||
"github.com/SigNoz/signoz/pkg/emailing"
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
@ -54,7 +55,7 @@ func New(
|
||||
zeusConfig zeus.Config,
|
||||
zeusProviderFactory factory.ProviderFactory[zeus.Zeus, zeus.Config],
|
||||
licenseConfig licensing.Config,
|
||||
licenseProviderFactory func(sqlstore.SQLStore, zeus.Zeus, organization.Getter) factory.ProviderFactory[licensing.Licensing, licensing.Config],
|
||||
licenseProviderFactory func(sqlstore.SQLStore, zeus.Zeus, organization.Getter, analytics.Analytics) factory.ProviderFactory[licensing.Licensing, licensing.Config],
|
||||
emailingProviderFactories factory.NamedMap[factory.ProviderFactory[emailing.Emailing, emailing.Config]],
|
||||
cacheProviderFactories factory.NamedMap[factory.ProviderFactory[cache.Cache, cache.Config]],
|
||||
webProviderFactories factory.NamedMap[factory.ProviderFactory[web.Web, web.Config]],
|
||||
@ -235,7 +236,7 @@ func New(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
licensingProviderFactory := licenseProviderFactory(sqlstore, zeus, orgGetter)
|
||||
licensingProviderFactory := licenseProviderFactory(sqlstore, zeus, orgGetter, analytics)
|
||||
licensing, err := licensingProviderFactory.New(
|
||||
ctx,
|
||||
providerSettings,
|
||||
|
||||
@ -32,6 +32,8 @@ type License struct {
|
||||
PlanName valuer.String
|
||||
Features []*Feature
|
||||
Status valuer.String
|
||||
State string
|
||||
FreeUntil time.Time
|
||||
ValidFrom int64
|
||||
ValidUntil int64
|
||||
CreatedAt time.Time
|
||||
@ -165,6 +167,21 @@ func NewLicense(data []byte, organizationID valuer.UUID) (*License, error) {
|
||||
planName = PlanNameBasic
|
||||
}
|
||||
|
||||
state, err := extractKeyFromMapStringInterface[string](licenseData, "state")
|
||||
if err != nil {
|
||||
state = ""
|
||||
}
|
||||
|
||||
freeUntilStr, err := extractKeyFromMapStringInterface[string](licenseData, "free_until")
|
||||
if err != nil {
|
||||
freeUntilStr = ""
|
||||
}
|
||||
|
||||
freeUntil, err := time.Parse(time.RFC3339, freeUntilStr)
|
||||
if err != nil {
|
||||
freeUntil = time.Time{}
|
||||
}
|
||||
|
||||
featuresFromZeus := make([]*Feature, 0)
|
||||
if _features, ok := licenseData["features"]; ok {
|
||||
featuresData, err := json.Marshal(_features)
|
||||
@ -224,6 +241,8 @@ func NewLicense(data []byte, organizationID valuer.UUID) (*License, error) {
|
||||
ValidFrom: validFrom,
|
||||
ValidUntil: validUntil,
|
||||
Status: status,
|
||||
State: state,
|
||||
FreeUntil: freeUntil,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
LastValidatedAt: time.Now(),
|
||||
@ -306,6 +325,21 @@ func NewLicenseFromStorableLicense(storableLicense *StorableLicense) (*License,
|
||||
}
|
||||
validUntil := int64(_validUntil)
|
||||
|
||||
state, err := extractKeyFromMapStringInterface[string](storableLicense.Data, "state")
|
||||
if err != nil {
|
||||
state = ""
|
||||
}
|
||||
|
||||
freeUntilStr, err := extractKeyFromMapStringInterface[string](storableLicense.Data, "free_until")
|
||||
if err != nil {
|
||||
freeUntilStr = ""
|
||||
}
|
||||
|
||||
freeUntil, err := time.Parse(time.RFC3339, freeUntilStr)
|
||||
if err != nil {
|
||||
freeUntil = time.Time{}
|
||||
}
|
||||
|
||||
return &License{
|
||||
ID: storableLicense.ID,
|
||||
Key: storableLicense.Key,
|
||||
@ -315,6 +349,8 @@ func NewLicenseFromStorableLicense(storableLicense *StorableLicense) (*License,
|
||||
ValidFrom: validFrom,
|
||||
ValidUntil: validUntil,
|
||||
Status: status,
|
||||
State: state,
|
||||
FreeUntil: freeUntil,
|
||||
CreatedAt: storableLicense.CreatedAt,
|
||||
UpdatedAt: storableLicense.UpdatedAt,
|
||||
LastValidatedAt: storableLicense.LastValidatedAt,
|
||||
@ -325,8 +361,10 @@ 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(),
|
||||
"license.id": license.ID.StringValue(),
|
||||
"license.plan.name": license.PlanName.StringValue(),
|
||||
"license.state.name": license.State,
|
||||
"license.free_until.time": license.FreeUntil.UTC(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,7 @@ func TestNewLicenseV3(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Parse the entire license properly",
|
||||
data: []byte(`{"id":"0196f794-ff30-7bee-a5f4-ef5ad315715e","key":"does-not-matter-key","category":"FREE","status":"ACTIVE","plan":{"name":"ENTERPRISE"},"valid_from": 1730899309,"valid_until": -1}`),
|
||||
data: []byte(`{"id":"0196f794-ff30-7bee-a5f4-ef5ad315715e","key":"does-not-matter-key","category":"FREE","status":"ACTIVE","plan":{"name":"ENTERPRISE"},"valid_from": 1730899309,"valid_until": -1,"state":"test","free_until":"2025-05-16T11:17:48.124202Z"}`),
|
||||
pass: true,
|
||||
expected: &License{
|
||||
ID: valuer.MustNewUUID("0196f794-ff30-7bee-a5f4-ef5ad315715e"),
|
||||
@ -87,11 +87,15 @@ func TestNewLicenseV3(t *testing.T) {
|
||||
"status": "ACTIVE",
|
||||
"valid_from": float64(1730899309),
|
||||
"valid_until": float64(-1),
|
||||
"state": "test",
|
||||
"free_until": "2025-05-16T11:17:48.124202Z",
|
||||
},
|
||||
PlanName: PlanNameEnterprise,
|
||||
ValidFrom: 1730899309,
|
||||
ValidUntil: -1,
|
||||
Status: valuer.NewString("ACTIVE"),
|
||||
State: "test",
|
||||
FreeUntil: time.Date(2025, 5, 16, 11, 17, 48, 124202000, time.UTC),
|
||||
Features: make([]*Feature, 0),
|
||||
OrganizationID: valuer.MustNewUUID("0196f794-ff30-7bee-a5f4-ef5ad315715e"),
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user