Skip to content
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

Support trace-level sampling #7

Merged
merged 2 commits into from
Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions tracing-honeycomb/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tracing-honeycomb"
version = "0.2.0"
version = "0.2.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw 0.2 isn't even out yet, see #5

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.2 is out, I just never published it (sorry, 2020 has been.. very 2020 recently) https://github.com/inanna-malick/tracing-honeycomb/blob/master/tracing-honeycomb/Cargo.toml#L3

authors = ["Inanna Malick <[email protected]>"]
edition = "2018"
description = "Honeycomb.io tracing layer for multiprocess telemetry"
Expand All @@ -13,7 +13,7 @@ readme = "README.md"
[dependencies]
tracing = "0.1.12"
tracing-core = "0.1.9"
tracing-distributed = { path = "../tracing-distributed" , version = "0.2.0"}
tracing-distributed = { path = "../tracing-distributed", version = "0.2.0" }
libhoney-rust = "0.1.3"
rand = "0.7"
chrono = "0.4.9"
Expand Down
25 changes: 19 additions & 6 deletions tracing-honeycomb/src/honeycomb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ use tracing_distributed::{Event, Span, Telemetry};
#[derive(Debug)]
pub struct HoneycombTelemetry {
honeycomb_client: Mutex<libhoney::Client<libhoney::transmission::Transmission>>,
sample_rate: usize,
}

impl HoneycombTelemetry {
pub(crate) fn new(cfg: libhoney::Config) -> Self {
pub(crate) fn new(cfg: libhoney::Config, sample_rate: usize) -> Self {
let honeycomb_client = libhoney::init(cfg);

// publishing requires &mut so just mutex-wrap it
// FIXME: may not be performant, investigate options (eg mpsc)
let honeycomb_client = Mutex::new(honeycomb_client);

HoneycombTelemetry { honeycomb_client }
HoneycombTelemetry { honeycomb_client, sample_rate }
}

fn report_data(&self, data: HashMap<String, ::libhoney::Value>) {
Expand All @@ -34,6 +35,14 @@ impl HoneycombTelemetry {
eprintln!("error sending event to honeycomb, {:?}", err);
}
}

fn should_report(&self, trace_id: TraceId) -> bool {
if self.sample_rate <= 1 {
return true;
}

trace_id.0 as usize % self.sample_rate == 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clever but I would have expected the sample rate to be a 0 to 1 kind of range - is this sort of sample rate common in other tracing libraries?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also expect a float of some sort here - maybe an f32, with a 0 to 1 range

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it looks like you're using sample_rate <= 1 to signify 'sample everything' - how do you feel about making this an Option<SampleRate> instead, where type SampleRate = u32 (or f32 or w/e)

}
}

impl Telemetry for HoneycombTelemetry {
Expand All @@ -46,13 +55,17 @@ impl Telemetry for HoneycombTelemetry {
}

fn report_span(&self, span: Span<Self::Visitor, Self::SpanId, Self::TraceId>) {
let data = span_to_values(span);
self.report_data(data);
if self.should_report(span.trace_id) {
let data = span_to_values(span);
self.report_data(data);
}
}

fn report_event(&self, event: Event<Self::Visitor, Self::SpanId, Self::TraceId>) {
let data = event_to_values(event);
self.report_data(data);
if self.should_report(event.trace_id) {
let data = event_to_values(event);
self.report_data(data);
}
}
}

Expand Down
33 changes: 32 additions & 1 deletion tracing-honeycomb/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,38 @@ pub fn new_honeycomb_telemetry_layer(
let instance_id: u64 = rand::thread_rng().gen();
TelemetryLayer::new(
service_name,
HoneycombTelemetry::new(honeycomb_config),
HoneycombTelemetry::new(honeycomb_config, 1),
move |tracing_id| SpanId {
instance_id,
tracing_id,
},
)
}

/// Construct a TelemetryLayer that publishes telemetry to honeycomb.io using the
/// provided honeycomb config, and sample rate. This function differs from
/// `new_honeycomb_telemetry_layer` and the `sample_rate` on the
/// `libhoney::Config` there in an important way. `libhoney` samples `Event`
/// data, which is individual spans on each trace. This means that using the
/// sampling logic in libhoney may result in missing event data or incomplete
/// traces. Calling this function provides trace-level sampling, meaning sampling
/// decisions are based on a modulo of the traceID, and events in a single trace
/// will not be sampled differently. If the trace is sampled, then all spans
/// under it will be sent to honeycomb. If a trace is not sampled, no spans or
/// events under it will be sent. When using this trace-level sampling, the
/// `sample_rate` parameter on the `libhoney::Config` should be set to 1, which
/// is the default.
///
/// Specialized to the honeycomb.io-specific SpanId and TraceId provided by this crate.
pub fn new_honeycomb_telemetry_layer_with_trace_sampling(
service_name: &'static str,
honeycomb_config: libhoney::Config,
sample_rate: usize,
) -> TelemetryLayer<HoneycombTelemetry, SpanId, TraceId> {
let instance_id: u64 = rand::thread_rng().gen();
TelemetryLayer::new(
service_name,
HoneycombTelemetry::new(honeycomb_config, sample_rate),
move |tracing_id| SpanId {
instance_id,
tracing_id,
Expand Down