-
Notifications
You must be signed in to change notification settings - Fork 133
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
RUM-1836 feat(otel-tracer): conform to otel Tracer, SpanBuilder and Span #1611
RUM-1836 feat(otel-tracer): conform to otel Tracer, SpanBuilder and Span #1611
Conversation
7baf47a
to
deb6977
Compare
deb6977
to
6e552e1
Compare
b8700b0
to
95d5382
Compare
Datadog ReportBranch report: ✅ 0 Failed, 2727 Passed, 0 Skipped, 12m 27.49s Wall Time ⬇️ Code Coverage Decreases vs Default Branch (7)
|
|
||
internal struct DDNoopGlobals { | ||
static let tracer = DDNoopTracer() | ||
static let span = DDNoopSpan() | ||
static let context = DDNoopSpanContext() | ||
} | ||
|
||
internal struct DDNoopTracer: OTTracer { | ||
internal class DDNoopTracer: OTTracer, OpenTelemetryApi.Tracer { |
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.
OpenTelemetryApi.Tracer
is class only protocol.
8f37dd0
to
84a7f78
Compare
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 stuff and decent coverage! 🙇
Left some minor comments :)
func addEvent(name: String, attributes: [String: OpenTelemetryApi.AttributeValue], timestamp: Date) {} | ||
|
||
func end() { | ||
OpenTelemetry.instance.contextProvider.removeContextForSpan(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.
just curious: is there a use case for noop to have this implementation?
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.
probably never, unless someone adds the span manually to the context.
There is an API for it OpenTelemetry.instance.contextProvider.setActiveSpan(span)
var description: String { | ||
return "OTelSpan" | ||
} |
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.
Maybe we can dump a little bit more data. Will be useful when debugging with print
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.
that's debugDescription
https://developer.apple.com/documentation/swift/customdebugstringconvertible
I can put a separate PR for a pretty print.
extension OpenTelemetryApi.SpanId { | ||
/// Converts OpenTelemetry `SpanId` to Datadog `SpanID`. | ||
/// - Returns: Datadog `SpanID`. | ||
func toDatadog() -> SpanID { |
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.
Having Id
and ID
is a little bit awkward :/
Is there any way we could easily normalise class naming to one fashion?
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.
that's otel (SpanId) vs datadog (SpanID), given these are public types - we don't want to change them.
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.
Nice to see that it fits the existing DatadogTracer
👌. I left few questions and pointed to some blockers on thread safety.
var tracer: DatadogTracer | ||
var spanName: String | ||
var spanKind = SpanKind.client | ||
var attributes: [String: OpenTelemetryApi.AttributeValue] | ||
var startTime: Date? | ||
var active: Bool | ||
var parent: Parent |
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.
blocking/ It's all a mutable state modified by user and it lacks synchronisation. @ReadWriteLock
might do the job.
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 argue that this needs to thread safe given the purpose of the builder. When a customer is building the span using the SpanBuilder
it must be all done from the same thread. Once they start the span, it can be move around different threads.
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.
On the same hypothesis https://opentelemetry.io/docs/specs/otel/trace/api/#concurrency
func startSpan() -> OpenTelemetryApi.Span { | ||
let parentContext = parent.context() | ||
let traceId: TraceId | ||
let spanId = SpanId.random() |
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.
suggestion/ Abstracting trace IDs generation to separate type might be handy in some unit tests.
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 required at this point - so going to keep as it is. We can refactor when needed.
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.
Looks good 👍, I left only one question.
Please be aware of the impact that #1615 may have on this work.
Yes, I'm aware of that. Had a glance on your PR. Thanks for headsup. |
Things that have fatal error - will be implemented in future PRs
What and why?
Otel tracer implementation.
How?
This PR conforms to Tracer, SpanBuilder and Span protocols from otel.
We are not trying to reinventing the wheel but rather use the existing implementation and make it complaint to otel. During the otel API usage, we keep a internal copy of the span which is a datadog span. When a span is closed, all the otel data is mapped to the datadog span and reported.
Things that are supported
Review checklist
Custom CI job configuration (optional)
tools/