From c79914dd30c3837dff5e19186b8e495179725b87 Mon Sep 17 00:00:00 2001 From: lizhanpeng Date: Thu, 30 Oct 2025 12:17:05 +0800 Subject: [PATCH 1/4] feat(backend): refactor code --- .../observability/application/trace.go | 145 +++++++++++------- 1 file changed, 87 insertions(+), 58 deletions(-) diff --git a/backend/modules/observability/application/trace.go b/backend/modules/observability/application/trace.go index ec88002c1..84f1c1adc 100644 --- a/backend/modules/observability/application/trace.go +++ b/backend/modules/observability/application/trace.go @@ -6,14 +6,9 @@ package application import ( "context" "strconv" + "sync" "time" - "github.com/coze-dev/coze-loop/backend/modules/observability/application/convertor" - "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/tenant" - - "github.com/samber/lo" - "golang.org/x/sync/errgroup" - "github.com/coze-dev/coze-loop/backend/infra/external/benefit" "github.com/coze-dev/coze-loop/backend/infra/middleware/session" "github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/observability/domain/common" @@ -21,11 +16,13 @@ import ( "github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/observability/domain/span" "github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/observability/domain/view" "github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/observability/trace" + "github.com/coze-dev/coze-loop/backend/modules/observability/application/convertor" tconv "github.com/coze-dev/coze-loop/backend/modules/observability/application/convertor/trace" "github.com/coze-dev/coze-loop/backend/modules/observability/application/utils" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/config" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/metrics" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/rpc" + "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/tenant" commdo "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/entity/common" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/entity/loop_span" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/repo" @@ -35,6 +32,8 @@ import ( "github.com/coze-dev/coze-loop/backend/pkg/lang/goroutine" "github.com/coze-dev/coze-loop/backend/pkg/lang/ptr" "github.com/coze-dev/coze-loop/backend/pkg/logs" + "github.com/samber/lo" + "golang.org/x/sync/errgroup" ) const ( @@ -47,6 +46,7 @@ const ( type ITraceApplication interface { trace.TraceService + GetDisplayInfo(context.Context, *GetDisplayInfoRequest) GetDisplayInfoResponse } func NewTraceApplication( @@ -109,13 +109,13 @@ func (t *TraceApplication) ListSpans(ctx context.Context, req *trace.ListSpansRe return nil, err } logs.CtxInfo(ctx, "List spans successfully, spans count: %d", len(sResp.Spans)) - userMap, evalMap, tagMap := t.getAnnoDisplayInfo(ctx, - req.GetWorkspaceID(), - nil, - sResp.Spans.GetEvaluatorVersionIDs(), - sResp.Spans.GetAnnotationTagIDs()) + dResp := t.GetDisplayInfo(ctx, &GetDisplayInfoRequest{ + WorkspaceID: req.GetWorkspaceID(), + EvaluatorIDs: sResp.Spans.GetEvaluatorVersionIDs(), + TagKeyIDs: sResp.Spans.GetAnnotationTagIDs(), + }) return &trace.ListSpansResponse{ - Spans: tconv.SpanListDO2DTO(sResp.Spans, userMap, evalMap, tagMap), + Spans: tconv.SpanListDO2DTO(sResp.Spans, dResp.UserMap, dResp.EvalMap, dResp.TagMap), NextPageToken: sResp.NextPageToken, HasMore: sResp.HasMore, }, nil @@ -203,13 +203,14 @@ func (t *TraceApplication) GetTrace(ctx context.Context, req *trace.GetTraceRequ return nil, errorx.WrapByCode(err, obErrorx.CommercialCommonInternalErrorCodeCode) } logs.CtxInfo(ctx, "Get trace successfully, spans count %d", len(sResp.Spans)) - userMap, evalMap, tagMap := t.getAnnoDisplayInfo(ctx, - req.GetWorkspaceID(), - sResp.Spans.GetUserIDs(), - sResp.Spans.GetEvaluatorVersionIDs(), - sResp.Spans.GetAnnotationTagIDs()) + dResp := t.GetDisplayInfo(ctx, &GetDisplayInfoRequest{ + WorkspaceID: req.GetWorkspaceID(), + UserIDs: sResp.Spans.GetUserIDs(), + EvaluatorIDs: sResp.Spans.GetEvaluatorVersionIDs(), + TagKeyIDs: sResp.Spans.GetAnnotationTagIDs(), + }) return &trace.GetTraceResponse{ - Spans: tconv.SpanListDO2DTO(sResp.Spans, userMap, evalMap, tagMap), + Spans: tconv.SpanListDO2DTO(sResp.Spans, dResp.UserMap, dResp.EvalMap, dResp.TagMap), TracesAdvanceInfo: &trace.TraceAdvanceInfo{ TraceID: sResp.TraceId, Tokens: &trace.TokenCost{ @@ -281,13 +282,14 @@ func (t *TraceApplication) SearchTraceTree(ctx context.Context, req *trace.Searc return nil, errorx.WrapByCode(err, obErrorx.CommercialCommonInternalErrorCodeCode) } logs.CtxInfo(ctx, "SearchTraceTree successfully, spans count %d", len(sResp.Spans)) - userMap, evalMap, tagMap := t.getAnnoDisplayInfo(ctx, - req.GetWorkspaceID(), - sResp.Spans.GetUserIDs(), - sResp.Spans.GetEvaluatorVersionIDs(), - sResp.Spans.GetAnnotationTagIDs()) + resp := t.GetDisplayInfo(ctx, &GetDisplayInfoRequest{ + WorkspaceID: req.GetWorkspaceID(), + UserIDs: sResp.Spans.GetUserIDs(), + EvaluatorIDs: sResp.Spans.GetEvaluatorVersionIDs(), + TagKeyIDs: sResp.Spans.GetAnnotationTagIDs(), + }) return &trace.SearchTraceTreeResponse{ - Spans: tconv.SpanListDO2DTO(sResp.Spans, userMap, evalMap, tagMap), + Spans: tconv.SpanListDO2DTO(sResp.Spans, resp.UserMap, resp.EvalMap, resp.TagMap), TracesAdvanceInfo: &trace.TraceAdvanceInfo{ TraceID: sResp.TraceId, Tokens: &trace.TokenCost{ @@ -807,44 +809,17 @@ func (t *TraceApplication) ListAnnotations(ctx context.Context, req *trace.ListA if err != nil { return nil, err } - userMap, evalMap, tagMap := t.getAnnoDisplayInfo(ctx, - req.GetWorkspaceID(), - resp.Annotations.GetUserIDs(), - resp.Annotations.GetEvaluatorVersionIDs(), - resp.Annotations.GetAnnotationTagIDs()) + dResp := t.GetDisplayInfo(ctx, &GetDisplayInfoRequest{ + WorkspaceID: req.GetWorkspaceID(), + UserIDs: resp.Annotations.GetUserIDs(), + EvaluatorIDs: resp.Annotations.GetEvaluatorVersionIDs(), + TagKeyIDs: resp.Annotations.GetAnnotationTagIDs(), + }) return &trace.ListAnnotationsResponse{ - Annotations: tconv.AnnotationListDO2DTO(resp.Annotations, userMap, evalMap, tagMap), + Annotations: tconv.AnnotationListDO2DTO(resp.Annotations, dResp.UserMap, dResp.EvalMap, dResp.TagMap), }, nil } -func (t *TraceApplication) getAnnoDisplayInfo(ctx context.Context, workspaceId int64, userIds []string, evalIds []int64, tagKeyIds []string, -) (userMap map[string]*commdo.UserInfo, evalMap map[int64]*rpc.Evaluator, tagMap map[int64]*rpc.TagInfo) { - if len(userIds) == 0 && len(tagKeyIds) == 0 && len(evalIds) == 0 { - return userMap, evalMap, tagMap - } - g := errgroup.Group{} - g.Go(func() error { - defer goroutine.Recovery(ctx) - _, userMap, _ = t.userSvc.GetUserInfo(ctx, userIds) - return nil - }) - g.Go(func() error { - defer goroutine.Recovery(ctx) - _, evalMap, _ = t.evalSvc.BatchGetEvaluatorVersions(ctx, &rpc.BatchGetEvaluatorVersionsParam{ - WorkspaceID: workspaceId, - EvaluatorVersionIds: evalIds, - }) - return nil - }) - g.Go(func() error { - defer goroutine.Recovery(ctx) - tagMap, _ = t.tagSvc.BatchGetTagInfo(ctx, workspaceId, tagKeyIds) - return nil - }) - _ = g.Wait() - return userMap, evalMap, tagMap -} - func (t *TraceApplication) ExportTracesToDataset(ctx context.Context, req *trace.ExportTracesToDatasetRequest) ( r *trace.ExportTracesToDatasetResponse, err error, ) { @@ -1032,3 +1007,57 @@ func (t *TraceApplication) validateExtractSpanInfoReq(ctx context.Context, req * } return nil } + +// inner usage +type GetDisplayInfoRequest struct { + WorkspaceID int64 + UserIDs []string + EvaluatorIDs []int64 + TagKeyIDs []string +} + +type GetDisplayInfoResponse struct { + UserMap map[string]*commdo.UserInfo + EvalMap map[int64]*rpc.Evaluator + TagMap map[int64]*rpc.TagInfo +} + +func (t *TraceApplication) GetDisplayInfo(ctx context.Context, req *GetDisplayInfoRequest) GetDisplayInfoResponse { + resp := GetDisplayInfoResponse{} + if len(req.UserIDs) == 0 && len(req.EvaluatorIDs) == 0 && len(req.TagKeyIDs) == 0 { + return resp + } + var ( + g errgroup.Group + lock sync.Mutex + ) + g.Go(func() error { + defer goroutine.Recovery(ctx) + _, userMap, _ := t.userSvc.GetUserInfo(ctx, req.UserIDs) + lock.Lock() + defer lock.Unlock() + resp.UserMap = userMap + return nil + }) + g.Go(func() error { + defer goroutine.Recovery(ctx) + _, evalMap, _ := t.evalSvc.BatchGetEvaluatorVersions(ctx, &rpc.BatchGetEvaluatorVersionsParam{ + WorkspaceID: req.WorkspaceID, + EvaluatorVersionIds: req.EvaluatorIDs, + }) + lock.Lock() + defer lock.Unlock() + resp.EvalMap = evalMap + return nil + }) + g.Go(func() error { + defer goroutine.Recovery(ctx) + tagMap, _ := t.tagSvc.BatchGetTagInfo(ctx, req.WorkspaceID, req.TagKeyIDs) + lock.Lock() + defer lock.Unlock() + resp.TagMap = tagMap + return nil + }) + _ = g.Wait() + return resp +} From d051f4c7c32fd96090bafb532ed94013b1d3e60f Mon Sep 17 00:00:00 2001 From: lizhanpeng Date: Fri, 31 Oct 2025 14:56:30 +0800 Subject: [PATCH 2/4] feat(backend): refactor --- .../application/mocks/trace_application.go | 342 ++++++++++++++++++ .../observability/application/trace.go | 1 + .../domain/component/config/config.go | 6 +- .../domain/component/config/mocks/config.go | 11 +- .../trace/span_filter/prompt_filter.go | 7 +- .../trace/span_filter/prompt_filter_test.go | 36 +- .../span_processor/platform_processor.go | 3 +- .../span_processor/platform_processor_test.go | 10 +- .../observability/infra/config/trace.go | 13 +- .../observability/infra/config/trace_test.go | 27 +- 10 files changed, 403 insertions(+), 53 deletions(-) create mode 100644 backend/modules/observability/application/mocks/trace_application.go diff --git a/backend/modules/observability/application/mocks/trace_application.go b/backend/modules/observability/application/mocks/trace_application.go new file mode 100644 index 000000000..28cbde7ea --- /dev/null +++ b/backend/modules/observability/application/mocks/trace_application.go @@ -0,0 +1,342 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/coze-dev/coze-loop/backend/modules/observability/application (interfaces: ITraceApplication) +// +// Generated by this command: +// +// mockgen -destination=mocks/trace_application.go -package=mocks . ITraceApplication +// + +// Package mocks is a generated GoMock package. +package mocks + +import ( + context "context" + reflect "reflect" + + trace "github.com/coze-dev/coze-loop/backend/kitex_gen/coze/loop/observability/trace" + application "github.com/coze-dev/coze-loop/backend/modules/observability/application" + gomock "go.uber.org/mock/gomock" +) + +// MockITraceApplication is a mock of ITraceApplication interface. +type MockITraceApplication struct { + ctrl *gomock.Controller + recorder *MockITraceApplicationMockRecorder + isgomock struct{} +} + +// MockITraceApplicationMockRecorder is the mock recorder for MockITraceApplication. +type MockITraceApplicationMockRecorder struct { + mock *MockITraceApplication +} + +// NewMockITraceApplication creates a new mock instance. +func NewMockITraceApplication(ctrl *gomock.Controller) *MockITraceApplication { + mock := &MockITraceApplication{ctrl: ctrl} + mock.recorder = &MockITraceApplicationMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockITraceApplication) EXPECT() *MockITraceApplicationMockRecorder { + return m.recorder +} + +// BatchGetTracesAdvanceInfo mocks base method. +func (m *MockITraceApplication) BatchGetTracesAdvanceInfo(ctx context.Context, req *trace.BatchGetTracesAdvanceInfoRequest) (*trace.BatchGetTracesAdvanceInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BatchGetTracesAdvanceInfo", ctx, req) + ret0, _ := ret[0].(*trace.BatchGetTracesAdvanceInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BatchGetTracesAdvanceInfo indicates an expected call of BatchGetTracesAdvanceInfo. +func (mr *MockITraceApplicationMockRecorder) BatchGetTracesAdvanceInfo(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchGetTracesAdvanceInfo", reflect.TypeOf((*MockITraceApplication)(nil).BatchGetTracesAdvanceInfo), ctx, req) +} + +// ChangeEvaluatorScore mocks base method. +func (m *MockITraceApplication) ChangeEvaluatorScore(ctx context.Context, req *trace.ChangeEvaluatorScoreRequest) (*trace.ChangeEvaluatorScoreResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ChangeEvaluatorScore", ctx, req) + ret0, _ := ret[0].(*trace.ChangeEvaluatorScoreResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ChangeEvaluatorScore indicates an expected call of ChangeEvaluatorScore. +func (mr *MockITraceApplicationMockRecorder) ChangeEvaluatorScore(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeEvaluatorScore", reflect.TypeOf((*MockITraceApplication)(nil).ChangeEvaluatorScore), ctx, req) +} + +// CreateManualAnnotation mocks base method. +func (m *MockITraceApplication) CreateManualAnnotation(ctx context.Context, req *trace.CreateManualAnnotationRequest) (*trace.CreateManualAnnotationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateManualAnnotation", ctx, req) + ret0, _ := ret[0].(*trace.CreateManualAnnotationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateManualAnnotation indicates an expected call of CreateManualAnnotation. +func (mr *MockITraceApplicationMockRecorder) CreateManualAnnotation(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateManualAnnotation", reflect.TypeOf((*MockITraceApplication)(nil).CreateManualAnnotation), ctx, req) +} + +// CreateView mocks base method. +func (m *MockITraceApplication) CreateView(ctx context.Context, req *trace.CreateViewRequest) (*trace.CreateViewResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateView", ctx, req) + ret0, _ := ret[0].(*trace.CreateViewResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateView indicates an expected call of CreateView. +func (mr *MockITraceApplicationMockRecorder) CreateView(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateView", reflect.TypeOf((*MockITraceApplication)(nil).CreateView), ctx, req) +} + +// DeleteManualAnnotation mocks base method. +func (m *MockITraceApplication) DeleteManualAnnotation(ctx context.Context, req *trace.DeleteManualAnnotationRequest) (*trace.DeleteManualAnnotationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteManualAnnotation", ctx, req) + ret0, _ := ret[0].(*trace.DeleteManualAnnotationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteManualAnnotation indicates an expected call of DeleteManualAnnotation. +func (mr *MockITraceApplicationMockRecorder) DeleteManualAnnotation(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteManualAnnotation", reflect.TypeOf((*MockITraceApplication)(nil).DeleteManualAnnotation), ctx, req) +} + +// DeleteView mocks base method. +func (m *MockITraceApplication) DeleteView(ctx context.Context, req *trace.DeleteViewRequest) (*trace.DeleteViewResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteView", ctx, req) + ret0, _ := ret[0].(*trace.DeleteViewResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteView indicates an expected call of DeleteView. +func (mr *MockITraceApplicationMockRecorder) DeleteView(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteView", reflect.TypeOf((*MockITraceApplication)(nil).DeleteView), ctx, req) +} + +// ExportTracesToDataset mocks base method. +func (m *MockITraceApplication) ExportTracesToDataset(ctx context.Context, req *trace.ExportTracesToDatasetRequest) (*trace.ExportTracesToDatasetResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportTracesToDataset", ctx, req) + ret0, _ := ret[0].(*trace.ExportTracesToDatasetResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExportTracesToDataset indicates an expected call of ExportTracesToDataset. +func (mr *MockITraceApplicationMockRecorder) ExportTracesToDataset(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportTracesToDataset", reflect.TypeOf((*MockITraceApplication)(nil).ExportTracesToDataset), ctx, req) +} + +// ExtractSpanInfo mocks base method. +func (m *MockITraceApplication) ExtractSpanInfo(ctx context.Context, req *trace.ExtractSpanInfoRequest) (*trace.ExtractSpanInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExtractSpanInfo", ctx, req) + ret0, _ := ret[0].(*trace.ExtractSpanInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExtractSpanInfo indicates an expected call of ExtractSpanInfo. +func (mr *MockITraceApplicationMockRecorder) ExtractSpanInfo(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtractSpanInfo", reflect.TypeOf((*MockITraceApplication)(nil).ExtractSpanInfo), ctx, req) +} + +// GetDisplayInfo mocks base method. +func (m *MockITraceApplication) GetDisplayInfo(arg0 context.Context, arg1 *application.GetDisplayInfoRequest) application.GetDisplayInfoResponse { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDisplayInfo", arg0, arg1) + ret0, _ := ret[0].(application.GetDisplayInfoResponse) + return ret0 +} + +// GetDisplayInfo indicates an expected call of GetDisplayInfo. +func (mr *MockITraceApplicationMockRecorder) GetDisplayInfo(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDisplayInfo", reflect.TypeOf((*MockITraceApplication)(nil).GetDisplayInfo), arg0, arg1) +} + +// GetTrace mocks base method. +func (m *MockITraceApplication) GetTrace(ctx context.Context, req *trace.GetTraceRequest) (*trace.GetTraceResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTrace", ctx, req) + ret0, _ := ret[0].(*trace.GetTraceResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTrace indicates an expected call of GetTrace. +func (mr *MockITraceApplicationMockRecorder) GetTrace(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTrace", reflect.TypeOf((*MockITraceApplication)(nil).GetTrace), ctx, req) +} + +// GetTracesMetaInfo mocks base method. +func (m *MockITraceApplication) GetTracesMetaInfo(ctx context.Context, req *trace.GetTracesMetaInfoRequest) (*trace.GetTracesMetaInfoResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTracesMetaInfo", ctx, req) + ret0, _ := ret[0].(*trace.GetTracesMetaInfoResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTracesMetaInfo indicates an expected call of GetTracesMetaInfo. +func (mr *MockITraceApplicationMockRecorder) GetTracesMetaInfo(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTracesMetaInfo", reflect.TypeOf((*MockITraceApplication)(nil).GetTracesMetaInfo), ctx, req) +} + +// IngestTracesInner mocks base method. +func (m *MockITraceApplication) IngestTracesInner(ctx context.Context, req *trace.IngestTracesRequest) (*trace.IngestTracesResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IngestTracesInner", ctx, req) + ret0, _ := ret[0].(*trace.IngestTracesResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IngestTracesInner indicates an expected call of IngestTracesInner. +func (mr *MockITraceApplicationMockRecorder) IngestTracesInner(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IngestTracesInner", reflect.TypeOf((*MockITraceApplication)(nil).IngestTracesInner), ctx, req) +} + +// ListAnnotationEvaluators mocks base method. +func (m *MockITraceApplication) ListAnnotationEvaluators(ctx context.Context, req *trace.ListAnnotationEvaluatorsRequest) (*trace.ListAnnotationEvaluatorsResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListAnnotationEvaluators", ctx, req) + ret0, _ := ret[0].(*trace.ListAnnotationEvaluatorsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListAnnotationEvaluators indicates an expected call of ListAnnotationEvaluators. +func (mr *MockITraceApplicationMockRecorder) ListAnnotationEvaluators(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAnnotationEvaluators", reflect.TypeOf((*MockITraceApplication)(nil).ListAnnotationEvaluators), ctx, req) +} + +// ListAnnotations mocks base method. +func (m *MockITraceApplication) ListAnnotations(ctx context.Context, req *trace.ListAnnotationsRequest) (*trace.ListAnnotationsResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListAnnotations", ctx, req) + ret0, _ := ret[0].(*trace.ListAnnotationsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListAnnotations indicates an expected call of ListAnnotations. +func (mr *MockITraceApplicationMockRecorder) ListAnnotations(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAnnotations", reflect.TypeOf((*MockITraceApplication)(nil).ListAnnotations), ctx, req) +} + +// ListSpans mocks base method. +func (m *MockITraceApplication) ListSpans(ctx context.Context, req *trace.ListSpansRequest) (*trace.ListSpansResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListSpans", ctx, req) + ret0, _ := ret[0].(*trace.ListSpansResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListSpans indicates an expected call of ListSpans. +func (mr *MockITraceApplicationMockRecorder) ListSpans(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListSpans", reflect.TypeOf((*MockITraceApplication)(nil).ListSpans), ctx, req) +} + +// ListViews mocks base method. +func (m *MockITraceApplication) ListViews(ctx context.Context, req *trace.ListViewsRequest) (*trace.ListViewsResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListViews", ctx, req) + ret0, _ := ret[0].(*trace.ListViewsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListViews indicates an expected call of ListViews. +func (mr *MockITraceApplicationMockRecorder) ListViews(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListViews", reflect.TypeOf((*MockITraceApplication)(nil).ListViews), ctx, req) +} + +// PreviewExportTracesToDataset mocks base method. +func (m *MockITraceApplication) PreviewExportTracesToDataset(ctx context.Context, req *trace.PreviewExportTracesToDatasetRequest) (*trace.PreviewExportTracesToDatasetResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PreviewExportTracesToDataset", ctx, req) + ret0, _ := ret[0].(*trace.PreviewExportTracesToDatasetResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// PreviewExportTracesToDataset indicates an expected call of PreviewExportTracesToDataset. +func (mr *MockITraceApplicationMockRecorder) PreviewExportTracesToDataset(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PreviewExportTracesToDataset", reflect.TypeOf((*MockITraceApplication)(nil).PreviewExportTracesToDataset), ctx, req) +} + +// SearchTraceTree mocks base method. +func (m *MockITraceApplication) SearchTraceTree(ctx context.Context, req *trace.SearchTraceTreeRequest) (*trace.SearchTraceTreeResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SearchTraceTree", ctx, req) + ret0, _ := ret[0].(*trace.SearchTraceTreeResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SearchTraceTree indicates an expected call of SearchTraceTree. +func (mr *MockITraceApplicationMockRecorder) SearchTraceTree(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchTraceTree", reflect.TypeOf((*MockITraceApplication)(nil).SearchTraceTree), ctx, req) +} + +// UpdateManualAnnotation mocks base method. +func (m *MockITraceApplication) UpdateManualAnnotation(ctx context.Context, req *trace.UpdateManualAnnotationRequest) (*trace.UpdateManualAnnotationResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateManualAnnotation", ctx, req) + ret0, _ := ret[0].(*trace.UpdateManualAnnotationResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateManualAnnotation indicates an expected call of UpdateManualAnnotation. +func (mr *MockITraceApplicationMockRecorder) UpdateManualAnnotation(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateManualAnnotation", reflect.TypeOf((*MockITraceApplication)(nil).UpdateManualAnnotation), ctx, req) +} + +// UpdateView mocks base method. +func (m *MockITraceApplication) UpdateView(ctx context.Context, req *trace.UpdateViewRequest) (*trace.UpdateViewResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateView", ctx, req) + ret0, _ := ret[0].(*trace.UpdateViewResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateView indicates an expected call of UpdateView. +func (mr *MockITraceApplicationMockRecorder) UpdateView(ctx, req any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateView", reflect.TypeOf((*MockITraceApplication)(nil).UpdateView), ctx, req) +} diff --git a/backend/modules/observability/application/trace.go b/backend/modules/observability/application/trace.go index 84f1c1adc..e3c3bd135 100644 --- a/backend/modules/observability/application/trace.go +++ b/backend/modules/observability/application/trace.go @@ -44,6 +44,7 @@ const ( QueryLimitDefault = 100 ) +//go:generate mockgen -destination=mocks/trace_application.go -package=mocks . ITraceApplication type ITraceApplication interface { trace.TraceService GetDisplayInfo(context.Context, *GetDisplayInfoRequest) GetDisplayInfoResponse diff --git a/backend/modules/observability/domain/component/config/config.go b/backend/modules/observability/domain/component/config/config.go index f587b3188..9921d84a7 100644 --- a/backend/modules/observability/domain/component/config/config.go +++ b/backend/modules/observability/domain/component/config/config.go @@ -23,7 +23,9 @@ type PlatformTenantsCfg struct { } type SpanTransHandlerConfig struct { - PlatformCfg map[string]loop_span.SpanTransCfgList `mapstructure:"platform_cfg" json:"platform_cfg"` + BasicConfig map[string]loop_span.SpanTransCfgList `mapstructure:"basic_config" json:"basic_config"` + PlatformCfg map[string]loop_span.SpanTransCfgList `mapstructure:"platform_cfg" json:"platform_cfg"` + PlatformInheritance map[string][]string `mapstructure:"platform_basic" json:"platform_basic"` } type IngestConfig struct { @@ -116,7 +118,7 @@ type ConsumerListening struct { type ITraceConfig interface { GetSystemViews(ctx context.Context) ([]*SystemView, error) GetPlatformTenants(ctx context.Context) (*PlatformTenantsCfg, error) - GetPlatformSpansTrans(ctx context.Context) (*SpanTransHandlerConfig, error) + GetPlatformSpansTrans(ctx context.Context, platformType loop_span.PlatformType) (loop_span.SpanTransCfgList, error) GetTraceIngestTenantProducerCfg(ctx context.Context) (map[string]*IngestConfig, error) GetAnnotationMqProducerCfg(ctx context.Context) (*MqProducerCfg, error) GetTraceCkCfg(ctx context.Context) (*TraceCKCfg, error) diff --git a/backend/modules/observability/domain/component/config/mocks/config.go b/backend/modules/observability/domain/component/config/mocks/config.go index e53f087e3..0221946fd 100644 --- a/backend/modules/observability/domain/component/config/mocks/config.go +++ b/backend/modules/observability/domain/component/config/mocks/config.go @@ -14,6 +14,7 @@ import ( reflect "reflect" config "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/config" + loop_span "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/entity/loop_span" conf "github.com/coze-dev/coze-loop/backend/pkg/conf" gomock "go.uber.org/mock/gomock" ) @@ -130,18 +131,18 @@ func (mr *MockITraceConfigMockRecorder) GetKeySpanTypes(ctx any) *gomock.Call { } // GetPlatformSpansTrans mocks base method. -func (m *MockITraceConfig) GetPlatformSpansTrans(ctx context.Context) (*config.SpanTransHandlerConfig, error) { +func (m *MockITraceConfig) GetPlatformSpansTrans(ctx context.Context, platformType loop_span.PlatformType) (loop_span.SpanTransCfgList, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPlatformSpansTrans", ctx) - ret0, _ := ret[0].(*config.SpanTransHandlerConfig) + ret := m.ctrl.Call(m, "GetPlatformSpansTrans", ctx, platformType) + ret0, _ := ret[0].(loop_span.SpanTransCfgList) ret1, _ := ret[1].(error) return ret0, ret1 } // GetPlatformSpansTrans indicates an expected call of GetPlatformSpansTrans. -func (mr *MockITraceConfigMockRecorder) GetPlatformSpansTrans(ctx any) *gomock.Call { +func (mr *MockITraceConfigMockRecorder) GetPlatformSpansTrans(ctx, platformType any) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPlatformSpansTrans", reflect.TypeOf((*MockITraceConfig)(nil).GetPlatformSpansTrans), ctx) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPlatformSpansTrans", reflect.TypeOf((*MockITraceConfig)(nil).GetPlatformSpansTrans), ctx, platformType) } // GetPlatformTenants mocks base method. diff --git a/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter.go b/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter.go index 37d1bbce7..c4dd20054 100644 --- a/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter.go +++ b/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter.go @@ -5,7 +5,6 @@ package span_filter import ( "context" - "fmt" "strconv" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/config" @@ -86,14 +85,10 @@ func (c *PromptFilterFactory) PlatformType() loop_span.PlatformType { } func (c *PromptFilterFactory) CreateFilter(ctx context.Context) (Filter, error) { - transCfg, err := c.traceConfig.GetPlatformSpansTrans(ctx) + cfg, err := c.traceConfig.GetPlatformSpansTrans(ctx, c.PlatformType()) if err != nil { return nil, err } - cfg, ok := transCfg.PlatformCfg[string(c.PlatformType())] - if !ok { - return nil, fmt.Errorf("trans config not configured for platform type %s", c.PlatformType()) - } return &PromptFilter{ transCfg: cfg, }, nil diff --git a/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter_test.go b/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter_test.go index 452e6211f..459c3c5f0 100644 --- a/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter_test.go +++ b/backend/modules/observability/domain/trace/service/trace/span_filter/prompt_filter_test.go @@ -188,20 +188,16 @@ func TestPromptFilterFactory_CreateFilter(t *testing.T) { name: "success", fieldsGetter: func(ctrl *gomock.Controller) fields { confmock := confmocks.NewMockITraceConfig(ctrl) - confmock.EXPECT().GetPlatformSpansTrans(gomock.Any()).Return(&config.SpanTransHandlerConfig{ - PlatformCfg: map[string]loop_span.SpanTransCfgList{ - string(loop_span.PlatformPrompt): { - { - SpanFilter: &loop_span.FilterFields{ - QueryAndOr: ptr.Of(loop_span.QueryAndOrEnumAnd), - FilterFields: []*loop_span.FilterField{ - { - FieldName: "test_field", - FieldType: loop_span.FieldTypeString, - Values: []string{"test_value"}, - QueryType: ptr.Of(loop_span.QueryTypeEnumIn), - }, - }, + confmock.EXPECT().GetPlatformSpansTrans(gomock.Any(), gomock.Any()).Return(loop_span.SpanTransCfgList{ + { + SpanFilter: &loop_span.FilterFields{ + QueryAndOr: ptr.Of(loop_span.QueryAndOrEnumAnd), + FilterFields: []*loop_span.FilterField{ + { + FieldName: "test_field", + FieldType: loop_span.FieldTypeString, + Values: []string{"test_value"}, + QueryType: ptr.Of(loop_span.QueryTypeEnumIn), }, }, }, @@ -216,23 +212,21 @@ func TestPromptFilterFactory_CreateFilter(t *testing.T) { name: "error getting config", fieldsGetter: func(ctrl *gomock.Controller) fields { confmock := confmocks.NewMockITraceConfig(ctrl) - confmock.EXPECT().GetPlatformSpansTrans(gomock.Any()).Return(nil, assert.AnError) + confmock.EXPECT().GetPlatformSpansTrans(gomock.Any(), gomock.Any()).Return(nil, assert.AnError) return fields{confmock} }, want: nil, wantErr: true, }, { - name: "config not found", + name: "empty config is valid", fieldsGetter: func(ctrl *gomock.Controller) fields { confmock := confmocks.NewMockITraceConfig(ctrl) - confmock.EXPECT().GetPlatformSpansTrans(gomock.Any()).Return(&config.SpanTransHandlerConfig{ - PlatformCfg: map[string]loop_span.SpanTransCfgList{}, - }, nil) + confmock.EXPECT().GetPlatformSpansTrans(gomock.Any(), gomock.Any()).Return(loop_span.SpanTransCfgList{}, nil) return fields{confmock} }, - want: nil, - wantErr: true, + want: &PromptFilter{}, + wantErr: false, }, } diff --git a/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor.go b/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor.go index 43f87c777..7efcc958a 100644 --- a/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor.go +++ b/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor.go @@ -23,11 +23,10 @@ type PlatformProcessorFactory struct { } func (p *PlatformProcessorFactory) CreateProcessor(ctx context.Context, set Settings) (Processor, error) { - transCfg, err := p.traceConfig.GetPlatformSpansTrans(ctx) + cfg, err := p.traceConfig.GetPlatformSpansTrans(ctx, set.PlatformType) if err != nil { return nil, err } - cfg := transCfg.PlatformCfg[string(set.PlatformType)] return &PlatformProcessor{ cfg: cfg, }, nil diff --git a/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor_test.go b/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor_test.go index 1fc45700c..3f31512a1 100644 --- a/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor_test.go +++ b/backend/modules/observability/domain/trace/service/trace/span_processor/platform_processor_test.go @@ -187,12 +187,8 @@ func TestPlatformProcessorFactory_CreateProcessor(t *testing.T) { name: "create processor successfully", fieldsGetter: func(ctrl *gomock.Controller) fields { confMock := confmocks.NewMockITraceConfig(ctrl) - confMock.EXPECT().GetPlatformSpansTrans(gomock.Any()).Return(&config.SpanTransHandlerConfig{ - PlatformCfg: map[string]loop_span.SpanTransCfgList{ - "cozeloop": { - {}, - }, - }, + confMock.EXPECT().GetPlatformSpansTrans(gomock.Any(), gomock.Any()).Return(loop_span.SpanTransCfgList{ + {}, }, nil) return fields{ traceConfig: confMock, @@ -215,7 +211,7 @@ func TestPlatformProcessorFactory_CreateProcessor(t *testing.T) { name: "create processor failed when config returns error", fieldsGetter: func(ctrl *gomock.Controller) fields { confMock := confmocks.NewMockITraceConfig(ctrl) - confMock.EXPECT().GetPlatformSpansTrans(gomock.Any()).Return(nil, fmt.Errorf("config error")) + confMock.EXPECT().GetPlatformSpansTrans(gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("config error")) return fields{ traceConfig: confMock, } diff --git a/backend/modules/observability/infra/config/trace.go b/backend/modules/observability/infra/config/trace.go index d5f3923e3..2c648dc2f 100644 --- a/backend/modules/observability/infra/config/trace.go +++ b/backend/modules/observability/infra/config/trace.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/config" + "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/entity/loop_span" "github.com/coze-dev/coze-loop/backend/pkg/conf" "github.com/coze-dev/coze-loop/backend/pkg/logs" ) @@ -50,12 +51,20 @@ func (t *TraceConfigCenter) GetPlatformTenants(ctx context.Context) (*config.Pla return cfg, nil } -func (t *TraceConfigCenter) GetPlatformSpansTrans(ctx context.Context) (*config.SpanTransHandlerConfig, error) { +func (t *TraceConfigCenter) GetPlatformSpansTrans(ctx context.Context, platformType loop_span.PlatformType) (loop_span.SpanTransCfgList, error) { cfg := new(config.SpanTransHandlerConfig) if err := t.UnmarshalKey(ctx, platformSpanHandlerCfgKey, cfg); err != nil { return nil, err } - return cfg, nil + ret := cfg.PlatformCfg[string(platformType)] + for _, inheritance := range cfg.PlatformInheritance[string(platformType)] { + basic := cfg.BasicConfig[inheritance] + if len(basic) == 0 { + continue + } + ret = append(ret, basic...) + } + return ret, nil } func (t *TraceConfigCenter) GetTraceIngestTenantProducerCfg(ctx context.Context) (map[string]*config.IngestConfig, error) { diff --git a/backend/modules/observability/infra/config/trace_test.go b/backend/modules/observability/infra/config/trace_test.go index 86628368c..c83ee6148 100644 --- a/backend/modules/observability/infra/config/trace_test.go +++ b/backend/modules/observability/infra/config/trace_test.go @@ -145,13 +145,14 @@ func TestTraceConfigCenter_GetPlatformSpansTrans(t *testing.T) { configLoader *confmocks.MockIConfigLoader } type args struct { - ctx context.Context + ctx context.Context + platformType loop_span.PlatformType } tests := []struct { name string fieldsGetter func(ctrl *gomock.Controller) fields args args - want *config.SpanTransHandlerConfig + want loop_span.SpanTransCfgList wantErr bool }{ { @@ -161,14 +162,21 @@ func TestTraceConfigCenter_GetPlatformSpansTrans(t *testing.T) { mockLoader.EXPECT().UnmarshalKey(gomock.Any(), platformSpanHandlerCfgKey, gomock.Any()). DoAndReturn(func(ctx context.Context, key string, v interface{}, opts ...interface{}) error { cfg := v.(*config.SpanTransHandlerConfig) - cfg.PlatformCfg = make(map[string]loop_span.SpanTransCfgList) + cfg.PlatformCfg = map[string]loop_span.SpanTransCfgList{ + "test_platform": { + {}, + }, + } return nil }) return fields{configLoader: mockLoader} }, - args: args{ctx: context.Background()}, - want: &config.SpanTransHandlerConfig{ - PlatformCfg: make(map[string]loop_span.SpanTransCfgList), + args: args{ + ctx: context.Background(), + platformType: "test_platform", + }, + want: loop_span.SpanTransCfgList{ + {}, }, wantErr: false, }, @@ -180,7 +188,10 @@ func TestTraceConfigCenter_GetPlatformSpansTrans(t *testing.T) { Return(fmt.Errorf("unmarshal error")) return fields{configLoader: mockLoader} }, - args: args{ctx: context.Background()}, + args: args{ + ctx: context.Background(), + platformType: "test_platform", + }, want: nil, wantErr: true, }, @@ -193,7 +204,7 @@ func TestTraceConfigCenter_GetPlatformSpansTrans(t *testing.T) { tr := &TraceConfigCenter{ IConfigLoader: f.configLoader, } - got, err := tr.GetPlatformSpansTrans(tt.args.ctx) + got, err := tr.GetPlatformSpansTrans(tt.args.ctx, tt.args.platformType) assert.Equal(t, tt.wantErr, err != nil) assert.Equal(t, tt.want, got) }) From 7d5d29e5f46511d5842e151f7a8d247878b3dda2 Mon Sep 17 00:00:00 2001 From: lizhanpeng Date: Fri, 31 Oct 2025 17:24:42 +0800 Subject: [PATCH 3/4] feat(backend): fix --- .../observability/infra/config/trace.go | 14 ++++++++++++-- .../observability/infra/config/trace_test.go | 19 ++++--------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/backend/modules/observability/infra/config/trace.go b/backend/modules/observability/infra/config/trace.go index 2c648dc2f..d6e43745c 100644 --- a/backend/modules/observability/infra/config/trace.go +++ b/backend/modules/observability/infra/config/trace.go @@ -10,6 +10,7 @@ import ( "github.com/coze-dev/coze-loop/backend/modules/observability/domain/component/config" "github.com/coze-dev/coze-loop/backend/modules/observability/domain/trace/entity/loop_span" "github.com/coze-dev/coze-loop/backend/pkg/conf" + "github.com/coze-dev/coze-loop/backend/pkg/json" "github.com/coze-dev/coze-loop/backend/pkg/logs" ) @@ -53,8 +54,17 @@ func (t *TraceConfigCenter) GetPlatformTenants(ctx context.Context) (*config.Pla func (t *TraceConfigCenter) GetPlatformSpansTrans(ctx context.Context, platformType loop_span.PlatformType) (loop_span.SpanTransCfgList, error) { cfg := new(config.SpanTransHandlerConfig) - if err := t.UnmarshalKey(ctx, platformSpanHandlerCfgKey, cfg); err != nil { - return nil, err + val := t.Get(ctx, platformSpanHandlerCfgKey) + if val == nil { + return nil, fmt.Errorf("config not found") + } + strVal, ok := val.(string) + if !ok { + return nil, fmt.Errorf("config not string") + } + // unmarshal to avoid data race + if err := json.Unmarshal([]byte(strVal), cfg); err != nil { + return nil, fmt.Errorf("fail to unmarshal config: %v", err) } ret := cfg.PlatformCfg[string(platformType)] for _, inheritance := range cfg.PlatformInheritance[string(platformType)] { diff --git a/backend/modules/observability/infra/config/trace_test.go b/backend/modules/observability/infra/config/trace_test.go index c83ee6148..317822b98 100644 --- a/backend/modules/observability/infra/config/trace_test.go +++ b/backend/modules/observability/infra/config/trace_test.go @@ -159,33 +159,22 @@ func TestTraceConfigCenter_GetPlatformSpansTrans(t *testing.T) { name: "get platform spans trans successfully", fieldsGetter: func(ctrl *gomock.Controller) fields { mockLoader := confmocks.NewMockIConfigLoader(ctrl) - mockLoader.EXPECT().UnmarshalKey(gomock.Any(), platformSpanHandlerCfgKey, gomock.Any()). - DoAndReturn(func(ctx context.Context, key string, v interface{}, opts ...interface{}) error { - cfg := v.(*config.SpanTransHandlerConfig) - cfg.PlatformCfg = map[string]loop_span.SpanTransCfgList{ - "test_platform": { - {}, - }, - } - return nil - }) + mockLoader.EXPECT().Get(gomock.Any(), platformSpanHandlerCfgKey).Return(`{"platform_cfg":{"test_platform":[]}}`) return fields{configLoader: mockLoader} }, args: args{ ctx: context.Background(), platformType: "test_platform", }, - want: loop_span.SpanTransCfgList{ - {}, - }, + want: loop_span.SpanTransCfgList{}, wantErr: false, }, { name: "unmarshal key failed", fieldsGetter: func(ctrl *gomock.Controller) fields { mockLoader := confmocks.NewMockIConfigLoader(ctrl) - mockLoader.EXPECT().UnmarshalKey(gomock.Any(), platformSpanHandlerCfgKey, gomock.Any()). - Return(fmt.Errorf("unmarshal error")) + mockLoader.EXPECT().Get(gomock.Any(), platformSpanHandlerCfgKey). + Return(nil) return fields{configLoader: mockLoader} }, args: args{ From 71ab06072b5e150121e96c37aac7c4883a5d7970 Mon Sep 17 00:00:00 2001 From: lizhanpeng Date: Mon, 3 Nov 2025 12:02:15 +0800 Subject: [PATCH 4/4] feat(backend): refactor --- .../observability/application/trace.go | 31 ++++++++----------- .../observability/infra/rpc/tag/tag.go | 1 + 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/backend/modules/observability/application/trace.go b/backend/modules/observability/application/trace.go index e3c3bd135..024b825e6 100644 --- a/backend/modules/observability/application/trace.go +++ b/backend/modules/observability/application/trace.go @@ -6,7 +6,6 @@ package application import ( "context" "strconv" - "sync" "time" "github.com/coze-dev/coze-loop/backend/infra/external/benefit" @@ -1024,41 +1023,37 @@ type GetDisplayInfoResponse struct { } func (t *TraceApplication) GetDisplayInfo(ctx context.Context, req *GetDisplayInfoRequest) GetDisplayInfoResponse { - resp := GetDisplayInfoResponse{} if len(req.UserIDs) == 0 && len(req.EvaluatorIDs) == 0 && len(req.TagKeyIDs) == 0 { - return resp + return GetDisplayInfoResponse{} } var ( - g errgroup.Group - lock sync.Mutex + g errgroup.Group + userMap map[string]*commdo.UserInfo + evalMap map[int64]*rpc.Evaluator + tagMap map[int64]*rpc.TagInfo ) g.Go(func() error { defer goroutine.Recovery(ctx) - _, userMap, _ := t.userSvc.GetUserInfo(ctx, req.UserIDs) - lock.Lock() - defer lock.Unlock() - resp.UserMap = userMap + _, userMap, _ = t.userSvc.GetUserInfo(ctx, req.UserIDs) return nil }) g.Go(func() error { defer goroutine.Recovery(ctx) - _, evalMap, _ := t.evalSvc.BatchGetEvaluatorVersions(ctx, &rpc.BatchGetEvaluatorVersionsParam{ + _, evalMap, _ = t.evalSvc.BatchGetEvaluatorVersions(ctx, &rpc.BatchGetEvaluatorVersionsParam{ WorkspaceID: req.WorkspaceID, EvaluatorVersionIds: req.EvaluatorIDs, }) - lock.Lock() - defer lock.Unlock() - resp.EvalMap = evalMap return nil }) g.Go(func() error { defer goroutine.Recovery(ctx) - tagMap, _ := t.tagSvc.BatchGetTagInfo(ctx, req.WorkspaceID, req.TagKeyIDs) - lock.Lock() - defer lock.Unlock() - resp.TagMap = tagMap + tagMap, _ = t.tagSvc.BatchGetTagInfo(ctx, req.WorkspaceID, req.TagKeyIDs) return nil }) _ = g.Wait() - return resp + return GetDisplayInfoResponse{ + UserMap: userMap, + EvalMap: evalMap, + TagMap: tagMap, + } } diff --git a/backend/modules/observability/infra/rpc/tag/tag.go b/backend/modules/observability/infra/rpc/tag/tag.go index e4c2a55e2..4ca6a8a95 100644 --- a/backend/modules/observability/infra/rpc/tag/tag.go +++ b/backend/modules/observability/infra/rpc/tag/tag.go @@ -63,6 +63,7 @@ func (t *TagRPCAdapter) BatchGetTagInfo(ctx context.Context, workspaceID int64, TagKeyIds: ids, }) if err != nil { + logs.CtxWarn(ctx, "failed to batch get tags: %v", err) return nil, err } else if len(res.TagInfoList) == 0 { return nil, fmt.Errorf("tag info not found")