@@ -12,9 +12,12 @@ import (
1212 "strings"
1313 "time"
1414
15+ "github.com/coze-dev/coze-loop/backend/infra/looptracer"
16+ "github.com/coze-dev/coze-loop/backend/infra/middleware/session"
1517 "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/component"
1618 "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/component/metrics"
1719 "github.com/coze-dev/coze-loop/backend/modules/evaluation/domain/entity"
20+ "github.com/coze-dev/coze-loop/backend/modules/evaluation/infra/tracer"
1821 "github.com/coze-dev/coze-loop/backend/modules/evaluation/pkg/errno"
1922 "github.com/coze-dev/coze-loop/backend/pkg/errorx"
2023 "github.com/coze-dev/coze-loop/backend/pkg/logs"
@@ -50,12 +53,16 @@ func (c *EvaluatorSourceCodeServiceImpl) Run(ctx context.Context, evaluator *ent
5053 var err error
5154 var code string
5255 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 ()
5659
5760 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 )
5966 }()
6067
6168 // 1. 验证评估器
@@ -77,37 +84,41 @@ func (c *EvaluatorSourceCodeServiceImpl) Run(ctx context.Context, evaluator *ent
7784}
7885
7986// 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 ) {
8188 if * output == nil {
8289 * output = & entity.EvaluatorOutputData {
8390 EvaluatorRunError : & entity.EvaluatorRunError {},
8491 }
8592 }
8693
87- if * err != nil {
94+ if * errInfo != nil {
8895 // 处理错误信息
8996 if (* output ).EvaluatorRunError == nil {
9097 (* output ).EvaluatorRunError = & entity.EvaluatorRunError {}
9198 }
92- statusErr , ok := errorx .FromStatusError (* err )
99+ statusErr , ok := errorx .FromStatusError (* errInfo )
93100 if ok {
94101 (* output ).EvaluatorRunError .Code = statusErr .Code ()
95102 (* output ).EvaluatorRunError .Message = statusErr .Error ()
96103 } else {
97104 (* output ).EvaluatorRunError .Code = errno .CodeExecutionFailedCode
98- (* output ).EvaluatorRunError .Message = (* err ).Error ()
105+ (* output ).EvaluatorRunError .Message = (* errInfo ).Error ()
99106 }
100107 }
101108
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+ })
111122}
112123
113124// validateEvaluator 验证评估器类型和版本
@@ -717,15 +728,25 @@ func (c *EvaluatorSourceCodeServiceImpl) validatePythonCode(ctx context.Context,
717728 // 构建Python语法检查代码,参考pyodide客户端的AST验证方式
718729 syntaxCheckCode := c .buildPythonSyntaxCheckCode (codeVersion .CodeContent )
719730
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+
720741 // 使用runtime执行语法检查,设置较短的超时时间
721742 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秒超时用于语法验证
723744 if err != nil {
724745 return fmt .Errorf ("python syntax validation failed: %w" , err )
725746 }
726747
727748 // 处理执行结果并解析stdout中的JSON
728- valid , errorMsg , err : = c .processSyntaxValidationExecutionResult (result )
749+ valid , errorMsg , err = c .processSyntaxValidationExecutionResult (result )
729750 if err != nil {
730751 return fmt .Errorf ("failed to process syntax validation result: %w" , err )
731752 }
@@ -759,15 +780,25 @@ func (c *EvaluatorSourceCodeServiceImpl) validateJavaScriptCode(ctx context.Cont
759780 // 构建JavaScript语法检查代码 (使用Builder模式)
760781 syntaxCheckCode := c .buildJavaScriptSyntaxCheckCode (codeVersion .CodeContent )
761782
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+
762793 // 使用runtime执行语法检查,设置较短的超时时间
763794 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秒超时
765796 if err != nil {
766797 return fmt .Errorf ("javascript syntax validation failed: %w" , err )
767798 }
768799
769800 // 使用统一的结果处理方法 (与Python保持一致)
770- valid , errorMsg , err : = c .processSyntaxValidationExecutionResult (result )
801+ valid , errorMsg , err = c .processSyntaxValidationExecutionResult (result )
771802 if err != nil {
772803 return fmt .Errorf ("failed to process syntax validation result: %w" , err )
773804 }
@@ -1125,8 +1156,9 @@ func (c *EvaluatorSourceCodeServiceImpl) validateJavaScriptExecEvaluationFunctio
11251156
11261157
11271158
1128- // evaluatorSpan 简化的span结构
1159+ // evaluatorSpan 评估器span包装器
11291160type evaluatorSpan struct {
1161+ looptracer.Span
11301162}
11311163
11321164// ReportCodeRootSpanRequest Code评估器专用的上报请求结构
@@ -1139,8 +1171,95 @@ type ReportCodeRootSpanRequest struct {
11391171 code string // 评估器代码内容
11401172}
11411173
1142- // reportCodeRootSpan 上报Code评估器的根节点trace - 简化实现
1174+ // reportCodeRootSpan 上报Code评估器的根节点trace
11431175func (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 )
11461265}
0 commit comments