Convert opencode transcripts to otel (or agent) traces
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Include all parsed log data in span output

- Added full content field to SpanDisplay (was truncated preview)
- Added thinking field to SpanDisplay (was missing entirely)
- Added opencode.content attribute to OTLP exporter
- Both stdout output and OTLP export now include complete log data
- All fields from ParsedLogEntry are now captured in spans

rektide d9a8f640 3e1090a6

+12 -8
+2
src/exporter.rs
··· 132 132 attributes.push(KeyValue::new("opencode.thinking", thinking.clone())); 133 133 } 134 134 135 + attributes.push(KeyValue::new("opencode.content", entry.content.clone())); 136 + 135 137 let span_name = if let Some(tool_name) = &tool_name_str { 136 138 format!("tools/call {}", tool_name) 137 139 } else {
+10 -8
src/formatter.rs
··· 14 14 pub operation_name: Option<String>, 15 15 pub timestamp: String, 16 16 pub duration_ms: Option<u64>, 17 - pub content_preview: String, 17 + pub content: String, 18 + pub thinking: Option<String>, 18 19 pub attributes: Vec<(String, String)>, 19 20 } 20 21 21 22 impl SpanDisplay { 22 23 pub fn from_entry(entry: &ParsedLogEntry) -> Self { 23 - let content_preview = if entry.content.len() > 100 { 24 - format!("{}...", &entry.content[..100]) 25 - } else { 26 - entry.content.clone() 27 - }; 28 - 29 24 let mut attributes = vec![ 30 25 ("mcp.session.id".to_string(), entry.session_id.clone()), 31 26 ("network.transport".to_string(), "tcp".to_string()), ··· 50 45 )); 51 46 } 52 47 48 + if let Some(thinking) = &entry.thinking { 49 + attributes.push(("opencode.thinking".to_string(), thinking.clone())); 50 + } 51 + 52 + attributes.push(("opencode.content".to_string(), entry.content.clone())); 53 + 53 54 let span_name = if let Some(tool_name) = &tool_name_str { 54 55 format!("tools/call {}", tool_name) 55 56 } else { ··· 70 71 .map(|_| "execute_tool".to_string()), 71 72 timestamp: entry.timestamp.to_string(), 72 73 duration_ms: entry.duration_ms, 73 - content_preview, 74 + content: entry.content.clone(), 75 + thinking: entry.thinking.clone(), 74 76 attributes, 75 77 } 76 78 }