zuozhiw commented on code in PR #5376:
URL: https://github.com/apache/texera/pull/5376#discussion_r3680509406


##########
amber/src/main/scala/org/apache/texera/web/service/WorkflowService.scala:
##########
@@ -178,126 +180,157 @@ class WorkflowService(
     new WorkflowContext(workflowId = workflowId, cuid = Some(computingUnitId))
   }
 
+  /** Sets up and launches a workflow execution inside a run-level span so
+    * setup-path logs carry its trace id. The span covers the synchronous
+    * setup and the handoff to async execution via `executeWorkflow()`; it
+    * does not span the full async run. The real execution failure is
+    * recorded onto the current span from `errorHandler`.
+    */
   def initExecutionService(
       req: WorkflowExecuteRequest,
       userOpt: Option[User],
       sessionUri: URI
   ): Unit = {
+    val span = TexeraTracer.tracer
+      .spanBuilder("WorkflowService.initExecutionService")
+      .setAttribute("texera.workflow.id", workflowId.id.toString)

Review Comment:
   minor: use standard keys instead of plain string



##########
amber/src/main/scala/org/apache/texera/web/service/WorkflowService.scala:
##########
@@ -183,6 +185,25 @@ class WorkflowService(
       userOpt: Option[User],
       sessionUri: URI
   ): Unit = {
+    TexeraTracer.withSpan(
+      "workflow.execute",
+      _.setAttribute("texera.workflow.id", workflowId.id.toString)
+    ) { span =>
+      initExecutionServiceSpanned(req, userOpt, sessionUri, span)

Review Comment:
   👍 



##########
amber/src/main/scala/org/apache/texera/web/service/WorkflowService.scala:
##########
@@ -183,6 +185,25 @@ class WorkflowService(
       userOpt: Option[User],
       sessionUri: URI
   ): Unit = {
+    TexeraTracer.withSpan(
+      "workflow.execute",

Review Comment:
   👍 



##########
amber/src/main/scala/org/apache/texera/web/service/WorkflowService.scala:
##########
@@ -178,126 +180,157 @@ class WorkflowService(
     new WorkflowContext(workflowId = workflowId, cuid = Some(computingUnitId))
   }
 
+  /** Sets up and launches a workflow execution inside a run-level span so
+    * setup-path logs carry its trace id. The span covers the synchronous
+    * setup and the handoff to async execution via `executeWorkflow()`; it
+    * does not span the full async run. The real execution failure is
+    * recorded onto the current span from `errorHandler`.
+    */
   def initExecutionService(
       req: WorkflowExecuteRequest,
       userOpt: Option[User],
       sessionUri: URI
   ): Unit = {
+    val span = TexeraTracer.tracer
+      .spanBuilder("WorkflowService.initExecutionService")
+      .setAttribute("texera.workflow.id", workflowId.id.toString)
+      .startSpan()
+    val scope = span.makeCurrent()
+    try {
 
-    if (executionService.hasValue) {
-      executionService.getValue.unsubscribeAll()
-    }
+      if (executionService.hasValue) {
+        executionService.getValue.unsubscribeAll()
+      }
 
-    val (uidOpt, userEmailOpt) = userOpt.map(user => (user.getUid, 
user.getEmail)).unzip
+      val (uidOpt, userEmailOpt) = userOpt.map(user => (user.getUid, 
user.getEmail)).unzip
 
-    // uid is NOT NULL in the DB; fail early here rather than letting the 
insert fail downstream.
-    val uid = uidOpt.getOrElse(
-      throw new IllegalArgumentException(
-        "Cannot start execution: a user id (uid) is required but none was 
provided."
+      // uid is NOT NULL in the DB; fail early here rather than letting the 
insert fail downstream.
+      val uid = uidOpt.getOrElse(
+        throw new IllegalArgumentException(
+          "Cannot start execution: a user id (uid) is required but none was 
provided."
+        )
       )
-    )
-
-    val workflowContext: WorkflowContext = createWorkflowContext()
-    var coordinatorConf = CoordinatorConfig.default
-
-    // clean up results from previous run
-    val previousExecutionId =
-      WorkflowExecutionService.getLatestExecutionId(workflowId, 
req.computingUnitId)
-    previousExecutionId.foreach(eid => {
-      clearExecutionResources(eid)
-    }) // TODO: change this behavior after enabling cache.
-
-    workflowContext.executionId = 
ExecutionsMetadataPersistService.insertNewExecution(
-      workflowContext.workflowId,
-      uid,
-      req.executionName,
-      convertToJson(req.engineVersion),
-      req.computingUnitId
-    )
 
-    if (ApplicationConfig.faultToleranceLogRootFolder.isDefined) {
-      val writeLocation = 
ApplicationConfig.faultToleranceLogRootFolder.get.resolve(
-        s"${workflowContext.workflowId}/${workflowContext.executionId}/"
+      val workflowContext: WorkflowContext = createWorkflowContext()
+      var coordinatorConf = CoordinatorConfig.default
+
+      // clean up results from previous run
+      val previousExecutionId =
+        WorkflowExecutionService.getLatestExecutionId(workflowId, 
req.computingUnitId)
+      previousExecutionId.foreach(eid => {
+        clearExecutionResources(eid)
+      }) // TODO: change this behavior after enabling cache.
+
+      workflowContext.executionId = 
ExecutionsMetadataPersistService.insertNewExecution(
+        workflowContext.workflowId,
+        uid,
+        req.executionName,
+        convertToJson(req.engineVersion),
+        req.computingUnitId
       )
-      
ExecutionsMetadataPersistService.tryUpdateExistingExecution(workflowContext.executionId)
 {
-        execution => execution.setLogLocation(writeLocation.toString)
+      span.setAttribute("texera.execution.id", 
workflowContext.executionId.id.toString)
+      // A run has started: record the start counter and stamp its start time.
+      org.apache.texera.web.observability.WorkflowMetricsRecorder
+        .onStart(workflowContext.executionId)
+
+      if (ApplicationConfig.faultToleranceLogRootFolder.isDefined) {
+        val writeLocation = 
ApplicationConfig.faultToleranceLogRootFolder.get.resolve(
+          s"${workflowContext.workflowId}/${workflowContext.executionId}/"
+        )
+        
ExecutionsMetadataPersistService.tryUpdateExistingExecution(workflowContext.executionId)
 {
+          execution => execution.setLogLocation(writeLocation.toString)
+        }
+        coordinatorConf = coordinatorConf.copy(faultToleranceConfOpt =
+          Some(FaultToleranceConfig(writeTo = writeLocation))
+        )
       }
-      coordinatorConf = coordinatorConf.copy(faultToleranceConfOpt =
-        Some(FaultToleranceConfig(writeTo = writeLocation))
-      )
-    }
-    if (req.replayFromExecution.isDefined) {
-      val replayInfo = req.replayFromExecution.get
-      ExecutionsMetadataPersistService
-        .tryGetExistingExecution(ExecutionIdentity(replayInfo.eid))
-        .foreach { execution =>
-          val readLocation = new URI(execution.getLogLocation)
-          coordinatorConf = coordinatorConf.copy(stateRestoreConfOpt =
-            Some(
-              StateRestoreConfig(
-                readFrom = readLocation,
-                replayDestination = 
EmbeddedControlMessageIdentity(replayInfo.interaction)
+      if (req.replayFromExecution.isDefined) {
+        val replayInfo = req.replayFromExecution.get
+        ExecutionsMetadataPersistService
+          .tryGetExistingExecution(ExecutionIdentity(replayInfo.eid))
+          .foreach { execution =>
+            val readLocation = new URI(execution.getLogLocation)
+            coordinatorConf = coordinatorConf.copy(stateRestoreConfOpt =
+              Some(
+                StateRestoreConfig(
+                  readFrom = readLocation,
+                  replayDestination = 
EmbeddedControlMessageIdentity(replayInfo.interaction)
+                )
               )
             )
-          )
-        }
-    }
+          }
+      }
 
-    val executionStateStore = new ExecutionStateStore()
-    // assign execution id to find the execution from DB in case the 
constructor fails.
-    executionStateStore.metadataStore.updateState(state =>
-      state.withExecutionId(workflowContext.executionId)
-    )
-    val errorHandler: Throwable => Unit = { t =>
-      {
-        val fromActorOpt = t match {
-          case ex: WorkflowRuntimeException =>
-            ex.relatedWorkerId
-          case other =>
-            None
-        }
-        val (operatorId, workerId) = getOperatorFromActorIdOpt(fromActorOpt)
-        logger.error("error during execution", t)
-        executionStateStore.statsStore.updateState(stats =>
-          stats.withEndTimeStamp(System.currentTimeMillis())
-        )
-        executionStateStore.metadataStore.updateState { metadataStore =>
-          updateWorkflowState(FAILED, metadataStore).addFatalErrors(
-            WorkflowFatalError(
-              EXECUTION_FAILURE,
-              Timestamp(Instant.now),
-              t.toString,
-              getStackTraceWithAllCauses(t),
-              operatorId,
-              workerId
-            )
+      val executionStateStore = new ExecutionStateStore()
+      // assign execution id to find the execution from DB in case the 
constructor fails.
+      executionStateStore.metadataStore.updateState(state =>
+        state.withExecutionId(workflowContext.executionId)
+      )
+      val errorHandler: Throwable => Unit = { t =>
+        {

Review Comment:
   this error handler needs to be extra careful becaue it's passed around as an 
argument to WorkflowExecutionService, and it will be called beyond this 
function's lifecycle, we really need to check who calls it. when they call it 
this specific span object we get here might already ended after this function 
ends. this handler is also used locally, that is fine, but if other places call 
it then we have troubles and the error is not attached to the correct span
   
   this one is a bit tricky, as we need to inspect the places that invokes this 
error handler and see what spans they have, then we either call span.current() 
again inside this span (but need to make sure the callers has good spans...), 
or has to pass in a span as optinal argument,  please check how we are using 
this handler and see what's the best way to handle this, maybe passing such 
error handler around is not a good error handling method



##########
amber/src/main/scala/org/apache/texera/web/service/WorkflowService.scala:
##########
@@ -183,6 +185,25 @@ class WorkflowService(
       userOpt: Option[User],
       sessionUri: URI
   ): Unit = {
+    TexeraTracer.withSpan(
+      "workflow.execute",
+      _.setAttribute("texera.workflow.id", workflowId.id.toString)
+    ) { span =>

Review Comment:
   left another comment on the error hanlder callback, please check



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to