@@ -12,9 +12,12 @@ import (
12
12
"strings"
13
13
"time"
14
14
15
+ "github.com/coze-dev/coze-loop/backend/infra/looptracer"
16
+ "github.com/coze-dev/coze-loop/backend/infra/middleware/session"
15
17
"github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/component"
16
18
"github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/component/metrics"
17
19
"github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/entity"
20
+ "github.com/coze-dev/coze-loop/backend/modules/evaluation/infra/tracer"
18
21
"github.com/coze-dev/coze-loop/backend/modules/evaluation/pkg/errno"
19
22
"github.com/coze-dev/coze-loop/backend/pkg/errorx"
20
23
"github.com/coze-dev/coze-loop/backend/pkg/logs"
@@ -50,12 +53,16 @@ func (c *EvaluatorSourceCodeServiceImpl) Run(ctx context.Context, evaluator *ent
50
53
var err error
51
54
var code string
52
55
startTime := time .Now ()
53
- // 直接创建一个简单的span,避免依赖evaluator_source_prompt_impl.go中的函数
54
- rootSpan := & evaluatorSpan {}
55
- traceID = "code-evaluator-trace"
56
+ // 创建trace span
57
+ rootSpan , ctx := c . newEvaluatorSpan ( ctx , evaluator . Name , "LoopEvaluation" , strconv . FormatInt ( evaluator . SpaceID , 10 ), false )
58
+ traceID = rootSpan . GetTraceID ()
56
59
57
60
defer func () {
58
- c .handleRunDefer (ctx , rootSpan , & output , & err , input , evaluator , code , runStatus )
61
+ var errInfo error
62
+ if err != nil {
63
+ errInfo = err
64
+ }
65
+ c .handleRunDefer (ctx , rootSpan , & output , & errInfo , input , evaluator , code , runStatus )
59
66
}()
60
67
61
68
// 1. 验证评估器
@@ -77,37 +84,41 @@ func (c *EvaluatorSourceCodeServiceImpl) Run(ctx context.Context, evaluator *ent
77
84
}
78
85
79
86
// handleRunDefer 处理Run方法的defer逻辑
80
- func (c * EvaluatorSourceCodeServiceImpl ) handleRunDefer (ctx context.Context , rootSpan * evaluatorSpan , output * * entity.EvaluatorOutputData , err * error , input * entity.EvaluatorInputData , evaluator * entity.Evaluator , code string , runStatus entity.EvaluatorRunStatus ) {
87
+ func (c * EvaluatorSourceCodeServiceImpl ) handleRunDefer (ctx context.Context , rootSpan * evaluatorSpan , output * * entity.EvaluatorOutputData , errInfo * error , input * entity.EvaluatorInputData , evaluator * entity.Evaluator , code string , runStatus entity.EvaluatorRunStatus ) {
81
88
if * output == nil {
82
89
* output = & entity.EvaluatorOutputData {
83
90
EvaluatorRunError : & entity.EvaluatorRunError {},
84
91
}
85
92
}
86
93
87
- if * err != nil {
94
+ if * errInfo != nil {
88
95
// 处理错误信息
89
96
if (* output ).EvaluatorRunError == nil {
90
97
(* output ).EvaluatorRunError = & entity.EvaluatorRunError {}
91
98
}
92
- statusErr , ok := errorx .FromStatusError (* err )
99
+ statusErr , ok := errorx .FromStatusError (* errInfo )
93
100
if ok {
94
101
(* output ).EvaluatorRunError .Code = statusErr .Code ()
95
102
(* output ).EvaluatorRunError .Message = statusErr .Error ()
96
103
} else {
97
104
(* output ).EvaluatorRunError .Code = errno .CodeExecutionFailedCode
98
- (* output ).EvaluatorRunError .Message = (* err ).Error ()
105
+ (* output ).EvaluatorRunError .Message = (* errInfo ).Error ()
99
106
}
100
107
}
101
108
102
- // 上报trace - 暂时跳过trace上报,避免复杂的依赖
103
- // rootSpan.reportCodeRootSpan(ctx, &ReportCodeRootSpanRequest{
104
- // input: input,
105
- // output: *output,
106
- // runStatus: runStatus,
107
- // evaluatorVersion: evaluator.CodeEvaluatorVersion,
108
- // errInfo: errInfo,
109
- // code: code, // 构建后的完整代码
110
- // })
109
+ // 上报trace
110
+ var finalErr error
111
+ if errInfo != nil {
112
+ finalErr = * errInfo
113
+ }
114
+ rootSpan .reportCodeRootSpan (ctx , & ReportCodeRootSpanRequest {
115
+ input : input ,
116
+ output : * output ,
117
+ runStatus : runStatus ,
118
+ evaluatorVersion : evaluator .CodeEvaluatorVersion ,
119
+ errInfo : finalErr ,
120
+ code : code , // 构建后的完整代码
121
+ })
111
122
}
112
123
113
124
// validateEvaluator 验证评估器类型和版本
@@ -717,15 +728,25 @@ func (c *EvaluatorSourceCodeServiceImpl) validatePythonCode(ctx context.Context,
717
728
// 构建Python语法检查代码,参考pyodide客户端的AST验证方式
718
729
syntaxCheckCode := c .buildPythonSyntaxCheckCode (codeVersion .CodeContent )
719
730
731
+ var result * entity.ExecutionResult
732
+ var valid bool
733
+ var errorMsg string
734
+
735
+ // 创建语法检查的span
736
+ syntaxCheckSpan , syntaxCtx := c .newEvaluatorSpan (ctx , "PythonSyntaxCheck" , "LoopEvaluation" , strconv .FormatInt (evaluator .SpaceID , 10 ), true )
737
+ defer func () {
738
+ c .reportSyntaxCheckSpan (syntaxCtx , syntaxCheckSpan , "python" , codeVersion .CodeContent , syntaxCheckCode , result , valid , errorMsg , err )
739
+ }()
740
+
720
741
// 使用runtime执行语法检查,设置较短的超时时间
721
742
ext := c .buildExtParams (evaluator )
722
- result , err : = runtime .RunCode (ctx , syntaxCheckCode , "python" , 10000 , ext ) // 10秒超时用于语法验证
743
+ result , err = runtime .RunCode (syntaxCtx , syntaxCheckCode , "python" , 10000 , ext ) // 10秒超时用于语法验证
723
744
if err != nil {
724
745
return fmt .Errorf ("python syntax validation failed: %w" , err )
725
746
}
726
747
727
748
// 处理执行结果并解析stdout中的JSON
728
- valid , errorMsg , err : = c .processSyntaxValidationExecutionResult (result )
749
+ valid , errorMsg , err = c .processSyntaxValidationExecutionResult (result )
729
750
if err != nil {
730
751
return fmt .Errorf ("failed to process syntax validation result: %w" , err )
731
752
}
@@ -759,15 +780,25 @@ func (c *EvaluatorSourceCodeServiceImpl) validateJavaScriptCode(ctx context.Cont
759
780
// 构建JavaScript语法检查代码 (使用Builder模式)
760
781
syntaxCheckCode := c .buildJavaScriptSyntaxCheckCode (codeVersion .CodeContent )
761
782
783
+ var result * entity.ExecutionResult
784
+ var valid bool
785
+ var errorMsg string
786
+
787
+ // 创建语法检查的span
788
+ syntaxCheckSpan , syntaxCtx := c .newEvaluatorSpan (ctx , "JavaScriptSyntaxCheck" , "LoopEvaluation" , strconv .FormatInt (evaluator .SpaceID , 10 ), true )
789
+ defer func () {
790
+ c .reportSyntaxCheckSpan (syntaxCtx , syntaxCheckSpan , "javascript" , codeVersion .CodeContent , syntaxCheckCode , result , valid , errorMsg , err )
791
+ }()
792
+
762
793
// 使用runtime执行语法检查,设置较短的超时时间
763
794
ext := c .buildExtParams (evaluator )
764
- result , err : = runtime .RunCode (ctx , syntaxCheckCode , "js" , 10000 , ext ) // 与Python保持一致的10秒超时
795
+ result , err = runtime .RunCode (syntaxCtx , syntaxCheckCode , "js" , 10000 , ext ) // 与Python保持一致的10秒超时
765
796
if err != nil {
766
797
return fmt .Errorf ("javascript syntax validation failed: %w" , err )
767
798
}
768
799
769
800
// 使用统一的结果处理方法 (与Python保持一致)
770
- valid , errorMsg , err : = c .processSyntaxValidationExecutionResult (result )
801
+ valid , errorMsg , err = c .processSyntaxValidationExecutionResult (result )
771
802
if err != nil {
772
803
return fmt .Errorf ("failed to process syntax validation result: %w" , err )
773
804
}
@@ -1125,8 +1156,9 @@ func (c *EvaluatorSourceCodeServiceImpl) validateJavaScriptExecEvaluationFunctio
1125
1156
1126
1157
1127
1158
1128
- // evaluatorSpan 简化的span结构
1159
+ // evaluatorSpan 评估器span包装器
1129
1160
type evaluatorSpan struct {
1161
+ looptracer.Span
1130
1162
}
1131
1163
1132
1164
// ReportCodeRootSpanRequest Code评估器专用的上报请求结构
@@ -1139,8 +1171,95 @@ type ReportCodeRootSpanRequest struct {
1139
1171
code string // 评估器代码内容
1140
1172
}
1141
1173
1142
- // reportCodeRootSpan 上报Code评估器的根节点trace - 简化实现
1174
+ // reportCodeRootSpan 上报Code评估器的根节点trace
1143
1175
func (e * evaluatorSpan ) reportCodeRootSpan (ctx context.Context , request * ReportCodeRootSpanRequest ) {
1144
- // 暂时跳过实际的trace上报,只做日志记录
1145
- logs .CtxInfo (ctx , "Code evaluator execution completed, status: %v" , request .runStatus )
1176
+ e .SetInput (ctx , tracer .Convert2TraceString (request .input ))
1177
+ if request .output != nil {
1178
+ e .SetOutput (ctx , tracer .Convert2TraceString (request .output .EvaluatorResult ))
1179
+ }
1180
+ switch request .runStatus {
1181
+ case entity .EvaluatorRunStatusSuccess :
1182
+ e .SetStatusCode (ctx , 0 )
1183
+ case entity .EvaluatorRunStatusFail :
1184
+ e .SetStatusCode (ctx , int (entity .EvaluatorRunStatusFail ))
1185
+ e .SetError (ctx , request .errInfo )
1186
+ default :
1187
+ e .SetStatusCode (ctx , 0 ) // 默认为成功
1188
+ }
1189
+ tags := make (map [string ]interface {}, 0 )
1190
+ tags ["evaluator_id" ] = request .evaluatorVersion .EvaluatorID
1191
+ tags ["evaluator_version" ] = request .evaluatorVersion .Version
1192
+ tags ["code_content" ] = request .code // 添加代码内容到trace
1193
+ e .SetCallType ("Evaluator" )
1194
+ userIDInContext := session .UserIDInCtxOrEmpty (ctx )
1195
+ if userIDInContext != "" {
1196
+ e .SetUserID (ctx , userIDInContext )
1197
+ }
1198
+ e .SetTags (ctx , tags )
1199
+ e .Finish (ctx )
1200
+ }
1201
+
1202
+ // newEvaluatorSpan 创建评估器span
1203
+ func (c * EvaluatorSourceCodeServiceImpl ) newEvaluatorSpan (ctx context.Context , spanName , spanType , spaceID string , asyncChild bool ) (* evaluatorSpan , context.Context ) {
1204
+ var evalSpan looptracer.Span
1205
+ var nctx context.Context
1206
+ if asyncChild {
1207
+ nctx , evalSpan = looptracer .GetTracer ().StartSpan (ctx , spanName , spanType , looptracer .WithSpanWorkspaceID (spaceID ))
1208
+ } else {
1209
+ nctx , evalSpan = looptracer .GetTracer ().StartSpan (ctx , spanName , spanType , looptracer .WithStartNewTrace (), looptracer .WithSpanWorkspaceID (spaceID ))
1210
+ }
1211
+
1212
+ return & evaluatorSpan {
1213
+ Span : evalSpan ,
1214
+ }, nctx
1215
+ }
1216
+
1217
+ // reportSyntaxCheckSpan 上报语法检查的trace信息
1218
+ func (c * EvaluatorSourceCodeServiceImpl ) reportSyntaxCheckSpan (ctx context.Context , span * evaluatorSpan , language , userCode , syntaxCheckCode string , result * entity.ExecutionResult , valid bool , errorMsg string , err error ) {
1219
+ // 设置输入:用户代码
1220
+ span .SetInput (ctx , tracer .Convert2TraceString (map [string ]interface {}{
1221
+ "user_code" : userCode ,
1222
+ "language" : language ,
1223
+ }))
1224
+
1225
+ // 设置输出:语法检查结果
1226
+ output := map [string ]interface {}{
1227
+ "valid" : valid ,
1228
+ }
1229
+ if errorMsg != "" {
1230
+ output ["error" ] = errorMsg
1231
+ }
1232
+ if result != nil && result .Output != nil {
1233
+ output ["stdout" ] = result .Output .Stdout
1234
+ output ["stderr" ] = result .Output .Stderr
1235
+ output ["ret_val" ] = result .Output .RetVal
1236
+ }
1237
+ span .SetOutput (ctx , tracer .Convert2TraceString (output ))
1238
+
1239
+ // 设置状态码
1240
+ if err != nil {
1241
+ span .SetStatusCode (ctx , errno .CodeExecutionFailedCode )
1242
+ span .SetError (ctx , err )
1243
+ } else if ! valid {
1244
+ span .SetStatusCode (ctx , errno .InvalidInputDataCode )
1245
+ span .SetError (ctx , fmt .Errorf ("syntax validation failed: %s" , errorMsg ))
1246
+ } else {
1247
+ span .SetStatusCode (ctx , 0 )
1248
+ }
1249
+
1250
+ // 设置标签
1251
+ tags := map [string ]interface {}{
1252
+ "language" : language ,
1253
+ "syntax_check_code" : syntaxCheckCode ,
1254
+ "validation_result" : valid ,
1255
+ }
1256
+ span .SetTags (ctx , tags )
1257
+ span .SetCallType ("Evaluator" )
1258
+
1259
+ userIDInContext := session .UserIDInCtxOrEmpty (ctx )
1260
+ if userIDInContext != "" {
1261
+ span .SetUserID (ctx , userIDInContext )
1262
+ }
1263
+
1264
+ span .Finish (ctx )
1146
1265
}
0 commit comments