[OpenTracing] Span and SpanContext implementation#472
Conversation
Kyle-Verhoog
left a comment
There was a problem hiding this comment.
Just a couple of things.
| # @param key [String] the key of the baggage item | ||
| # @param value [String] the value of the baggage item | ||
| def set_baggage_item(key, value) | ||
| tap { context.baggage[key] = value } |
There was a problem hiding this comment.
Do we want the span to be in charge of manipulating the data within the baggage?
By having the span context take care of manipulating the baggage we can abstract away the implementation details of the baggage.
Although it is unlikely that the implementation of the baggage will change.
There was a problem hiding this comment.
I agree, I don't think the span should be responsible for knowing details about baggage on the span context. That's why I'm a bit confused about this: if the span context manages the baggage, why is there a baggage function on the span at all?
We could implement baggage functions on the span context object that mirror this, and have this span delegate to those. I guess I'm hesitant to do that only because it seems like a modification of the OT spec. But since its all internal anyways, maybe it's okay.
@Kyle-Verhoog What are your thoughts: move this to SpanContext and delegate from Span, or keep as is?
There was a problem hiding this comment.
I think the delegate makes sense. Also, I forgot to mention this earlier, but we gotta keep in mind the span context instance should be immutable[0]. So setting a key in the baggage for a span context should produce a new span context instance with the key which the span will use.
There was a problem hiding this comment.
I think what this could look like is spancontext.set_baggage_item returns a new span context instance with the new item added and span.set_baggage_item will update its span context reference with this new instance.
(This is a change I have to make in the python tracer still).
There was a problem hiding this comment.
@Kyle-Verhoog Okay, I think you're right about the immutable part. I think the implementation might need to be a little different: how about we don't implement SpanContext#set_baggage_item and force the use of SpanContext#new constructor which accepts baggage? Then do as you said, and have the Span#set_baggage_item build a new SpanContext from an old one?
The more complicated this SpanContext management gets, the more it screams "factory pattern" to me. Especially if the tracer has to build these too.
There was a problem hiding this comment.
Sounds good to me! The SpanContext#new should duplicate the baggage that it receives. 👍
There was a problem hiding this comment.
Alright, I'll go ahead and make this change then.
| # Add a log entry to this span | ||
| # @param timestamp [Time] time of the log | ||
| # @param fields [Hash] Additional information to log | ||
| def log_kv(timestamp: Time.now, **fields) |
There was a problem hiding this comment.
What about the other error fields (stack, event, etc)? Or does error.object basically encapsulate all of these?
All standard log fields:
https://github.com/opentracing/specification/blob/master/semantic_conventions.md#log-fields-table
There was a problem hiding this comment.
Datadog::Span#set_error only accepts an StandardError object, which contains the message, stack, and type. That function then pulls those parts out and tags the span with them appropriately.
pawelchcki
left a comment
There was a problem hiding this comment.
One tiny comment otherwise LGTM!
|
|
||
| before(:each) do | ||
| # Expect a deprecation warning to be output. | ||
| it do |
There was a problem hiding this comment.
Would it 'expects a deprecation warning to be output.' work here?
There was a problem hiding this comment.
You could do that, and that would be okay. What matters is that the test is easy to read and understand. The language as its written reads as "it expects log to output 'Span#log is deprecated.' to stderr." In my mind, I think this is an abundantly clear statement, that does not require clarification by naming the example.
There was a problem hiding this comment.
Not to bikesched too much. I have mixed feelings about using nameless examples. Having explicit name to a example most often than not makes it more clearer than the code itself.
And while 1 line and relatively short nameless examples are fine and easy to read most of the time.
However examples like:
it do
expect {x}.to change {z}
end
look like a exception from this rule.
However since beauty lies in the eye of beholder I'm fine with both :).
Lets come back ot this discussion a bit later when working on Rubocop rules
There was a problem hiding this comment.
For what its worth, the style choice here isn't arbitrary, it's an implementation of the http://www.betterspecs.org/ standard, which I think does a better job of explaining the reasoning than I can here.
This all comes down to style ultimately I think. Sometimes it's worth discussing the possible merits, and it's totally reasonable to suggest alternatives, but given that both suggested styles are clear and understandable, it doesn't seem like there's much to gain by dwelling too much on things like this. The same would apply if the circumstances were reversed, and it was the named example in the PR instead of the nameless one.
| tap do | ||
| # SpanContext is immutable, so to make changes | ||
| # build a new span context. | ||
| @span_context = SpanContextFactory.clone( |
| :datadog_context | ||
|
|
||
| def initialize(datadog_context:, baggage: {}) | ||
| @datadog_context = datadog_context |
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
* Added: Datadog::OpenTracer::SpanContext implementation. * Added: Datadog::OpenTracer::Span implementation. * Changed: Bump required Ruby version for OpenTracing to 2.1. * Added: Datadog::OpenTracer::SpanContextFactory. * Changed: OpenTracer::Span#set_baggage_item to create new SpanContexts. * Changed: Datadog::OpenTracer::SpanContext#baggage to be immutable. * Added: span_id, trace_id, parent_id to Datadog::OpenTracer::SpanContext. * Changed: Replaced span_id, trace_id, parent_id with reference to Datadog::Context.
This pull request implements the OpenTracing
SpanandSpanContext. In their current forms, they are very simple, and may not represent the full scope of what will ultimately be supported.Some worthwhile notes:
SpanandSpanContextare still somewhat undetermined. They may require changes depending on how and where we actually construct and configure spans. The current plan is that they are treated like simple data structs, that are not responsible for building sophisticated Spans or SpanContexts. That logic is anticipated to be a part of the Tracer, or some kind of factory pattern.logandlog_kvshould be implemented. For now, they simply set errors, if provided with one. Otherwise they do nothing. We didn't interpret these functions to have responsibilities beyond setting some "debug tags", as opposed to doing logging in the traditional sense.span_idandtrace_idto theSpanContext, since this object is meant to be a serializable layer of data for sharing trace data across process boundaries (particularly for the purposes of distributed tracing.)