-
Notifications
You must be signed in to change notification settings - Fork 94
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
Made built-in tracing broader and OTel compliant #472
base: main
Are you sure you want to change the base?
Conversation
cbe0dd9
to
8579a70
Compare
72cc9ad
to
da2a8de
Compare
4abd1a1
to
cf5a580
Compare
6451697
to
38d4bc4
Compare
@wprzytula There are conflicts with |
0469dbe
to
0e04b9a
Compare
fa0419e
to
419b1b1
Compare
37b3fc0
to
e38b48b
Compare
scylla/src/transport/session.rs
Outdated
@@ -881,6 +891,11 @@ impl Session { | |||
self.extract_partitioner_name(&prepared, &self.cluster.get_data()), | |||
); | |||
|
|||
span.record( | |||
"db.scylladb.prepared_id", | |||
&format!("{:X}", prepared.get_id()).as_str(), |
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.
Using format!
unconditionally here is a bit costly because it allocates. I think you should call .record
and construct the arguments for it only if the span is enabled.
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.
Under what circumstances can the span be disabled?
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.
Ping @piodul
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.
trace_span!
, which underlies otel_span!
, might not emit anything if necessary criteria are not met (e.g. tracing level is not high enough), right?
I just want to make sure that the allocation cost is avoided if the otel_span!
invocation doesn't have any effect. However, approach from #656 is probably simpler, so let's just make sure that we don't allocate when passing information to tracing but rather use format_args!
etc.
@@ -21,6 +22,33 @@ use secrecy::{ExposeSecret, Secret, Zeroize}; | |||
/// serialize() should write the Value as [bytes] to the provided buffer | |||
pub trait Value { | |||
fn serialize(&self, buf: &mut Vec<u8>) -> Result<(), ValueTooBig>; | |||
|
|||
fn for_debug(&self) -> String { |
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.
Are for_debug
and its friends really needed?. Wouldn't it suffice to just require Values to implement Display
trait?
scylla/src/transport/session.rs
Outdated
let gen_bound_values_repr = |columns: &mut dyn Iterator<Item = usize>| { | ||
let mut s = String::new(); | ||
for i in columns { | ||
s.push_str(&metadata.col_specs[i].name); | ||
s.push('='); | ||
bound_values.for_debug_append_nth(&mut s, i).ok()?; | ||
s.push_str(", "); | ||
} | ||
if metadata.col_count > 0 { | ||
s.pop(); | ||
s.pop(); | ||
} | ||
Some(s) | ||
}; |
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.
This should use the std formatting framework in order to avoid allocations.
fn for_debug(&self) -> String { | ||
let mut s = String::new(); | ||
self.for_debug_append(&mut s); | ||
s | ||
} | ||
|
||
fn for_debug_append(&self, s: &mut String) { | ||
s.push_str("<Serialized>") | ||
} | ||
|
||
fn for_debug_append_nth(&self, s: &mut String, _n: usize) -> Result<(), NotEnoughValuesError> { | ||
s.push_str("<Serialized>"); | ||
Ok(()) | ||
} |
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.
Similar concern here as in Value
. Is it important to always print query arguments as a comma-separated list of string? Can we get away with just requiring Display
?
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.
Besides, this is quite fragile - I think we have some public methods which take ValueList
, call serialized()
and then just call other methods that also take ValueList
. If the tracing logic is situated in the latter, then we will always get "<Serialized>"
in tracing and this all will be useless.
Maybe, instead, we could just print raw bytes from a serialized form? We already have SerializedValues::iter()
that allows going over serialized values. It doesn't look as nice, but will be more consistent and less prone to such issues. Then, we wouldn't also need Display
on ValueList
or Value
.
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.
Will the serialized form of the values be as readable and helpful in debug as the Display form is?
v2:
|
Added otel_span! macro and SpanExt trait. Their purpose is to avoid boilerplate across driver code when instrumenting it with OTel-compatible tracing.
As a way to both test the subsequently added OTel tracing features and present their demo, I added this example. It involves emitting a trace and sending it to Zipkin.
We'll use it for display in OTel traces.
We'll use it for display in OTel traces.
We'll use it for display in OTel traces.
In an effort to increase ScyllaDB observability, we want to make the Rust driver emit traces complying to OpenTelemetry standard. Therefore, I adjusted the names of existing tags and added new ones, so the tag set resembles one already used in the Java driver and complies to OTel.
This will enable adding "partition_key" and "bound_values" tags to produced OTel traces.
v3:
|
In effort of increasing Scylla drivers' observability, I instrumented this one with OpenTelemetry compliant tracing. The solution utilises the
tokio-tracing
already present in the driver, however adding more spans and tags to them. The structure and content of those are expected to be roughly consistent among various drivers, so I kept close to Java driver's implementation. For convertingtokio-tracing
traces into OTel traces, I've usedtracing_opentelemetry
compatibility layer.Considerations yet to be done
Value
andValueList
so that they enable putting their string representation intobound_values
andpartition_key
tags.Pre-review checklist
Fixes:
annotations to PR description.