-
Notifications
You must be signed in to change notification settings - Fork 66
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
Expose active traces through telemetry server #87
Changes from all commits
10fec1b
4b81143
bf4d711
5114703
0a60af5
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 |
---|---|---|
@@ -0,0 +1,94 @@ | ||
//! Outputs telemetry spans in Chrome JSON trace format (i.e. the format used by about:tracing). | ||
use super::SharedSpanHandle; | ||
use std::time::SystemTime; | ||
|
||
/// Outputs a slice of shared spans as a Chrome JSON trace log. | ||
pub(crate) fn spans_to_trace_events(epoch: SystemTime, spans: &[SharedSpanHandle]) -> String { | ||
use cf_rustracing::span::InspectableSpan; | ||
|
||
let mut log_builder = TraceLogBuilder::new(); | ||
|
||
let end_timestamp = epoch | ||
.elapsed() | ||
.ok() | ||
.and_then(|x| u64::try_from(x.as_micros()).ok()) | ||
.unwrap_or(u64::MAX); | ||
|
||
for span in spans { | ||
let span_ref = span.read(); | ||
let span_state = span_ref.context().unwrap().state(); | ||
let trace_id = span_state.trace_id().to_string(); | ||
let name = span_ref.operation_name(); | ||
|
||
let start_ts = span_ref | ||
.start_time() | ||
.duration_since(epoch) | ||
.ok() | ||
.and_then(|x| u64::try_from(x.as_micros()).ok()) | ||
.unwrap_or_default(); | ||
|
||
let end_ts = span_ref | ||
.finish_time() | ||
.and_then(|x| x.duration_since(epoch).ok()) | ||
.and_then(|x| u64::try_from(x.as_micros()).ok()) | ||
.unwrap_or(end_timestamp); | ||
|
||
log_builder.write_event(&trace_id, name, "", TraceEventType::Begin, start_ts); | ||
log_builder.write_event(&trace_id, name, "", TraceEventType::End, end_ts); | ||
} | ||
|
||
log_builder.finalize(end_timestamp) | ||
} | ||
|
||
#[derive(Copy, Clone)] | ||
enum TraceEventType { | ||
Begin, | ||
End, | ||
} | ||
|
||
fn escape(s: &str) -> String { | ||
s.escape_default().to_string() | ||
} | ||
|
||
struct TraceLogBuilder { | ||
out: String, | ||
} | ||
|
||
impl TraceLogBuilder { | ||
fn new() -> Self { | ||
TraceLogBuilder { | ||
out: "[".to_string(), | ||
} | ||
} | ||
|
||
fn write_event( | ||
&mut self, | ||
trace_id: &str, | ||
name: &str, | ||
category: &str, | ||
event_type: TraceEventType, | ||
timestamp_us: u64, | ||
) { | ||
self.out.push_str(&format!( | ||
"{{\"pid\":1,\"name\":\"{}\",\"cat\":\"{}\",\"ph\":\"{}\",\"ts\":{},\"id\":\"{}\"}},", | ||
escape(name), | ||
escape(category), | ||
match event_type { | ||
TraceEventType::Begin => "B", | ||
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. async events (those with 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. Despite the name, async events don't have the right semantics for what we want to express here. Regular events are enough for the visualisation. |
||
TraceEventType::End => "E", | ||
}, | ||
timestamp_us, | ||
trace_id, | ||
)); | ||
} | ||
|
||
fn finalize(mut self, end_timestamp: u64) -> String { | ||
self.out.push_str(&format!( | ||
"{{\"pid\":1,\"name\":\"Trace dump requested\",\"ph\":\"i\",\"ts\":{},\"s\":\"g\"}}", | ||
end_timestamp, | ||
)); | ||
|
||
self.out.push(']'); | ||
self.out | ||
} | ||
} |
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.
It would be nice to also emit the trace tags as
args
, but I understand if you don't have time to implement this right now.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.
Tags are typed, so we'd need to generate JSON objects with serde or something rather than this quick and dirty approach.
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.
Yeah, let's leave that for a future iteration