Skip to content
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

RUMM-675 Add tracer.startRootSpan() API #236

Merged
merged 1 commit into from
Sep 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions Sources/Datadog/OpenTracing/OTTracer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,35 @@ public protocol OTTracer {
/// Start a new span with the given operation name.
///
/// - parameter operationName: the operation name for the newly-started span
/// - parameter references: an optional list of Reference instances to record causal relationships
/// - parameter tags: a set of tag keys and values per OTSpan#setTag:value:, or nil to start with
/// - parameter references: an optional list of Reference instances to record causal relationships. If no
/// reference is provided, and an active span exists in the current execution context
/// the active span will be used as the parent.
/// - parameter tags: a set of tag keys and values per `OTSpan#setTag:value:`, or `nil` to start with
/// an empty tag map
/// - parameter startTime: an explicitly specified start timestamp for the OTSpan, or nil to use the
/// - parameter startTime: an explicitly specified start timestamp for the `OTSpan`, or `nil` to use the
/// current walltime
/// - returns: a valid Span instance; it is the caller's responsibility to call finish()
/// - returns: a valid Span instance; it is the caller's responsibility to call `finish()`.
func startSpan(
operationName: String,
references: [OTReference]?,
tags: [String: Encodable]?,
startTime: Date?
) -> OTSpan

/// Start a new root span with the given operation name.
/// - Parameters:
/// - operationName: the operation name for the newly-started span
/// - tags: a set of tag keys and values per `OTSpan#setTag:value:`, or `nil` to start with
/// an empty tag map
/// - startTime: an explicitly specified start timestamp for the `OTSpan`, or `nil` to use the
/// current walltime
/// - returns: a valid Span instance; it is the caller's responsibility to call `finish()`.
func startRootSpan(
operationName: String,
tags: [String: Encodable]?,
startTime: Date?
) -> OTSpan

/// Transfer the span information into the carrier of the given format.
///
/// For example:
Expand Down Expand Up @@ -67,7 +83,9 @@ public extension OTTracer {
/// Start a new span with the given operation name.
///
/// - parameter operationName: the operation name for the newly-started span
/// - parameter parent: span context that will be a parent reference
/// - parameter parent: span context that will be a parent reference. If no
/// reference is provided, and an active span exists in the current execution context
/// the active span will be used as the parent.
/// - parameter tags: a set of tag keys and values per OTSpan#setTag:value:, or nil to start with
/// an empty tag map
/// - parameter startTime: an explicitly specified start timestamp for the OTSpan, or nil to use the
Expand All @@ -87,4 +105,24 @@ public extension OTTracer {
startTime: startTime
)
}

/// Start a new root span with the given operation name.
/// - Parameters:
/// - operationName: the operation name for the newly-started span
/// - tags: a set of tag keys and values per `OTSpan#setTag:value:`, or `nil` to start with
/// an empty tag map
/// - startTime: an explicitly specified start timestamp for the `OTSpan`, or `nil` to use the
/// current walltime
/// - returns: a valid Span instance; it is the caller's responsibility to call `finish()`.
func startRootSpan(
operationName: String,
tags: [String: Encodable]? = nil,
startTime: Date? = nil
) -> OTSpan {
return self.startRootSpan(
operationName: operationName,
tags: tags,
startTime: startTime
)
ncreated marked this conversation as resolved.
Show resolved Hide resolved
}
}
21 changes: 14 additions & 7 deletions Sources/Datadog/Tracer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,18 @@ public class Tracer: OTTracer {
// MARK: - Open Tracing interface

public func startSpan(operationName: String, references: [OTReference]? = nil, tags: [String: Encodable]? = nil, startTime: Date? = nil) -> OTSpan {
let parentSpanContext = references?.compactMap { $0.context.dd }.last
let spanContext = createSpanContext(parentSpanContext: parentSpanContext)
let parentSpanContext = references?.compactMap { $0.context.dd }.last ?? activeSpan?.context as? DDSpanContext
return startSpan(
spanContext: spanContext,
spanContext: createSpanContext(parentSpanContext: parentSpanContext),
operationName: operationName,
tags: tags,
startTime: startTime
)
}

public func startRootSpan(operationName: String, tags: [String: Encodable]? = nil, startTime: Date? = nil) -> OTSpan {
return startSpan(
spanContext: createSpanContext(parentSpanContext: nil),
operationName: operationName,
tags: tags,
startTime: startTime
Expand All @@ -160,12 +168,11 @@ public class Tracer: OTTracer {
// MARK: - Internal

internal func createSpanContext(parentSpanContext: DDSpanContext? = nil) -> DDSpanContext {
let parentContext = parentSpanContext ?? activeSpan?.context as? DDSpanContext
return DDSpanContext(
traceID: parentContext?.traceID ?? tracingUUIDGenerator.generateUnique(),
traceID: parentSpanContext?.traceID ?? tracingUUIDGenerator.generateUnique(),
spanID: tracingUUIDGenerator.generateUnique(),
parentSpanID: parentContext?.spanID,
baggageItems: BaggageItems(targetQueue: queue, parentSpanItems: parentContext?.baggageItems)
parentSpanID: parentSpanContext?.spanID,
baggageItems: BaggageItems(targetQueue: queue, parentSpanItems: parentSpanContext?.baggageItems)
)
}

Expand Down
31 changes: 31 additions & 0 deletions Tests/DatadogTests/Datadog/TracerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,37 @@ class TracerTests: XCTestCase {
XCTAssertEqual(try spanMatchers[1].parentSpanID(), "0")
}

func testStartingRootActiveSpanInAsynchronousJobs() throws {
TracingFeature.instance = .mockByRecordingSpanMatchers(directory: temporaryDirectory)
defer { TracingFeature.instance = nil }

let tracer = Tracer.initialize(configuration: .init())
let queue = DispatchQueue(label: "\(#function)")

func makeFakeAPIRequest(on queue: DispatchQueue, completion: @escaping () -> Void) {
let requestSpan = tracer.startRootSpan(operationName: "request").setActive()
queue.asyncAfter(deadline: .now() + 1) {
let responseDecodingSpan = tracer.startSpan(operationName: "response decoding")
responseDecodingSpan.finish()
requestSpan.finish()
completion()
}
}
makeFakeAPIRequest(on: queue) {}
makeFakeAPIRequest(on: queue) {}

let spanMatchers = try TracingFeature.waitAndReturnSpanMatchers(count: 4)
let response1Matcher = spanMatchers[0]
let request1Matcher = spanMatchers[1]
let response2Matcher = spanMatchers[2]
let request2Matcher = spanMatchers[3]

XCTAssertEqual(try response1Matcher.parentSpanID(), try request1Matcher.spanID())
XCTAssertEqual(try request1Matcher.parentSpanID(), "0")
XCTAssertEqual(try response2Matcher.parentSpanID(), try request2Matcher.spanID())
XCTAssertEqual(try request2Matcher.parentSpanID(), "0")
}

// MARK: - Sending user info

func testSendingUserInfo() throws {
Expand Down