-
Notifications
You must be signed in to change notification settings - Fork 7
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
WIP: Span #12
base: master
Are you sure you want to change the base?
WIP: Span #12
Conversation
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.
I left a few comments here and there.
Something that I noticed is missing (both here and in the Java interface) is the span referencing logic.
I am not sure how opentracing-java is meant to do child of/follows from/possible extensions.
My reading of https://github.com/opentracing/specification/blob/master/specification.md#references-between-spans is that Span
s should carry these references and it seems to be missing.
opentracing-api/src/span.rs
Outdated
/// Retrieve the associated `SpanContext`. | ||
/// | ||
/// This may be called any time, including after `finish`. | ||
fn context(&self) -> &'a Self::Context; |
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.
I have been debating in my own head if we want this to return an owned SpanContext
.
This is because we have not required for SpanContext
to be Clone
.
The SpanContext
should be Clone
or returned owned is that it will be used for references (child of/follows from).
How do you think references should look like?
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.
The SpanContext should be Clone or returned owned is that it will be used for references (child of/follows from). -> if thats the case then I think we should add the clone constraint so users can clone if needed? .. let's see how it turns out down the road once we do more impls
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.
I agree it is best if we mark SpanContext: Clone
as that gives more flexibility to users:+1:
opentracing-api/src/span.rs
Outdated
fn set_tag(&mut self, key: &str, value: TagValue); | ||
|
||
/// Record an event at the current walltime timestamp. | ||
fn log(&mut self, event: 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.
I'm thinking the event type should be some specialised type.
According to the spec this is a timestamped Key/Value map where the map can be anything.
Personally I went for a LogValue
enum that mirrors the TagValue
and a Log
struct that has a timestamp and a String => LogValue
map.
Not sure if that is the best approach though.
opentracing-api/src/span.rs
Outdated
fn context(&self) -> &'a Self::Context; | ||
|
||
/// Sets a key:value tag on the `Span`. | ||
fn set_tag(&mut self, key: &str, value: TagValue); |
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.
Should the key be a String
?
We are likely taking ownership/cloning it to add it to a map of sorts.
opentracing-api/src/span.rs
Outdated
|
||
/// the value of the baggage item identified by the given key, or None if no such item | ||
/// could be found. | ||
fn get_baggage_item(&self, key: &str) -> Option<&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.
Should the return value be Option<&'a String>
?
opentracing-api/src/span.rs
Outdated
/// call made to the span instance. Future calls to `finish` are defined | ||
/// as noops, and future calls to other methods other than `context()` | ||
/// lead to undefined behavior. | ||
fn finish(&mut self); |
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.
I used a finish(self) -> FinishedSpan
approach to have the type system enforce the distinction between a finished and unfinished span.
The FinishedSpan
takes ownership of the state of the Span
but only implements read-only methods to revent editing.
I found it quite a nice approach, what do you think?
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.
I like that!
With regards to the other things in your list @daschl:
Consistency would be nice.
Yep, looks good.
That is what the specs say.
My idea hinted at in the code, I guess we can discuss further in #13
Having a By the way: getters name are recommended not to have |
@stefano-pogliani with regards to https://rust-lang-nursery.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter : If there are only getters it makes sense to omit, but i'd also find it weird if you have getter and setter to look something like: fn tag(&self);
fn set_tag(&mut self); vs. fn get_tag(&self);
fn set_tag(&mut self); |
For the getters name: I'm not sure which way it is best but I'm trying to stick to the API guidelines when possible. I am too used to the |
https://github.com/rust-lang/rfcs/blob/master/text/0344-conventions-galore.md#gettersetter-apis Yep looks like it - will make the modifications |
Started to experiment more, will update all the span stuff as described above and also do the mock and noop impls right away so we have something to actually validate against. I think I can finish it this week - lets see :) |
That sounds great. |
@stefano-pogliani thinking of the relation, it reminds me there is another component I totally forgot: the SpanBuilder! In java its defined as part of the tracer, but I think for us it needs to be a standalone trait as well I think (https://github.com/opentracing/opentracing-java/blob/master/opentracing-api/src/main/java/io/opentracing/Tracer.java#L109) |
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.
I'm still unclear how References
are used.
Could you show me an example of a child span being created?
|
||
/// Allows to unset a tag based on the given key. Noop if | ||
/// it doesn't exist. | ||
fn unset_tag<S>(&mut self, key: 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 is not technically part of the spec and I did not see it in the Java interface.
Should this be provided by implementations rather then the interface?
|
||
/// Allows to unset a baggage item based on the given key. Noop if | ||
/// it doesn't exist. | ||
fn unset_baggage_item<S>(&mut self, key: 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.
Same as above.
I'm not sure we should add non-standard features to the core interface.
|
||
pub struct MockSpanContext { | ||
baggage: HashMap<String, String>, | ||
} | ||
|
||
impl MockSpanContext { | ||
/// Create a new `MockSpanContext` with the given baggage. | ||
pub fn new(baggage: HashMap<String, String>) -> Self { | ||
fn new(baggage: HashMap<String, String>) -> Self { |
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.
I think because this is a mock library we probably do want this to be public.
S: Into<String>; | ||
|
||
/// Record an event at the current walltime timestamp. | ||
fn log(&mut self, event: 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.
With regards to the event
type: what if it was any serde::Serialize
type?
fn log<E>(&mut self, event: E)
where
E: serde::Serialize;
Alternatively we can do what slog
does and define an Event
trait with an interface tailored to use by tracers.
Common types in the standard library would get an implementation of Event
and users can implement it for any other type then need to log.
S: Into<String>; | ||
|
||
/// Returns the operation name if set, None otherwise. | ||
fn operation_name(&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.
Should it be Option<&String>
?
@stefano-pogliani next item, the span!
I think this one is not as complicated either but I still have some questions / stuff we should work through: