-
Notifications
You must be signed in to change notification settings - Fork 288
Add span context to OnStartSpan #159
Add span context to OnStartSpan #159
Conversation
observer.go
Outdated
@@ -24,7 +24,7 @@ import opentracing "github.com/opentracing/opentracing-go" | |||
|
|||
// Observer can be registered with the Tracer to receive notifications about new Spans. | |||
type Observer interface { | |||
OnStartSpan(operationName string, options opentracing.StartSpanOptions) SpanObserver | |||
OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) SpanObserver |
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.
There's a problem with changing this interface - it is a breaking change and would require a major version upgrade. Given opentracing-contrib/go-observer#1, what if we leave this unchanged (document as deprecated) and instead add support for "options.ContribObserver()"?
We will support both until the next major release of jaeger-client, at which point we can consolidate into one AP.
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.
@yurishkuro Agreed and thanks for the suggestion.
Have added a commit which reverts this and adds ContribObserver.
config/options.go
Outdated
@@ -24,6 +24,8 @@ import ( | |||
"github.com/uber/jaeger-lib/metrics" | |||
|
|||
"github.com/uber/jaeger-client-go" | |||
|
|||
otobserver "github.com/opentracing-contrib/go-observer" |
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 would prefer not to have an explicit dependency on this package, but instead just re-define its interfaces here. Due to duck typing it should still be compatible, but Jaeger will be isolated from the potential API changes in the contrib package.
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.
Ok. I tried this with the latest commits I added here. And, it shows some compatibility issues, i.e., if I initialize a new observer based on go-observer and try to assign this observer with ContribObserver() in cfg.New(), I get a compatibility error :
have OnStartSpan(opentracing.Span, string, opentracing.StartSpanOptions) (otobserver.SpanObserver, bool)
want OnStartSpan(opentracing.Span, string, opentracing.StartSpanOptions) (jaeger.ContribSpanObserver, bool)
contrib_observer.go
Outdated
@@ -0,0 +1,90 @@ | |||
// Copyright (c) 2017 Uber Technologies, Inc. | |||
// (c) 2017 IBM Corp. |
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.
When you sign the CLA it assigns copyright to Uber, so please don't include this here, because it restricts our ability to manage licensing of Jaeger packages.
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.
Didn't know that. Updated.
config/options.go
Outdated
@@ -64,8 +66,18 @@ func Reporter(reporter jaeger.Reporter) Option { | |||
|
|||
// Observer can be registered with the Tracer to receive notifications about new Spans. | |||
func Observer(observer jaeger.Observer) Option { | |||
old := jaeger.OldObserver{Obs: observer} |
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's not good having OldObserver public. There are two ways we can handle this:
- duplicate ContribObserver option on the Tracer and do the wrapping there and only there, thus making oldObserver private
- or define an
internal/observer
package and declare a public type there - by convention people should not be depending on APIs underinternal
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 went with the 1st option, since, the 2nd option will still make old observer public.
span.go
Outdated
@@ -28,6 +28,8 @@ import ( | |||
"github.com/opentracing/opentracing-go" | |||
"github.com/opentracing/opentracing-go/ext" | |||
"github.com/opentracing/opentracing-go/log" | |||
|
|||
otobserver "github.com/opentracing-contrib/go-observer" |
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.
undesired dependency
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.
Updated.
span.go
Outdated
@@ -63,7 +65,7 @@ type Span struct { | |||
// references for this span | |||
references []Reference | |||
|
|||
observer SpanObserver | |||
contribObserver otobserver.SpanObserver |
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 you can keep the name observer
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.
Ok, changed this.
Hm, yes, that's unfortunate, duck typing doesn't work when you have an interface returning an interface. But to me a dependency on a contrib package is a bigger issue, for semver compatibility reasons, especially on a contrib pkg that is brand new and not battle tested. We may need to do a compromise. The duck typing will still work on the SpanObserver, but for the main Observer the end user would have to write a small wrapper that implements jaeger.ContribObserver interface. I don't think it's a huge burden because it's just one function and the end user needs to have some custom code when initializing Jaeger tracer anyway. So if you have a perf events related contrib.Observer, you would do something like this when passing it to Jaeger type jaegerObserver struct {
delegate *perfevents.Observer
}
// implement jaeger.ContribObserver
func (jo *jaegerObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (jaeger.ContribSpanObserver, bool) {
return delegate.OnStartSpanRaw(sp, opName, ops)
} as long as It's a bit of a dance, we can clean it up once the contrib.Observer gets more battle tested and the repo starts releasing semver. |
@yurishkuro alright, seems ok. We can have that bit of the initialization code. Any other comments on the added commits? |
contrib_observer.go
Outdated
// var sp opentracing.Span | ||
// sso := opentracing.StartSpanOptions{} | ||
// spanObserver, ok := Observer.OnStartSpan(span, opName, sso); | ||
// if 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.
this should be (idiomatic Go)
if spanObserver, ok := Observer.OnStartSpan(span, opName, sso); ok {
// we have a valid SpanObserver
}
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.
Changed this.
contrib_observer.go
Outdated
} | ||
|
||
// ContribSpanObserver is created by the Observer and receives notifications | ||
// about other Span events. |
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.
might add: It is meant to match http://...contrib-observer, but via duck typing, without directly importing the contrib package.
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.
Added this comment.
contrib_observer.go
Outdated
} | ||
|
||
// contribSpanObserver is a dispatcher to other span observers | ||
type contribSpanObserver struct { |
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.
s/contribSpanObserver/compositeSpanObserver/
(we use "composite" in many places). compositeObserver
at L63 as well.
I assume the nearly identical old dispatcher should be deleted?
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, changed the naming convention from contrib to composite and deleted the old dispatcher.
tracer.go
Outdated
@@ -59,7 +59,7 @@ type tracer struct { | |||
injectors map[interface{}]Injector | |||
extractors map[interface{}]Extractor | |||
|
|||
observer observer | |||
contribObserver contribObserver |
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.
nit: variable name should remain observer
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.
Renamed.
contrib_observer.go
Outdated
|
||
func (o contribObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) { | ||
var spanObservers []ContribSpanObserver | ||
for _, obs := range o.observers { |
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.
we should add a TODO to optimize this for the case when ==1 span observer is created - it can be returned directly, without allocating the slice.
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.
Didn't entirely understand this part. Can you please elaborate?
contrib_observer.go
Outdated
} | ||
} | ||
if len(spanObservers) == 0 { | ||
return noopContribSpanObserver, false |
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.
tracer has a direct dependency on this struct, so the function signature does not need to match the API. Specifically, the boolean value is meaningless because we always return a valid (albeit noop) span observer.
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.
Right. Nice suggestion. Updated in the latest commits.
tracer.go
Outdated
@@ -233,7 +233,7 @@ func (t *tracer) startSpanWithOptions( | |||
|
|||
sp := t.newSpan() | |||
sp.context = ctx | |||
sp.observer = t.observer.OnStartSpan(operationName, options) | |||
sp.observer, _ = t.contribObserver.OnStartSpan(sp, operationName, options) |
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.
per comment above, there's no need for the second return 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.
Got it.
Couldn't the span be just passed to a normal observer? I know this is breaking change but observer without access to span is not much of use really. |
@omeid the "normal" observer is the interface we had before the new one in contrib, and it did not accept the Span. If you need a span you can just implement the new |
But this doesn't seem to be merged in, right? Also, how do I get a hang of the logs from a span? They seem to be unexported. :( |
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.
minor clean-up needed, otherwise lgtm
Note about pointers:
- the
compositeObserver
is an addressable field in the tracer, it does not need to be declared as a pointer, but there's no reason to have its functions not use the pointer to avoid copying - the
compositeSpanObserver
instances should always be by pointer. When an instance of composite span observer is returned, the return type is an interface, so heap allocation will happen anyway, better to do that explicitly and avoid copying when calling functions on it.
contrib_observer.go
Outdated
|
||
// noopCompositeSpanObserver is used when there are no observers registered | ||
// on the Tracer or none of them returns span observers from OnStartSpan. | ||
var noopCompositeSpanObserver = compositeSpanObserver{} |
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.
take a pointer: = &compositeSpanObserver{}
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.
Done.
config/config.go
Outdated
@@ -147,10 +147,14 @@ func (c Configuration) New( | |||
jaeger.TracerOptions.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan), | |||
} | |||
|
|||
for _, obs := range opts.observers { | |||
for _,obs := range opts.observers { |
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.
go fmt
contrib_observer.go
Outdated
obs Observer | ||
} | ||
|
||
func (o oldObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) { |
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.
func (o *oldObserver)
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.
Done.
contrib_observer.go
Outdated
return compositeSpanObserver{observers: spanObservers} | ||
} | ||
|
||
func (o compositeSpanObserver) OnSetOperationName(operationName 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.
func (o *compositeSpanObserver)
contrib_observer.go
Outdated
} | ||
} | ||
|
||
func (o compositeSpanObserver) OnSetTag(key string, value interface{}) { |
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.
func (o *compositeSpanObserver)
observer.go
Outdated
@@ -22,12 +22,16 @@ package jaeger | |||
|
|||
import opentracing "github.com/opentracing/opentracing-go" | |||
|
|||
// Observer can be registered with the Tracer to receive notifications about new Spans. | |||
// Observer can be registered with the Tracer to receive notifications about | |||
// new Spans. Note that this interface is now Deprecated, see: |
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.
See the recommended format for deprecation notice https://rakyll.org/deprecated/
[blank line]
Deprecated: use jaeger.ContribObserver instead.
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.
Right. Made this and all the above changes except one.
observer.go
Outdated
// SpanObserver is created by the Observer and receives notifications about other Span events. | ||
// SpanObserver is created by the Observer and receives notifications about | ||
// other Span events. Note that this interface is now Deprecated, see: | ||
// github.com/opentracing-contrib/go-observer. |
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.
[blank line]
Deprecated: use jaeger.ContribSpanObserver instead.
observer.go
Outdated
@@ -39,50 +43,27 @@ type observer struct { | |||
observers []Observer | |||
} |
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.
Is this still needed? I thought compositeObserver
above would be used instead,
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 observer
is probably needed since, it implements the Observer
interface. If we remove this struct observer
, the function OnStartSpan(operationName string, options opentracing.StartSpanOptions)
i.e., without the span argument, can't be defined which in turn will affect the existing external observers, right? Is there any other way we can replace this?
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.
when old-style observers are passed to tracer or config via option, they are immediately converted to the contrib-style, thus we never need to use the old style observer, it is fully replaced by the new compositeObserver
contrib_observer.go
Outdated
} | ||
|
||
// compositeObserver is a dispatcher to other observers | ||
type compositeObserver struct { |
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 prefer to move this to observer.go
(replace the old type). In the next major we can remove the contrib file/types.
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.
Regarding moving this and replacing the old type, see below.
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.
replied below. The main reason to move it to observer.go
is to reduce the size of the diff.
contrib_observer.go
Outdated
o.observers = append(o.observers, contribObserver) | ||
} | ||
|
||
func (o compositeObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) ContribSpanObserver { |
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.
func (o *compositeObserver)
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.
Done.
please update your master and rebase |
Some of the observers will need to call span functions from within the observed span events.
Reverts the previous commit (add span context to OnStartSpan) since, it will break the existing observers. Adds another observer contribObserver instead, implementing the interface github.com/opentracing-contrib/go-observer.
Also renames the contribObserver -> observer in the Span struct.
Change the global interfaces back to contrib observer. Only the private struct implementations remain as composite*. This patch also fixes a test error by changing spanObserver to compositeSpanObserver.
f8643e5
to
cb923e2
Compare
config/config.go
Outdated
@@ -147,12 +147,16 @@ func (c Configuration) New( | |||
jaeger.TracerOptions.ZipkinSharedRPCSpan(opts.zipkinSharedRPCSpan), | |||
} | |||
|
|||
for _, tag := range opts.tags { | |||
tracerOptions = append(tracerOptions, jaeger.TracerOptions.Tag(tag.Key, tag.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.
hm, merge issue. You need to define the official repo as eg upstream
and
git checkout -b master
git pull upstream master
git checkout -b observer-with-spancontext
git rebase master
your master should be == upstream master
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, did the exact same thing, but I guess this crept on while resolving some conflicts. Will fix it.
tracer_options.go
Outdated
|
||
return func(tracer *Tracer) { | ||
tracer.observer.append(&old) | ||
} |
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.
just delegate (DRY)
func (tracerOptions) Observer(observer Observer) TracerOption {
return ContribObserver(&oldObserver{obs: observer})
}
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.
Ok, but delegation will require scope resolution here, since, ContribObserver
is also an interface and a tracerOptions
function. Are you ok with having this (asking this because it doesn't conform to the current convention for other functions in tracer_options.go)?
func (t *tracerOptions) Observer(observer Observer) TracerOption {
return t.ContribObserver(&oldObserver{obs: observer})
}
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.
sorry, yes delegate to scoped tracerOptions.ContribObserver function, so there's no naming conflicts.
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.
Thanks, updated.
contrib_observer.go
Outdated
} | ||
|
||
func (o *oldObserver) OnStartSpan(sp opentracing.Span, operationName string, options opentracing.StartSpanOptions) (ContribSpanObserver, bool) { | ||
return o.obs.OnStartSpan(operationName, options), true |
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.
spanObserver := o.obs.OnStartSpan(operationName, options)
return spanObserver, spanObserver != nil
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.
Made the change.
contrib_observer.go
Outdated
|
||
// noopCompositeSpanObserver is used when there are no observers registered | ||
// on the Tracer or none of them returns span observers from OnStartSpan. | ||
var noopCompositeSpanObserver = &compositeSpanObserver{} |
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.
nit: s/noopCompositeSpanObserver/noopSpanObserver/
- it is not relevant that it is "composite", just that it's "no-op"
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.
Done.
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.
For some reason, I am not able to reply to the previous comment, so, I will add my reply here:
replied below. The main reason to move it to observer.go is to reduce the size of the diff.
Got it. So, it does reduce the diff when the compositeObserver struct and its functions are moved to observer.go. But, to be clear, did you ask me to move all of compositeObserver and compositeSpanObserver code to observer.go leaving only the ContribObserver and ContribSpanObserver interfaces there?
observer.go
Outdated
@@ -39,50 +43,27 @@ type observer struct { | |||
observers []Observer | |||
} |
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.
when old-style observers are passed to tracer or config via option, they are immediately converted to the contrib-style, thus we never need to use the old style observer, it is fully replaced by the new compositeObserver
contrib_observer.go
Outdated
} | ||
|
||
// compositeObserver is a dispatcher to other observers | ||
type compositeObserver struct { |
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.
replied below. The main reason to move it to observer.go
is to reduce the size of the diff.
Thanks for your patience, @hkshaw1990 . |
Some observers will need to call span functions from within the observed span events.