-
Notifications
You must be signed in to change notification settings - Fork 804
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
Zipkin Exporter #192
Zipkin Exporter #192
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.
This is a great start :)
* Shutdown exporter. Noop operation in this exporter. | ||
*/ | ||
shutdown() { | ||
// TODO: should we initiate an oppurtinistic send(..)? |
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 a good point, I think we should call send()
one last time to send last batched data.
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.
Let's discuss behavior on the next SIG meeting. As we don't have a callback here graceful shutdown is not really possible. I'd love the spec to be more specific here about this behavior: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/sdk-exporter.md#shutdown
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 it depends on the use case. What is the use case of shutdown
?
[types.SpanKind.CONSUMER]: zipkinTypes.SpanKind.CONSUMER, | ||
[types.SpanKind.PRODUCER]: zipkinTypes.SpanKind.PRODUCER, | ||
// Zipkin doesnt have type INTERNAL | ||
[types.SpanKind.INTERNAL]: zipkinTypes.SpanKind.CLIENT, |
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.
Hmm, not sure about this. Just add @todo
here and will revisit again.
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 we should skip the span bcoz INTERNAL
indicates that the span is used internally.
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 you sure?
SpanKind.Internal MUST be assumed as a default.
- spec
This would mean that we would skip on every span by default, except someone defines SpanKind.
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.
Hmm, I checked out Zipkin docs again and sounds like we can just leave it undefined
and let JSON.stringify to remove it.
kind: When present, kind clarifies timestamp, duration and remoteEndpoint. When
absent, the span is local or incomplete.
id: span.spanContext.spanId, | ||
kind: ZIPKIN_SPAN_KIND_MAPPING[span.kind], | ||
timestamp: span.startTime * MICROS_PER_MILLI, | ||
duration: Math.round(span.startTime - span.endTime * MICROS_PER_MILLI), |
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.
(span.endTime - span.startTime) * MICROS_PER_MILLI?
Codecov Report
@@ Coverage Diff @@
## master #192 +/- ##
==========================================
+ Coverage 98.86% 98.95% +0.09%
==========================================
Files 69 76 +7
Lines 2732 3161 +429
Branches 193 209 +16
==========================================
+ Hits 2701 3128 +427
- Misses 31 33 +2
|
id: span.spanContext.spanId, | ||
kind: ZIPKIN_SPAN_KIND_MAPPING[span.kind], | ||
timestamp: span.startTime * MICROS_PER_MILLI, | ||
duration: (span.startTime - span.endTime) * MICROS_PER_MILLI, |
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 duration should be (span.endTime - span.startTime)
and not (span.startTime - span.endTime)
.
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 still think we should store the duration and not the end time. When I think about it, it doesn't even make sense to rely on the concept of an end time since it could end up before the start time because of daylight saving time. This makes the current implementation semantically incorrect.
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 daylight savings time, my understanding is that performance.now
is monotonic, so that wouldn't be an issue if we use it? Or am I missing something?
I'm open to storing the duration, but thought it could be simpler to just store start and end since that's what's provided either at measurement time or as a parameter
Please include the tests when you get time.
The Batching will most likely be handled by the
Handled in #195, should un-block you.
I think keep it
Per SIG discussion, let's go with current mapping (
Per SIG discussion, make it configurable
Per SIG discussion, this is up-to exporter to implement the retry mechanism. Use raw right now and it’s sufficient. |
77d8a4a
to
945cfe1
Compare
@mayurkale22 I added tests and tested with Zipkin backend. Could also make some fields optional when not provided to minimize the payload. After integrating the batch logic, it's ready to go. |
url?: string; | ||
// Initiates a request with spans in memory to the backend. | ||
forceFlush?: boolean; | ||
// Optional mapping overrides for OpenTelemetry status code and description. |
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.
Good idea :)
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.
LGTM, added a minor comment. Thanks for the work!
@mayurkale22 thanks for the review, I changed it. |
/** | ||
* The network context of a node in the service graph. | ||
*/ | ||
export interface Endpoint { |
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.
Zipkin format also supports ipv6 for endpoints. Any particular reason for not including it?
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.
Yes, you're right. This is what I found on zipkin API.
description: | The network context of a node in the service graph |
---|---|
serviceName | stringLower-case label of this node in the service graph, such as "favstar". Leaveabsent if unknown.This is a primary label for trace lookup and aggregation, so it should beintuitive and consistent. Many use a name from service discovery. |
ipv4 | string($ipv4)The text representation of the primary IPv4 address associated with thisconnection. Ex. 192.168.99.100 Absent if unknown. |
ipv6 | string($ipv6)The text representation of the primary IPv6 address associated with aconnection. Ex. 2001:db8::c001 Absent if unknown.Prefer using the ipv4 field for mapped addresses. |
port | integerDepending on context, this could be a listen port or the client-side of asocket. Absent if unknown. Please don’t set to zero. |
@hekike Could you please add support ipv6
? Thanks
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'd expect ipv6 would be handled by node, do I miss something?
$ node -p -e 'require("url").parse("http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:9411/api/v2/spans")'
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:9411',
port: '9411',
hostname: 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
hash: null,
search: null,
query: null,
pathname: '/api/v2/spans',
path: '/api/v2/spans',
href:
'http://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:9411/api/v2/spans' }
b625ca7
to
d58ff55
Compare
d58ff55
to
510b2b5
Compare
@mayurkale22 PR rebased and I think ready to go. |
Great, I will take a look today and merge once everything looks good. Thanks for the work @hekike |
@open-telemetry/node-approvers Please review when you get time, thanks :) |
4e6421a
to
cc5432e
Compare
@hekike thanks for the great work! I will merge this PR now and run end-to-end test. |
* chore: use addSpanNetworkEvents from otel-web Rather than use a modified copy, adjust event creation code to use shared routine from otel-web. This has the pleasant side effect of also adding http.response_content_length. * fix: bring resource fetch spans into spec compliance Names should not be raw URLs, so I arbitrarily chose 'resourceFetch' to mirror 'documentFetch' - I'm open to any better suggestions. Because the resource url is of course very useful I've put it in the 'http.url' attribute instead. * chore: lint:fix and use semantic constants * fix: firefox sometimes has a fetchStart of 0, doesn't emit doc load spans I noticed that in unit and manual tests Firefox would frequently not emit doc load events. Turns out that sometimes the fetchStart was 0 and the logic prevented spans from being emitted. Simply checking >= 0 rather than > 0 fixes that. * chore: use constant for resourceFetch span name Co-authored-by: Bartlomiej Obecny <bobecny@gmail.com>
First take on Zipkin Exporter.
Please provide feedback.
Zipkin Spec:
https://github.com/openzipkin/zipkin-api/blob/master/zipkin2-api.yaml
TODO:
span.shared
DISCUSS:
span.status
mapping