-
Notifications
You must be signed in to change notification settings - Fork 1
fix(tracing): record session outcomes on root spans #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,8 @@ impl TranslatorFactory for PiTranslatorFactory { | |
| external_parent: None, | ||
| opened: false, | ||
| turn: None, | ||
| turn_output: None, | ||
| last_turn_output: None, | ||
| turn_seq: 0, | ||
| llm_seq: 0, | ||
| total_tools: 0, | ||
|
|
@@ -309,6 +311,8 @@ struct PiTranslator { | |
| external_parent: Option<String>, | ||
| opened: bool, | ||
| turn: Option<(String, Value)>, | ||
| turn_output: Option<Value>, | ||
| last_turn_output: Option<Value>, | ||
| turn_seq: u32, | ||
| llm_seq: u32, | ||
| total_tools: u32, | ||
|
|
@@ -667,6 +671,11 @@ impl PiTranslator { | |
| .error_message | ||
| .clone() | ||
| .filter(|_| matches!(message.stop_reason.as_deref(), Some("error" | "aborted"))); | ||
| // Turn and root outcomes come from the latest completed assistant | ||
| // message; errored or aborted messages are not outcomes. | ||
| if error.is_none() { | ||
| self.turn_output = Some(output.clone()); | ||
|
Comment on lines
+676
to
+677
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a Pi turn emits a successful intermediate assistant message (for example, a tool call) and its later assistant message ends with Useful? React with 👍 / 👎. |
||
| } | ||
| let ttft = pending | ||
| .first_token_ms | ||
| .map(|first| (first - pending.start_ms) as f64 / 1000.0); | ||
|
|
@@ -842,10 +851,15 @@ impl PiTranslator { | |
| let Some((id, _)) = turn else { | ||
| return vec![]; | ||
| }; | ||
| let output = self.turn_output.take(); | ||
| if output.is_some() { | ||
| self.last_turn_output = output.clone(); | ||
| } | ||
| vec![SpanOp::Merge(SpanRow { | ||
| span_id: id, | ||
| root_span_id: self.effective_root_span_id.clone(), | ||
| end_ms: Some(ts), | ||
| output, | ||
| error, | ||
| ..Default::default() | ||
| })] | ||
|
|
@@ -859,6 +873,7 @@ impl PiTranslator { | |
| span_id: self.root_span_id.clone(), | ||
| root_span_id: self.effective_root_span_id.clone(), | ||
| end_ms: Some(ts), | ||
| output: self.last_turn_output.take(), | ||
| metadata: Some( | ||
| json!({"total_turns":self.turn_seq,"total_tool_calls":self.total_tools}), | ||
| ), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the Stop hook supplies an empty
last_assistant_messagebecause the final assistant row is written afterward, this condition records""as the session outcome. The existingclaude_groups_streamed_rows_and_reads_late_final_output_at_session_endflow demonstrates that SessionEnd can subsequently read the real"done"output, butemit_mainnever refresheslast_turn_output, so the root closes with an empty output instead of the actual answer. Derive or update the tracked outcome when those late transcript rows are consumed.Useful? React with 👍 / 👎.