mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-20 12:39:13 +08:00
feat: trace funnel state management
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
This commit is contained in:
parent
14ce7f80e2
commit
5e0d6110b5
@ -38,7 +38,9 @@ func (module *module) Create(ctx context.Context, timestamp int64, name string,
|
||||
|
||||
// Set up the user relationship
|
||||
funnel.CreatedByUser = &types.User{
|
||||
ID: userID,
|
||||
Identifiable: types.Identifiable{
|
||||
ID: valuer.MustNewUUID(userID),
|
||||
},
|
||||
}
|
||||
|
||||
if err := module.store.Create(ctx, funnel); err != nil {
|
||||
|
@ -32,7 +32,7 @@ func (store *store) Create(ctx context.Context, funnel *traceFunnels.Funnel) err
|
||||
|
||||
// Set created_by if CreatedByUser is present
|
||||
if funnel.CreatedByUser != nil {
|
||||
funnel.CreatedBy = funnel.CreatedByUser.ID
|
||||
funnel.CreatedBy = funnel.CreatedByUser.Identifiable.ID.String()
|
||||
}
|
||||
|
||||
_, err := store.
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
tracefunnel "github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
tracefunnel "github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -452,7 +452,7 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
},
|
||||
},
|
||||
CreatedByUser: &types.User{
|
||||
ID: "user-123",
|
||||
Identifiable: types.Identifiable{ID: valuer.MustNewUUID("user-123")},
|
||||
Email: "funnel@example.com",
|
||||
},
|
||||
Steps: []tracefunnel.FunnelStep{
|
||||
|
@ -87,7 +87,7 @@ func existsSubQueryForFixedColumn(key v3.AttributeKey, op v3.FilterOperator) (st
|
||||
}
|
||||
}
|
||||
|
||||
func buildTracesFilterQuery(fs *v3.FilterSet) (string, error) {
|
||||
func BuildTracesFilterQuery(fs *v3.FilterSet) (string, error) {
|
||||
var conditions []string
|
||||
|
||||
if fs != nil && len(fs.Items) != 0 {
|
||||
@ -167,7 +167,7 @@ func handleEmptyValuesInGroupBy(groupBy []v3.AttributeKey) (string, error) {
|
||||
Operator: "AND",
|
||||
Items: filterItems,
|
||||
}
|
||||
return buildTracesFilterQuery(&filterSet)
|
||||
return BuildTracesFilterQuery(&filterSet)
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
@ -248,7 +248,7 @@ func buildTracesQuery(start, end, step int64, mq *v3.BuilderQuery, panelType v3.
|
||||
|
||||
timeFilter := fmt.Sprintf("(timestamp >= '%d' AND timestamp <= '%d') AND (ts_bucket_start >= %d AND ts_bucket_start <= %d)", tracesStart, tracesEnd, bucketStart, bucketEnd)
|
||||
|
||||
filterSubQuery, err := buildTracesFilterQuery(mq.Filters)
|
||||
filterSubQuery, err := BuildTracesFilterQuery(mq.Filters)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ func Test_buildTracesFilterQuery(t *testing.T) {
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "Test buildTracesFilterQuery in, nin",
|
||||
name: "Test BuildTracesFilterQuery in, nin",
|
||||
args: args{
|
||||
fs: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||
{Key: v3.AttributeKey{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}, Value: []interface{}{"GET", "POST"}, Operator: v3.FilterOperatorIn},
|
||||
@ -226,7 +226,7 @@ func Test_buildTracesFilterQuery(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Test buildTracesFilterQuery not eq, neq, gt, lt, gte, lte",
|
||||
name: "Test BuildTracesFilterQuery not eq, neq, gt, lt, gte, lte",
|
||||
args: args{
|
||||
fs: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{
|
||||
{Key: v3.AttributeKey{Key: "duration", DataType: v3.AttributeKeyDataTypeInt64, Type: v3.AttributeKeyTypeTag}, Value: 102, Operator: v3.FilterOperatorEqual},
|
||||
@ -274,13 +274,13 @@ func Test_buildTracesFilterQuery(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := buildTracesFilterQuery(tt.args.fs)
|
||||
got, err := BuildTracesFilterQuery(tt.args.fs)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("buildTracesFilterQuery() error = %v, wantErr %v", err, tt.wantErr)
|
||||
t.Errorf("BuildTracesFilterQuery() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("buildTracesFilterQuery() = %v, want %v", got, tt.want)
|
||||
t.Errorf("BuildTracesFilterQuery() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/quickfilter/implquickfilter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview/implsavedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel/impltracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user/impluser"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
|
||||
@ -23,6 +25,7 @@ type Handlers struct {
|
||||
Organization organization.Handler
|
||||
Preference preference.Handler
|
||||
User user.Handler
|
||||
TraceFunnel tracefunnel.Handler
|
||||
SavedView savedview.Handler
|
||||
Apdex apdex.Handler
|
||||
Dashboard dashboard.Handler
|
||||
|
@ -16,10 +16,10 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/modules/quickfilter/implquickfilter"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/savedview/implsavedview"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user/impluser"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/modules/tracefunnel/impltracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user"
|
||||
"github.com/SigNoz/signoz/pkg/modules/user/impluser"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/preferencetypes"
|
||||
|
@ -83,6 +83,7 @@ func NewSQLMigrationProviderFactories(sqlstore sqlstore.SQLStore) factory.NamedM
|
||||
sqlmigration.NewDropGroupsFactory(sqlstore),
|
||||
sqlmigration.NewCreateQuickFiltersFactory(sqlstore),
|
||||
sqlmigration.NewUpdateQuickFiltersFactory(sqlstore),
|
||||
sqlmigration.NewAddTraceFunnelsFactory(sqlstore),
|
||||
sqlmigration.NewAuthRefactorFactory(sqlstore),
|
||||
sqlmigration.NewUpdateLicenseFactory(sqlstore),
|
||||
sqlmigration.NewMigratePATToFactorAPIKey(sqlstore),
|
||||
|
114
pkg/sqlmigration/050_add_trace_funnels.go
Normal file
114
pkg/sqlmigration/050_add_trace_funnels.go
Normal file
@ -0,0 +1,114 @@
|
||||
package sqlmigration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
traceFunnels "github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
)
|
||||
|
||||
type addTraceFunnels struct {
|
||||
sqlstore sqlstore.SQLStore
|
||||
}
|
||||
|
||||
func NewAddTraceFunnelsFactory(sqlstore sqlstore.SQLStore) factory.ProviderFactory[SQLMigration, Config] {
|
||||
return factory.
|
||||
NewProviderFactory(factory.
|
||||
MustNewName("add_trace_funnels"),
|
||||
func(ctx context.Context, providerSettings factory.ProviderSettings, config Config) (SQLMigration, error) {
|
||||
return newAddTraceFunnels(ctx, providerSettings, config, sqlstore)
|
||||
})
|
||||
}
|
||||
|
||||
func newAddTraceFunnels(_ context.Context, _ factory.ProviderSettings, _ Config, sqlstore sqlstore.SQLStore) (SQLMigration, error) {
|
||||
return &addTraceFunnels{sqlstore: sqlstore}, nil
|
||||
}
|
||||
|
||||
func (migration *addTraceFunnels) Register(migrations *migrate.Migrations) error {
|
||||
if err := migrations.
|
||||
Register(migration.Up, migration.Down); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (migration *addTraceFunnels) Up(ctx context.Context, db *bun.DB) error {
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
// Create trace_funnel table with foreign key constraint inline
|
||||
_, err = tx.NewCreateTable().
|
||||
Model((*traceFunnels.Funnel)(nil)).
|
||||
ForeignKey(`("org_id") REFERENCES "organizations" ("id") ON DELETE CASCADE`).
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create trace_funnel table: %v", err)
|
||||
}
|
||||
|
||||
// Add unique constraint for org_id and name
|
||||
//_, err = tx.NewRaw(`
|
||||
// CREATE UNIQUE INDEX IF NOT EXISTS idx_trace_funnel_org_id_name
|
||||
// ON trace_funnel (org_id, name)
|
||||
//`).Exec(ctx)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("failed to create unique constraint: %v", err)
|
||||
//}
|
||||
|
||||
// Create indexes
|
||||
_, err = tx.NewCreateIndex().
|
||||
Model((*traceFunnels.Funnel)(nil)).
|
||||
Index("idx_trace_funnel_org_id").
|
||||
Column("org_id").
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create org_id index: %v", err)
|
||||
}
|
||||
|
||||
_, err = tx.NewCreateIndex().
|
||||
Model((*traceFunnels.Funnel)(nil)).
|
||||
Index("idx_trace_funnel_created_at").
|
||||
Column("created_at").
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create created_at index: %v", err)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (migration *addTraceFunnels) Down(ctx context.Context, db *bun.DB) error {
|
||||
//tx, err := db.BeginTx(ctx, nil)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//defer tx.Rollback()
|
||||
//
|
||||
//// Drop trace_funnel table
|
||||
//_, err = tx.NewDropTable().
|
||||
// Model((*traceFunnels.Funnel)(nil)).
|
||||
// IfExists().
|
||||
// Exec(ctx)
|
||||
//if err != nil {
|
||||
// return fmt.Errorf("failed to drop trace_funnel table: %v", err)
|
||||
//}
|
||||
//
|
||||
//if err := tx.Commit(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
return nil
|
||||
}
|
@ -84,8 +84,8 @@ type TimeRange struct {
|
||||
// StepTransitionRequest represents a request for step transition analytics
|
||||
type StepTransitionRequest struct {
|
||||
TimeRange
|
||||
StepAOrder int64 `json:"step_a_order"`
|
||||
StepBOrder int64 `json:"step_b_order"`
|
||||
StepAOrder int64 `json:"step_start,omitempty"`
|
||||
StepBOrder int64 `json:"step_end,omitempty"`
|
||||
}
|
||||
|
||||
// UserInfo represents basic user information
|
||||
|
Loading…
x
Reference in New Issue
Block a user