mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-16 16:16:01 +08:00
fix: review comments
Signed-off-by: Shivanshu Raj Shrivastava <shivanshu1333@gmail.com>
This commit is contained in:
parent
ea1f4e8253
commit
78a5d7e39e
@ -21,13 +21,13 @@ func NewHandler(module tracefunnel.Module) tracefunnel.Handler {
|
||||
}
|
||||
|
||||
func (handler *handler) New(rw http.ResponseWriter, r *http.Request) {
|
||||
var req tf.FunnelRequest
|
||||
var req tf.PostableFunnel
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := tracefunnel.GetClaims(r)
|
||||
claims, err := tf.GetClaims(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -41,24 +41,24 @@ func (handler *handler) New(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
response := tracefunnel.ConstructFunnelResponse(funnel, claims)
|
||||
response := tf.ConstructFunnelResponse(funnel, claims)
|
||||
render.Success(rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateSteps(rw http.ResponseWriter, r *http.Request) {
|
||||
var req tf.FunnelRequest
|
||||
var req tf.PostableFunnel
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := tracefunnel.GetClaims(r)
|
||||
claims, err := tf.GetClaims(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
updatedAt, err := tracefunnel.ValidateAndConvertTimestamp(req.Timestamp)
|
||||
updatedAt, err := tf.ValidateAndConvertTimestamp(req.Timestamp)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -72,7 +72,7 @@ func (handler *handler) UpdateSteps(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
steps, err := tracefunnel.ProcessFunnelSteps(req.Steps)
|
||||
steps, err := tf.ProcessFunnelSteps(req.Steps)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -104,24 +104,24 @@ func (handler *handler) UpdateSteps(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
response := tracefunnel.ConstructFunnelResponse(updatedFunnel, claims)
|
||||
response := tf.ConstructFunnelResponse(updatedFunnel, claims)
|
||||
render.Success(rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (handler *handler) UpdateFunnel(rw http.ResponseWriter, r *http.Request) {
|
||||
var req tf.FunnelRequest
|
||||
var req tf.PostableFunnel
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := tracefunnel.GetClaims(r)
|
||||
claims, err := tf.GetClaims(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
updatedAt, err := tracefunnel.ValidateAndConvertTimestamp(req.Timestamp)
|
||||
updatedAt, err := tf.ValidateAndConvertTimestamp(req.Timestamp)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -163,12 +163,12 @@ func (handler *handler) UpdateFunnel(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
response := tracefunnel.ConstructFunnelResponse(updatedFunnel, claims)
|
||||
response := tf.ConstructFunnelResponse(updatedFunnel, claims)
|
||||
render.Success(rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (handler *handler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
claims, err := tracefunnel.GetClaims(r)
|
||||
claims, err := tf.GetClaims(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -182,9 +182,9 @@ func (handler *handler) List(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var response []tf.FunnelResponse
|
||||
var response []tf.GettableFunnel
|
||||
for _, f := range funnels {
|
||||
response = append(response, tracefunnel.ConstructFunnelResponse(f, claims))
|
||||
response = append(response, tf.ConstructFunnelResponse(f, claims))
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, response)
|
||||
@ -202,8 +202,8 @@ func (handler *handler) Get(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
claims, _ := tracefunnel.GetClaims(r) // Ignore error as email is optional
|
||||
response := tracefunnel.ConstructFunnelResponse(funnel, claims)
|
||||
claims, _ := tf.GetClaims(r) // Ignore error as email is optional
|
||||
response := tf.ConstructFunnelResponse(funnel, claims)
|
||||
render.Success(rw, http.StatusOK, response)
|
||||
}
|
||||
|
||||
@ -222,7 +222,7 @@ func (handler *handler) Delete(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (handler *handler) Save(rw http.ResponseWriter, r *http.Request) {
|
||||
var req tf.FunnelRequest
|
||||
var req tf.PostableFunnel
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput,
|
||||
errors.CodeInvalidInput,
|
||||
@ -230,7 +230,7 @@ func (handler *handler) Save(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := tracefunnel.GetClaims(r)
|
||||
claims, err := tf.GetClaims(r)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -247,14 +247,14 @@ func (handler *handler) Save(rw http.ResponseWriter, r *http.Request) {
|
||||
updateTimestamp := req.Timestamp
|
||||
if updateTimestamp == 0 {
|
||||
updateTimestamp = time.Now().UnixMilli()
|
||||
} else if !tracefunnel.ValidateTimestampIsMilliseconds(updateTimestamp) {
|
||||
} else if !tf.ValidateTimestampIsMilliseconds(updateTimestamp) {
|
||||
render.Error(rw, errors.Newf(errors.TypeInvalidInput,
|
||||
errors.CodeInvalidInput,
|
||||
"timestamp must be in milliseconds format (13 digits)"))
|
||||
return
|
||||
}
|
||||
|
||||
updatedAt, err := tracefunnel.ValidateAndConvertTimestamp(updateTimestamp)
|
||||
updatedAt, err := tf.ValidateAndConvertTimestamp(updateTimestamp)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
@ -279,7 +279,7 @@ func (handler *handler) Save(rw http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
resp := tf.FunnelResponse{
|
||||
resp := tf.GettableFunnel{
|
||||
FunnelName: funnel.Name,
|
||||
CreatedAt: createdAtMillis,
|
||||
UpdatedAt: updatedAtMillis,
|
||||
|
@ -22,24 +22,24 @@ type MockModule struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MockModule) Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.Funnel, error) {
|
||||
func (m *MockModule) Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.StorableFunnel, error) {
|
||||
args := m.Called(ctx, timestamp, name, userID, orgID)
|
||||
return args.Get(0).(*traceFunnels.Funnel), args.Error(1)
|
||||
return args.Get(0).(*traceFunnels.StorableFunnel), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockModule) Get(ctx context.Context, funnelID string) (*traceFunnels.Funnel, error) {
|
||||
func (m *MockModule) Get(ctx context.Context, funnelID string) (*traceFunnels.StorableFunnel, error) {
|
||||
args := m.Called(ctx, funnelID)
|
||||
return args.Get(0).(*traceFunnels.Funnel), args.Error(1)
|
||||
return args.Get(0).(*traceFunnels.StorableFunnel), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockModule) Update(ctx context.Context, funnel *traceFunnels.Funnel, userID string) error {
|
||||
func (m *MockModule) Update(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string) error {
|
||||
args := m.Called(ctx, funnel, userID)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockModule) List(ctx context.Context, orgID string) ([]*traceFunnels.Funnel, error) {
|
||||
func (m *MockModule) List(ctx context.Context, orgID string) ([]*traceFunnels.StorableFunnel, error) {
|
||||
args := m.Called(ctx, orgID)
|
||||
return args.Get(0).([]*traceFunnels.Funnel), args.Error(1)
|
||||
return args.Get(0).([]*traceFunnels.StorableFunnel), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockModule) Delete(ctx context.Context, funnelID string) error {
|
||||
@ -47,7 +47,7 @@ func (m *MockModule) Delete(ctx context.Context, funnelID string) error {
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockModule) Save(ctx context.Context, funnel *traceFunnels.Funnel, userID string, orgID string) error {
|
||||
func (m *MockModule) Save(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string, orgID string) error {
|
||||
args := m.Called(ctx, funnel, userID, orgID)
|
||||
return args.Error(0)
|
||||
}
|
||||
@ -61,7 +61,7 @@ func TestHandler_New(t *testing.T) {
|
||||
mockModule := new(MockModule)
|
||||
handler := NewHandler(mockModule)
|
||||
|
||||
reqBody := traceFunnels.FunnelRequest{
|
||||
reqBody := traceFunnels.PostableFunnel{
|
||||
Name: "test-funnel",
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}
|
||||
@ -81,7 +81,7 @@ func TestHandler_New(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
funnelID := valuer.GenerateUUID()
|
||||
expectedFunnel := &traceFunnels.Funnel{
|
||||
expectedFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
@ -91,7 +91,7 @@ func TestHandler_New(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
mockModule.On("List", req.Context(), orgID).Return([]*traceFunnels.Funnel{}, nil)
|
||||
mockModule.On("List", req.Context(), orgID).Return([]*traceFunnels.StorableFunnel{}, nil)
|
||||
mockModule.On("Create", req.Context(), reqBody.Timestamp, reqBody.Name, "user-123", orgID).Return(expectedFunnel, nil)
|
||||
|
||||
handler.New(rr, req)
|
||||
@ -100,7 +100,7 @@ func TestHandler_New(t *testing.T) {
|
||||
|
||||
var response struct {
|
||||
Status string `json:"status"`
|
||||
Data traceFunnels.FunnelResponse `json:"data"`
|
||||
Data traceFunnels.GettableFunnel `json:"data"`
|
||||
}
|
||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
@ -120,10 +120,10 @@ func TestHandler_Update(t *testing.T) {
|
||||
funnelID := valuer.GenerateUUID()
|
||||
orgID := valuer.GenerateUUID().String()
|
||||
|
||||
reqBody := traceFunnels.FunnelRequest{
|
||||
reqBody := traceFunnels.PostableFunnel{
|
||||
FunnelID: funnelID,
|
||||
Name: "updated-funnel",
|
||||
Steps: []traceFunnels.FunnelStep{
|
||||
Steps: []*traceFunnels.FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -161,7 +161,7 @@ func TestHandler_Update(t *testing.T) {
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// Set up mock expectations
|
||||
existingFunnel := &traceFunnels.Funnel{
|
||||
existingFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
@ -183,7 +183,7 @@ func TestHandler_Update(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
updatedFunnel := &traceFunnels.Funnel{
|
||||
updatedFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
@ -209,9 +209,9 @@ func TestHandler_Update(t *testing.T) {
|
||||
// First Get call to validate the funnel exists
|
||||
mockModule.On("Get", req.Context(), funnelID.String()).Return(existingFunnel, nil).Once()
|
||||
// List call to check for name conflicts
|
||||
mockModule.On("List", req.Context(), orgID).Return([]*traceFunnels.Funnel{}, nil).Once()
|
||||
mockModule.On("List", req.Context(), orgID).Return([]*traceFunnels.StorableFunnel{}, nil).Once()
|
||||
// Update call to save the changes
|
||||
mockModule.On("Update", req.Context(), mock.MatchedBy(func(f *traceFunnels.Funnel) bool {
|
||||
mockModule.On("Update", req.Context(), mock.MatchedBy(func(f *traceFunnels.StorableFunnel) bool {
|
||||
return f.Name == reqBody.Name &&
|
||||
f.ID.String() == funnelID.String() &&
|
||||
len(f.Steps) == len(reqBody.Steps) &&
|
||||
@ -233,7 +233,7 @@ func TestHandler_Update(t *testing.T) {
|
||||
|
||||
var response struct {
|
||||
Status string `json:"status"`
|
||||
Data traceFunnels.FunnelResponse `json:"data"`
|
||||
Data traceFunnels.GettableFunnel `json:"data"`
|
||||
}
|
||||
err = json.Unmarshal(rr.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
@ -261,7 +261,7 @@ func TestHandler_List(t *testing.T) {
|
||||
|
||||
funnel1ID := valuer.GenerateUUID()
|
||||
funnel2ID := valuer.GenerateUUID()
|
||||
expectedFunnels := []*traceFunnels.Funnel{
|
||||
expectedFunnels := []*traceFunnels.StorableFunnel{
|
||||
{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
@ -290,7 +290,7 @@ func TestHandler_List(t *testing.T) {
|
||||
|
||||
var response struct {
|
||||
Status string `json:"status"`
|
||||
Data []traceFunnels.FunnelResponse `json:"data"`
|
||||
Data []traceFunnels.GettableFunnel `json:"data"`
|
||||
}
|
||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
@ -312,7 +312,7 @@ func TestHandler_Get(t *testing.T) {
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
expectedFunnel := &traceFunnels.Funnel{
|
||||
expectedFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
@ -330,7 +330,7 @@ func TestHandler_Get(t *testing.T) {
|
||||
|
||||
var response struct {
|
||||
Status string `json:"status"`
|
||||
Data traceFunnels.FunnelResponse `json:"data"`
|
||||
Data traceFunnels.GettableFunnel `json:"data"`
|
||||
}
|
||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
@ -364,7 +364,7 @@ func TestHandler_Save(t *testing.T) {
|
||||
mockModule := new(MockModule)
|
||||
handler := NewHandler(mockModule)
|
||||
|
||||
reqBody := traceFunnels.FunnelRequest{
|
||||
reqBody := traceFunnels.PostableFunnel{
|
||||
FunnelID: valuer.GenerateUUID(),
|
||||
Description: "updated description",
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
@ -384,7 +384,7 @@ func TestHandler_Save(t *testing.T) {
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
existingFunnel := &traceFunnels.Funnel{
|
||||
existingFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: reqBody.FunnelID,
|
||||
@ -395,7 +395,7 @@ func TestHandler_Save(t *testing.T) {
|
||||
}
|
||||
|
||||
mockModule.On("Get", req.Context(), reqBody.FunnelID.String()).Return(existingFunnel, nil)
|
||||
mockModule.On("Save", req.Context(), mock.MatchedBy(func(f *traceFunnels.Funnel) bool {
|
||||
mockModule.On("Save", req.Context(), mock.MatchedBy(func(f *traceFunnels.StorableFunnel) bool {
|
||||
return f.ID.String() == reqBody.FunnelID.String() &&
|
||||
f.Name == existingFunnel.Name &&
|
||||
f.Description == reqBody.Description &&
|
||||
@ -410,7 +410,7 @@ func TestHandler_Save(t *testing.T) {
|
||||
|
||||
var response struct {
|
||||
Status string `json:"status"`
|
||||
Data traceFunnels.FunnelResponse `json:"data"`
|
||||
Data traceFunnels.GettableFunnel `json:"data"`
|
||||
}
|
||||
err := json.Unmarshal(rr.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
|
@ -21,13 +21,13 @@ func NewModule(store traceFunnels.FunnelStore) tracefunnel.Module {
|
||||
}
|
||||
}
|
||||
|
||||
func (module *module) Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.Funnel, error) {
|
||||
func (module *module) Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.StorableFunnel, error) {
|
||||
orgUUID, err := valuer.NewUUID(orgID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid org ID: %v", err)
|
||||
}
|
||||
|
||||
funnel := &traceFunnels.Funnel{
|
||||
funnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Name: name,
|
||||
OrgID: orgUUID,
|
||||
@ -43,6 +43,22 @@ func (module *module) Create(ctx context.Context, timestamp int64, name string,
|
||||
},
|
||||
}
|
||||
|
||||
if funnel.ID.IsZero() {
|
||||
funnel.ID = valuer.GenerateUUID()
|
||||
}
|
||||
|
||||
if funnel.CreatedAt.IsZero() {
|
||||
funnel.CreatedAt = time.Now()
|
||||
}
|
||||
if funnel.UpdatedAt.IsZero() {
|
||||
funnel.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
// Set created_by if CreatedByUser is present
|
||||
if funnel.CreatedByUser != nil {
|
||||
funnel.CreatedBy = funnel.CreatedByUser.Identifiable.ID.String()
|
||||
}
|
||||
|
||||
if err := module.store.Create(ctx, funnel); err != nil {
|
||||
return nil, fmt.Errorf("failed to create funnel: %v", err)
|
||||
}
|
||||
@ -51,7 +67,7 @@ func (module *module) Create(ctx context.Context, timestamp int64, name string,
|
||||
}
|
||||
|
||||
// Get gets a funnel by ID
|
||||
func (module *module) Get(ctx context.Context, funnelID string) (*traceFunnels.Funnel, error) {
|
||||
func (module *module) Get(ctx context.Context, funnelID string) (*traceFunnels.StorableFunnel, error) {
|
||||
uuid, err := valuer.NewUUID(funnelID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid funnel ID: %v", err)
|
||||
@ -60,13 +76,13 @@ func (module *module) Get(ctx context.Context, funnelID string) (*traceFunnels.F
|
||||
}
|
||||
|
||||
// Update updates a funnel
|
||||
func (module *module) Update(ctx context.Context, funnel *traceFunnels.Funnel, userID string) error {
|
||||
func (module *module) Update(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string) error {
|
||||
funnel.UpdatedBy = userID
|
||||
return module.store.Update(ctx, funnel)
|
||||
}
|
||||
|
||||
// List lists all funnels for an organization
|
||||
func (module *module) List(ctx context.Context, orgID string) ([]*traceFunnels.Funnel, error) {
|
||||
func (module *module) List(ctx context.Context, orgID string) ([]*traceFunnels.StorableFunnel, error) {
|
||||
orgUUID, err := valuer.NewUUID(orgID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid org ID: %v", err)
|
||||
@ -90,7 +106,7 @@ func (module *module) Delete(ctx context.Context, funnelID string) error {
|
||||
}
|
||||
|
||||
// Save saves a funnel
|
||||
func (module *module) Save(ctx context.Context, funnel *traceFunnels.Funnel, userID string, orgID string) error {
|
||||
func (module *module) Save(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string, orgID string) error {
|
||||
orgUUID, err := valuer.NewUUID(orgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid org ID: %v", err)
|
||||
|
@ -18,23 +18,7 @@ func NewStore(sqlstore sqlstore.SQLStore) traceFunnels.FunnelStore {
|
||||
return &store{sqlstore: sqlstore}
|
||||
}
|
||||
|
||||
func (store *store) Create(ctx context.Context, funnel *traceFunnels.Funnel) error {
|
||||
if funnel.ID.IsZero() {
|
||||
funnel.ID = valuer.GenerateUUID()
|
||||
}
|
||||
|
||||
if funnel.CreatedAt.IsZero() {
|
||||
funnel.CreatedAt = time.Now()
|
||||
}
|
||||
if funnel.UpdatedAt.IsZero() {
|
||||
funnel.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
// Set created_by if CreatedByUser is present
|
||||
if funnel.CreatedByUser != nil {
|
||||
funnel.CreatedBy = funnel.CreatedByUser.Identifiable.ID.String()
|
||||
}
|
||||
|
||||
func (store *store) Create(ctx context.Context, funnel *traceFunnels.StorableFunnel) error {
|
||||
_, err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
@ -49,8 +33,8 @@ func (store *store) Create(ctx context.Context, funnel *traceFunnels.Funnel) err
|
||||
}
|
||||
|
||||
// Get retrieves a funnel by ID
|
||||
func (store *store) Get(ctx context.Context, uuid valuer.UUID) (*traceFunnels.Funnel, error) {
|
||||
funnel := &traceFunnels.Funnel{}
|
||||
func (store *store) Get(ctx context.Context, uuid valuer.UUID) (*traceFunnels.StorableFunnel, error) {
|
||||
funnel := &traceFunnels.StorableFunnel{}
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
@ -66,7 +50,7 @@ func (store *store) Get(ctx context.Context, uuid valuer.UUID) (*traceFunnels.Fu
|
||||
}
|
||||
|
||||
// Update updates an existing funnel
|
||||
func (store *store) Update(ctx context.Context, funnel *traceFunnels.Funnel) error {
|
||||
func (store *store) Update(ctx context.Context, funnel *traceFunnels.StorableFunnel) error {
|
||||
funnel.UpdatedAt = time.Now()
|
||||
|
||||
_, err := store.
|
||||
@ -83,8 +67,8 @@ func (store *store) Update(ctx context.Context, funnel *traceFunnels.Funnel) err
|
||||
}
|
||||
|
||||
// List retrieves all funnels for a given organization
|
||||
func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*traceFunnels.Funnel, error) {
|
||||
var funnels []*traceFunnels.Funnel
|
||||
func (store *store) List(ctx context.Context, orgID valuer.UUID) ([]*traceFunnels.StorableFunnel, error) {
|
||||
var funnels []*traceFunnels.StorableFunnel
|
||||
err := store.
|
||||
sqlstore.
|
||||
BunDB().
|
||||
@ -105,7 +89,7 @@ func (store *store) Delete(ctx context.Context, uuid valuer.UUID) error {
|
||||
sqlstore.
|
||||
BunDB().
|
||||
NewDelete().
|
||||
Model((*traceFunnels.Funnel)(nil)).
|
||||
Model((*traceFunnels.StorableFunnel)(nil)).
|
||||
Where("id = ?", uuid).Exec(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete funnel: %v", err)
|
||||
|
@ -9,17 +9,17 @@ import (
|
||||
|
||||
// Module defines the interface for trace funnel operations
|
||||
type Module interface {
|
||||
Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.Funnel, error)
|
||||
Create(ctx context.Context, timestamp int64, name string, userID string, orgID string) (*traceFunnels.StorableFunnel, error)
|
||||
|
||||
Get(ctx context.Context, funnelID string) (*traceFunnels.Funnel, error)
|
||||
Get(ctx context.Context, funnelID string) (*traceFunnels.StorableFunnel, error)
|
||||
|
||||
Update(ctx context.Context, funnel *traceFunnels.Funnel, userID string) error
|
||||
Update(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string) error
|
||||
|
||||
List(ctx context.Context, orgID string) ([]*traceFunnels.Funnel, error)
|
||||
List(ctx context.Context, orgID string) ([]*traceFunnels.StorableFunnel, error)
|
||||
|
||||
Delete(ctx context.Context, funnelID string) error
|
||||
|
||||
Save(ctx context.Context, funnel *traceFunnels.Funnel, userID string, orgID string) error
|
||||
Save(ctx context.Context, funnel *traceFunnels.StorableFunnel, userID string, orgID string) error
|
||||
|
||||
GetFunnelMetadata(ctx context.Context, funnelID string) (int64, int64, string, error)
|
||||
}
|
||||
|
@ -17,22 +17,22 @@ type MockStore struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MockStore) Create(ctx context.Context, funnel *traceFunnels.Funnel) error {
|
||||
func (m *MockStore) Create(ctx context.Context, funnel *traceFunnels.StorableFunnel) error {
|
||||
args := m.Called(ctx, funnel)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (m *MockStore) Get(ctx context.Context, uuid valuer.UUID) (*traceFunnels.Funnel, error) {
|
||||
func (m *MockStore) Get(ctx context.Context, uuid valuer.UUID) (*traceFunnels.StorableFunnel, error) {
|
||||
args := m.Called(ctx, uuid)
|
||||
return args.Get(0).(*traceFunnels.Funnel), args.Error(1)
|
||||
return args.Get(0).(*traceFunnels.StorableFunnel), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockStore) List(ctx context.Context, orgID valuer.UUID) ([]*traceFunnels.Funnel, error) {
|
||||
func (m *MockStore) List(ctx context.Context, orgID valuer.UUID) ([]*traceFunnels.StorableFunnel, error) {
|
||||
args := m.Called(ctx, orgID)
|
||||
return args.Get(0).([]*traceFunnels.Funnel), args.Error(1)
|
||||
return args.Get(0).([]*traceFunnels.StorableFunnel), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockStore) Update(ctx context.Context, funnel *traceFunnels.Funnel) error {
|
||||
func (m *MockStore) Update(ctx context.Context, funnel *traceFunnels.StorableFunnel) error {
|
||||
args := m.Called(ctx, funnel)
|
||||
return args.Error(0)
|
||||
}
|
||||
@ -52,7 +52,7 @@ func TestModule_Create(t *testing.T) {
|
||||
userID := valuer.GenerateUUID()
|
||||
orgID := valuer.GenerateUUID().String()
|
||||
|
||||
mockStore.On("Create", ctx, mock.MatchedBy(func(f *traceFunnels.Funnel) bool {
|
||||
mockStore.On("Create", ctx, mock.MatchedBy(func(f *traceFunnels.StorableFunnel) bool {
|
||||
return f.Name == name &&
|
||||
f.CreatedBy == userID.String() &&
|
||||
f.OrgID.String() == orgID &&
|
||||
@ -79,7 +79,7 @@ func TestModule_Get(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
funnelID := valuer.GenerateUUID().String()
|
||||
expectedFunnel := &traceFunnels.Funnel{
|
||||
expectedFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Name: "test-funnel",
|
||||
},
|
||||
@ -100,7 +100,7 @@ func TestModule_Update(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
userID := "user-123"
|
||||
funnel := &traceFunnels.Funnel{
|
||||
funnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Name: "test-funnel",
|
||||
},
|
||||
@ -122,7 +122,7 @@ func TestModule_List(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
orgID := valuer.GenerateUUID().String()
|
||||
orgUUID := valuer.MustNewUUID(orgID)
|
||||
expectedFunnels := []*traceFunnels.Funnel{
|
||||
expectedFunnels := []*traceFunnels.StorableFunnel{
|
||||
{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Name: "funnel-1",
|
||||
@ -169,7 +169,7 @@ func TestModule_Save(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
userID := "user-123"
|
||||
orgID := valuer.GenerateUUID().String()
|
||||
funnel := &traceFunnels.Funnel{
|
||||
funnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Name: "test-funnel",
|
||||
},
|
||||
@ -192,7 +192,7 @@ func TestModule_GetFunnelMetadata(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
funnelID := valuer.GenerateUUID().String()
|
||||
now := time.Now()
|
||||
expectedFunnel := &traceFunnels.Funnel{
|
||||
expectedFunnel := &traceFunnels.StorableFunnel{
|
||||
BaseMetadata: traceFunnels.BaseMetadata{
|
||||
Description: "test description",
|
||||
TimeAuditable: types.TimeAuditable{
|
||||
|
@ -1,111 +0,0 @@
|
||||
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").
|
||||
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").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
|
||||
}
|
@ -3,25 +3,54 @@ package sqlmigration
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
||||
"github.com/SigNoz/signoz/pkg/sqlstore"
|
||||
traceFunnels "github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/migrate"
|
||||
)
|
||||
|
||||
type BaseMetadata struct {
|
||||
types.Identifiable // funnel id
|
||||
types.TimeAuditable
|
||||
types.UserAuditable
|
||||
Name string `json:"funnel_name" bun:"name,type:text,notnull"` // funnel name
|
||||
Description string `json:"description" bun:"description,type:text"` // funnel description
|
||||
OrgID valuer.UUID `json:"org_id" bun:"org_id,type:varchar,notnull"`
|
||||
}
|
||||
|
||||
// Funnel Core Data Structure (Funnel and FunnelStep)
|
||||
type Funnel struct {
|
||||
bun.BaseModel `bun:"table:trace_funnel"`
|
||||
BaseMetadata
|
||||
Steps []FunnelStep `json:"steps" bun:"steps,type:text,notnull"`
|
||||
Tags string `json:"tags" bun:"tags,type:text"`
|
||||
CreatedByUser *types.User `json:"user" bun:"rel:belongs-to,join:created_by=id"`
|
||||
}
|
||||
|
||||
type FunnelStep struct {
|
||||
ID valuer.UUID `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"` // step name
|
||||
Description string `json:"description,omitempty"` // step description
|
||||
Order int64 `json:"step_order"`
|
||||
ServiceName string `json:"service_name"`
|
||||
SpanName string `json:"span_name"`
|
||||
Filters *v3.FilterSet `json:"filters,omitempty"`
|
||||
LatencyPointer string `json:"latency_pointer,omitempty"`
|
||||
LatencyType string `json:"latency_type,omitempty"`
|
||||
HasErrors bool `json:"has_errors"`
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
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) {
|
||||
@ -29,8 +58,7 @@ func newAddTraceFunnels(_ context.Context, _ factory.ProviderSettings, _ Config,
|
||||
}
|
||||
|
||||
func (migration *addTraceFunnels) Register(migrations *migrate.Migrations) error {
|
||||
if err := migrations.
|
||||
Register(migration.Up, migration.Down); err != nil {
|
||||
if err := migrations.Register(migration.Up, migration.Down); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -43,9 +71,8 @@ func (migration *addTraceFunnels) Up(ctx context.Context, db *bun.DB) error {
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
// Create trace_funnel table with foreign key constraint inline
|
||||
_, err = tx.NewCreateTable().
|
||||
Model((*traceFunnels.Funnel)(nil)).
|
||||
Model((*Funnel)(nil)).
|
||||
ForeignKey(`("org_id") REFERENCES "organizations" ("id") ON DELETE CASCADE`).
|
||||
IfNotExists().
|
||||
Exec(ctx)
|
||||
@ -53,62 +80,9 @@ func (migration *addTraceFunnels) Up(ctx context.Context, db *bun.DB) error {
|
||||
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
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
)
|
||||
|
||||
type FunnelStore interface {
|
||||
Create(context.Context, *Funnel) error
|
||||
Get(context.Context, valuer.UUID) (*Funnel, error)
|
||||
List(context.Context, valuer.UUID) ([]*Funnel, error)
|
||||
Update(context.Context, *Funnel) error
|
||||
Create(context.Context, *StorableFunnel) error
|
||||
Get(context.Context, valuer.UUID) (*StorableFunnel, error)
|
||||
List(context.Context, valuer.UUID) ([]*StorableFunnel, error)
|
||||
Update(context.Context, *StorableFunnel) error
|
||||
Delete(context.Context, valuer.UUID) error
|
||||
}
|
||||
|
@ -22,13 +22,13 @@ type BaseMetadata struct {
|
||||
OrgID valuer.UUID `json:"org_id" bun:"org_id,type:varchar,notnull"`
|
||||
}
|
||||
|
||||
// Funnel Core Data Structure (Funnel and FunnelStep)
|
||||
type Funnel struct {
|
||||
// StorableFunnel Core Data Structure (StorableFunnel and FunnelStep)
|
||||
type StorableFunnel struct {
|
||||
bun.BaseModel `bun:"table:trace_funnel"`
|
||||
BaseMetadata
|
||||
Steps []FunnelStep `json:"steps" bun:"steps,type:text,notnull"`
|
||||
Tags string `json:"tags" bun:"tags,type:text"`
|
||||
CreatedByUser *types.User `json:"user" bun:"rel:belongs-to,join:created_by=id"`
|
||||
Steps []*FunnelStep `json:"steps" bun:"steps,type:text,notnull"`
|
||||
Tags string `json:"tags" bun:"tags,type:text"`
|
||||
CreatedByUser *types.User `json:"user" bun:"rel:belongs-to,join:created_by=id"`
|
||||
}
|
||||
|
||||
type FunnelStep struct {
|
||||
@ -44,14 +44,14 @@ type FunnelStep struct {
|
||||
HasErrors bool `json:"has_errors"`
|
||||
}
|
||||
|
||||
// FunnelRequest represents all possible funnel-related requests
|
||||
type FunnelRequest struct {
|
||||
FunnelID valuer.UUID `json:"funnel_id,omitempty"`
|
||||
Name string `json:"funnel_name,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Steps []FunnelStep `json:"steps,omitempty"`
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
// PostableFunnel represents all possible funnel-related requests
|
||||
type PostableFunnel struct {
|
||||
FunnelID valuer.UUID `json:"funnel_id,omitempty"`
|
||||
Name string `json:"funnel_name,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Steps []*FunnelStep `json:"steps,omitempty"`
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
|
||||
// Analytics specific fields
|
||||
StartTime int64 `json:"start_time,omitempty"`
|
||||
@ -60,19 +60,19 @@ type FunnelRequest struct {
|
||||
StepBOrder int64 `json:"step_b_order,omitempty"`
|
||||
}
|
||||
|
||||
// FunnelResponse represents all possible funnel-related responses
|
||||
type FunnelResponse struct {
|
||||
FunnelID string `json:"funnel_id,omitempty"`
|
||||
FunnelName string `json:"funnel_name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CreatedAt int64 `json:"created_at,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
UpdatedAt int64 `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
OrgID string `json:"org_id,omitempty"`
|
||||
UserEmail string `json:"user_email,omitempty"`
|
||||
Funnel *Funnel `json:"funnel,omitempty"`
|
||||
Steps []FunnelStep `json:"steps,omitempty"`
|
||||
// GettableFunnel represents all possible funnel-related responses
|
||||
type GettableFunnel struct {
|
||||
FunnelID string `json:"funnel_id,omitempty"`
|
||||
FunnelName string `json:"funnel_name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
CreatedAt int64 `json:"created_at,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
UpdatedAt int64 `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
OrgID string `json:"org_id,omitempty"`
|
||||
UserEmail string `json:"user_email,omitempty"`
|
||||
Funnel *StorableFunnel `json:"funnel,omitempty"`
|
||||
Steps []*FunnelStep `json:"steps,omitempty"`
|
||||
}
|
||||
|
||||
// TimeRange represents a time range for analytics
|
||||
|
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
)
|
||||
|
||||
@ -28,7 +27,7 @@ func ValidateTimestampIsMilliseconds(timestamp int64) bool {
|
||||
return timestamp >= 1000000000000 && timestamp <= 9999999999999
|
||||
}
|
||||
|
||||
func ValidateFunnelSteps(steps []tracefunnel.FunnelStep) error {
|
||||
func ValidateFunnelSteps(steps []FunnelStep) error {
|
||||
if len(steps) < 2 {
|
||||
return fmt.Errorf("funnel must have at least 2 steps")
|
||||
}
|
||||
@ -50,12 +49,12 @@ func ValidateFunnelSteps(steps []tracefunnel.FunnelStep) error {
|
||||
|
||||
// NormalizeFunnelSteps normalizes step orders to be sequential starting from 1.
|
||||
// Returns a new slice with normalized step orders, leaving the input slice unchanged.
|
||||
func NormalizeFunnelSteps(steps []tracefunnel.FunnelStep) []tracefunnel.FunnelStep {
|
||||
func NormalizeFunnelSteps(steps []FunnelStep) []FunnelStep {
|
||||
if len(steps) == 0 {
|
||||
return []tracefunnel.FunnelStep{}
|
||||
return []FunnelStep{}
|
||||
}
|
||||
|
||||
newSteps := make([]tracefunnel.FunnelStep, len(steps))
|
||||
newSteps := make([]FunnelStep, len(steps))
|
||||
copy(newSteps, steps)
|
||||
|
||||
sort.Slice(newSteps, func(i, j int) bool {
|
||||
@ -88,8 +87,8 @@ func ValidateAndConvertTimestamp(timestamp int64) (time.Time, error) {
|
||||
return time.Unix(0, timestamp*1000000), nil // Convert to nanoseconds
|
||||
}
|
||||
|
||||
func ConstructFunnelResponse(funnel *tracefunnel.Funnel, claims *authtypes.Claims) tracefunnel.FunnelResponse {
|
||||
resp := tracefunnel.FunnelResponse{
|
||||
func ConstructFunnelResponse(funnel *StorableFunnel, claims *authtypes.Claims) GettableFunnel {
|
||||
resp := GettableFunnel{
|
||||
FunnelName: funnel.Name,
|
||||
FunnelID: funnel.ID.String(),
|
||||
Steps: funnel.Steps,
|
||||
@ -110,7 +109,7 @@ func ConstructFunnelResponse(funnel *tracefunnel.Funnel, claims *authtypes.Claim
|
||||
return resp
|
||||
}
|
||||
|
||||
func ProcessFunnelSteps(steps []tracefunnel.FunnelStep) ([]tracefunnel.FunnelStep, error) {
|
||||
func ProcessFunnelSteps(steps []FunnelStep) ([]FunnelStep, error) {
|
||||
// First validate the steps
|
||||
if err := ValidateFunnelSteps(steps); err != nil {
|
||||
return nil, errors.Newf(errors.TypeInvalidInput,
|
@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/types"
|
||||
"github.com/SigNoz/signoz/pkg/types/authtypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/tracefunnel"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -91,12 +90,12 @@ func TestValidateTimestampIsMilliseconds(t *testing.T) {
|
||||
func TestValidateFunnelSteps(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
steps []tracefunnel.FunnelStep
|
||||
steps []FunnelStep
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "valid steps",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -116,7 +115,7 @@ func TestValidateFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "too few steps",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -129,7 +128,7 @@ func TestValidateFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "missing service name",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -148,7 +147,7 @@ func TestValidateFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "missing span name",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -167,7 +166,7 @@ func TestValidateFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "negative order",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -202,12 +201,12 @@ func TestValidateFunnelSteps(t *testing.T) {
|
||||
func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
steps []tracefunnel.FunnelStep
|
||||
expected []tracefunnel.FunnelStep
|
||||
steps []FunnelStep
|
||||
expected []FunnelStep
|
||||
}{
|
||||
{
|
||||
name: "already normalized steps",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -223,7 +222,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
Order: 2,
|
||||
},
|
||||
},
|
||||
expected: []tracefunnel.FunnelStep{
|
||||
expected: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -240,7 +239,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "unordered steps",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 2",
|
||||
@ -256,7 +255,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
Order: 1,
|
||||
},
|
||||
},
|
||||
expected: []tracefunnel.FunnelStep{
|
||||
expected: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -273,7 +272,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "steps with gaps in order",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -296,7 +295,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
Order: 2,
|
||||
},
|
||||
},
|
||||
expected: []tracefunnel.FunnelStep{
|
||||
expected: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -322,7 +321,7 @@ func TestNormalizeFunnelSteps(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Make a copy of the steps to avoid modifying the original
|
||||
steps := make([]tracefunnel.FunnelStep, len(tt.steps))
|
||||
steps := make([]FunnelStep, len(tt.steps))
|
||||
copy(steps, tt.steps)
|
||||
|
||||
result := NormalizeFunnelSteps(steps)
|
||||
@ -429,14 +428,14 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
funnel *tracefunnel.Funnel
|
||||
funnel *StorableFunnel
|
||||
claims *authtypes.Claims
|
||||
expected tracefunnel.FunnelResponse
|
||||
expected GettableFunnel
|
||||
}{
|
||||
{
|
||||
name: "with user email from funnel",
|
||||
funnel: &tracefunnel.Funnel{
|
||||
BaseMetadata: tracefunnel.BaseMetadata{
|
||||
funnel: &StorableFunnel{
|
||||
BaseMetadata: BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
},
|
||||
@ -455,7 +454,7 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
Identifiable: types.Identifiable{ID: valuer.MustNewUUID("user-123")},
|
||||
Email: "funnel@example.com",
|
||||
},
|
||||
Steps: []tracefunnel.FunnelStep{
|
||||
Steps: []*FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -470,10 +469,10 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
OrgID: orgID.String(),
|
||||
Email: "claims@example.com",
|
||||
},
|
||||
expected: tracefunnel.FunnelResponse{
|
||||
expected: GettableFunnel{
|
||||
FunnelName: "test-funnel",
|
||||
FunnelID: funnelID.String(),
|
||||
Steps: []tracefunnel.FunnelStep{
|
||||
Steps: []*FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -491,8 +490,8 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "with user email from claims",
|
||||
funnel: &tracefunnel.Funnel{
|
||||
BaseMetadata: tracefunnel.BaseMetadata{
|
||||
funnel: &StorableFunnel{
|
||||
BaseMetadata: BaseMetadata{
|
||||
Identifiable: types.Identifiable{
|
||||
ID: funnelID,
|
||||
},
|
||||
@ -507,7 +506,7 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
UpdatedBy: "user-123",
|
||||
},
|
||||
},
|
||||
Steps: []tracefunnel.FunnelStep{
|
||||
Steps: []*FunnelStep{
|
||||
{
|
||||
ID: valuer.GenerateUUID(),
|
||||
Name: "Step 1",
|
||||
@ -522,10 +521,10 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
OrgID: orgID.String(),
|
||||
Email: "claims@example.com",
|
||||
},
|
||||
expected: tracefunnel.FunnelResponse{
|
||||
expected: GettableFunnel{
|
||||
FunnelName: "test-funnel",
|
||||
FunnelID: funnelID.String(),
|
||||
Steps: []tracefunnel.FunnelStep{
|
||||
Steps: []*FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -573,12 +572,12 @@ func TestConstructFunnelResponse(t *testing.T) {
|
||||
func TestProcessFunnelSteps(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
steps []tracefunnel.FunnelStep
|
||||
steps []FunnelStep
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "valid steps with missing IDs",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
||||
@ -596,7 +595,7 @@ func TestProcessFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid steps - missing service name",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
SpanName: "test-span",
|
||||
@ -613,7 +612,7 @@ func TestProcessFunnelSteps(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid steps - negative order",
|
||||
steps: []tracefunnel.FunnelStep{
|
||||
steps: []FunnelStep{
|
||||
{
|
||||
Name: "Step 1",
|
||||
ServiceName: "test-service",
|
Loading…
x
Reference in New Issue
Block a user