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