diff --git a/CHANGELOG.md b/CHANGELOG.md index c484d74363..5deb9ecce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- [BUGFIX] Manual trace injection APIs are not available in DatadogTrace. See [#1415][]. - [BUGFIX] Fix session replay uploads to AP1 site. See [#1418][]. - [BUGFIX] Allow instantiating custom instance of the SDK after default one. See [#1413][]. - [BUGFIX] Do not propagate attributes from Errors and LongTasks to Views. @@ -497,6 +498,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO [#1355]: https://github.com/DataDog/dd-sdk-ios/pull/1355 [#1410]: https://github.com/DataDog/dd-sdk-ios/pull/1410 [#1413]: https://github.com/DataDog/dd-sdk-ios/pull/1413 +[#1415]: https://github.com/DataDog/dd-sdk-ios/pull/1415 [#1418]: https://github.com/DataDog/dd-sdk-ios/pull/1418 [#1419]: https://github.com/DataDog/dd-sdk-ios/pull/1419 [@00fa9a]: https://github.com/00FA9A diff --git a/Datadog/Datadog.xcodeproj/project.pbxproj b/Datadog/Datadog.xcodeproj/project.pbxproj index 302552f217..0467eafa3e 100644 --- a/Datadog/Datadog.xcodeproj/project.pbxproj +++ b/Datadog/Datadog.xcodeproj/project.pbxproj @@ -299,6 +299,7 @@ 6176991C2A86121B0030022B /* HTTPClientMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6176991A2A86121B0030022B /* HTTPClientMock.swift */; }; 6176991E2A8791880030022B /* Datadog+MultipleInstancesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6176991D2A8791880030022B /* Datadog+MultipleInstancesIntegrationTests.swift */; }; 6176991F2A8791880030022B /* Datadog+MultipleInstancesIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6176991D2A8791880030022B /* Datadog+MultipleInstancesIntegrationTests.swift */; }; + 617699212A8A7DF50030022B /* DebugManualTraceInjectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 617699202A8A7DF50030022B /* DebugManualTraceInjectionViewController.swift */; }; 61776CED273BEA5500F93802 /* DebugRUMSessionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61776CEC273BEA5500F93802 /* DebugRUMSessionViewController.swift */; }; 61776D4E273E6D9F00F93802 /* SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61776D4D273E6D9F00F93802 /* SwiftUI.swift */; }; 6179FFD3254ADB1700556A0B /* ObjcAppLaunchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6179FFD2254ADB1100556A0B /* ObjcAppLaunchHandler.m */; }; @@ -453,10 +454,10 @@ A728ADAC2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADAA2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift */; }; A728ADB02934EB0900397996 /* DDW3CHTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A728ADAD2934EB0300397996 /* DDW3CHTTPHeadersWriter+apiTests.m */; }; A728ADB12934EB0C00397996 /* DDW3CHTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A728ADAD2934EB0300397996 /* DDW3CHTTPHeadersWriter+apiTests.m */; }; - A79B0F64292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m */; }; - A79B0F65292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m */; }; - A79B0F66292BD7CA008742B3 /* OTelHTTPHeadersWriter+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5E292BA435008742B3 /* OTelHTTPHeadersWriter+objc.swift */; }; - A79B0F67292BD7CC008742B3 /* OTelHTTPHeadersWriter+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5E292BA435008742B3 /* OTelHTTPHeadersWriter+objc.swift */; }; + A79B0F64292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; + A79B0F65292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */; }; + A79B0F66292BD7CA008742B3 /* B3HTTPHeadersWriter+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5E292BA435008742B3 /* B3HTTPHeadersWriter+objc.swift */; }; + A79B0F67292BD7CC008742B3 /* B3HTTPHeadersWriter+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5E292BA435008742B3 /* B3HTTPHeadersWriter+objc.swift */; }; D20605A3287464F40047275C /* ContextValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20605A2287464F40047275C /* ContextValuePublisher.swift */; }; D20605A4287464F40047275C /* ContextValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20605A2287464F40047275C /* ContextValuePublisher.swift */; }; D20605A6287476230047275C /* ServerOffsetPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20605A5287476230047275C /* ServerOffsetPublisher.swift */; }; @@ -1332,11 +1333,11 @@ D2EBEE2029BA160F00B15732 /* TracePropagationHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDCF29B8A02100B15732 /* TracePropagationHeadersWriter.swift */; }; D2EBEE2129BA160F00B15732 /* W3CHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728AD9C2934CE4400397996 /* W3CHTTPHeaders.swift */; }; D2EBEE2229BA160F00B15732 /* TracePropagationHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDD229B8A58E00B15732 /* TracePropagationHeadersReader.swift */; }; - D2EBEE2329BA160F00B15732 /* OTelHTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DC29253F8B00AC1A62 /* OTelHTTPHeadersReader.swift */; }; + D2EBEE2329BA160F00B15732 /* B3HTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DC29253F8B00AC1A62 /* B3HTTPHeadersReader.swift */; }; D2EBEE2429BA160F00B15732 /* W3CHTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA02934CE5D00397996 /* W3CHTTPHeadersReader.swift */; }; D2EBEE2529BA160F00B15732 /* TraceID.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDCC29B893D800B15732 /* TraceID.swift */; }; - D2EBEE2629BA160F00B15732 /* OTelHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773D32924EA2D00AC1A62 /* OTelHTTPHeaders.swift */; }; - D2EBEE2729BA160F00B15732 /* OTelHTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DB29253F8B00AC1A62 /* OTelHTTPHeadersWriter.swift */; }; + D2EBEE2629BA160F00B15732 /* B3HTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773D32924EA2D00AC1A62 /* B3HTTPHeaders.swift */; }; + D2EBEE2729BA160F00B15732 /* B3HTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DB29253F8B00AC1A62 /* B3HTTPHeadersWriter.swift */; }; D2EBEE2829BA160F00B15732 /* W3CHTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728AD9E2934CE5000397996 /* W3CHTTPHeadersWriter.swift */; }; D2EBEE2929BA160F00B15732 /* HTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C5A88324509A0C00DA608C /* HTTPHeadersWriter.swift */; }; D2EBEE2A29BA160F00B15732 /* TracingHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618E13B02524B8F80098C6B0 /* TracingHTTPHeaders.swift */; }; @@ -1344,20 +1345,20 @@ D2EBEE2E29BA161100B15732 /* TracePropagationHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDCF29B8A02100B15732 /* TracePropagationHeadersWriter.swift */; }; D2EBEE2F29BA161100B15732 /* W3CHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728AD9C2934CE4400397996 /* W3CHTTPHeaders.swift */; }; D2EBEE3029BA161100B15732 /* TracePropagationHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDD229B8A58E00B15732 /* TracePropagationHeadersReader.swift */; }; - D2EBEE3129BA161100B15732 /* OTelHTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DC29253F8B00AC1A62 /* OTelHTTPHeadersReader.swift */; }; + D2EBEE3129BA161100B15732 /* B3HTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DC29253F8B00AC1A62 /* B3HTTPHeadersReader.swift */; }; D2EBEE3229BA161100B15732 /* W3CHTTPHeadersReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA02934CE5D00397996 /* W3CHTTPHeadersReader.swift */; }; D2EBEE3329BA161100B15732 /* TraceID.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EBEDCC29B893D800B15732 /* TraceID.swift */; }; - D2EBEE3429BA161100B15732 /* OTelHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773D32924EA2D00AC1A62 /* OTelHTTPHeaders.swift */; }; - D2EBEE3529BA161100B15732 /* OTelHTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DB29253F8B00AC1A62 /* OTelHTTPHeadersWriter.swift */; }; + D2EBEE3429BA161100B15732 /* B3HTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773D32924EA2D00AC1A62 /* B3HTTPHeaders.swift */; }; + D2EBEE3529BA161100B15732 /* B3HTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7F773DB29253F8B00AC1A62 /* B3HTTPHeadersWriter.swift */; }; D2EBEE3629BA161100B15732 /* W3CHTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728AD9E2934CE5000397996 /* W3CHTTPHeadersWriter.swift */; }; D2EBEE3729BA161100B15732 /* HTTPHeadersWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C5A88324509A0C00DA608C /* HTTPHeadersWriter.swift */; }; D2EBEE3829BA161100B15732 /* TracingHTTPHeaders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618E13B02524B8F80098C6B0 /* TracingHTTPHeaders.swift */; }; - D2EBEE3B29BA163E00B15732 /* OTelHTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F60292BB071008742B3 /* OTelHTTPHeadersReaderTests.swift */; }; - D2EBEE3C29BA163E00B15732 /* OTelHTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5A292B7C06008742B3 /* OTelHTTPHeadersWriterTests.swift */; }; + D2EBEE3B29BA163E00B15732 /* B3HTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F60292BB071008742B3 /* B3HTTPHeadersReaderTests.swift */; }; + D2EBEE3C29BA163E00B15732 /* B3HTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */; }; D2EBEE3D29BA163E00B15732 /* W3CHTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA22934DB5000397996 /* W3CHTTPHeadersWriterTests.swift */; }; D2EBEE3E29BA163E00B15732 /* W3CHTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA52934DF2400397996 /* W3CHTTPHeadersReaderTests.swift */; }; - D2EBEE3F29BA163F00B15732 /* OTelHTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F60292BB071008742B3 /* OTelHTTPHeadersReaderTests.swift */; }; - D2EBEE4029BA163F00B15732 /* OTelHTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5A292B7C06008742B3 /* OTelHTTPHeadersWriterTests.swift */; }; + D2EBEE3F29BA163F00B15732 /* B3HTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F60292BB071008742B3 /* B3HTTPHeadersReaderTests.swift */; }; + D2EBEE4029BA163F00B15732 /* B3HTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */; }; D2EBEE4129BA163F00B15732 /* W3CHTTPHeadersWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA22934DB5000397996 /* W3CHTTPHeadersWriterTests.swift */; }; D2EBEE4229BA163F00B15732 /* W3CHTTPHeadersReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A728ADA52934DF2400397996 /* W3CHTTPHeadersReaderTests.swift */; }; D2EBEE4329BA168200B15732 /* TraceIDGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61B558D32469CDD8001460D3 /* TraceIDGeneratorTests.swift */; }; @@ -2133,6 +2134,7 @@ 617699172A860D9D0030022B /* HTTPClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPClient.swift; sourceTree = ""; }; 6176991A2A86121B0030022B /* HTTPClientMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPClientMock.swift; sourceTree = ""; }; 6176991D2A8791880030022B /* Datadog+MultipleInstancesIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Datadog+MultipleInstancesIntegrationTests.swift"; sourceTree = ""; }; + 617699202A8A7DF50030022B /* DebugManualTraceInjectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugManualTraceInjectionViewController.swift; sourceTree = ""; }; 61776CEC273BEA5500F93802 /* DebugRUMSessionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugRUMSessionViewController.swift; sourceTree = ""; }; 61776D4D273E6D9F00F93802 /* SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUI.swift; sourceTree = ""; }; 61786F7624FCDE04009E6BAB /* RUMDebuggingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMDebuggingTests.swift; sourceTree = ""; }; @@ -2346,13 +2348,13 @@ A728ADA52934DF2400397996 /* W3CHTTPHeadersReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = W3CHTTPHeadersReaderTests.swift; sourceTree = ""; }; A728ADAA2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "W3CHTTPHeadersWriter+objc.swift"; sourceTree = ""; }; A728ADAD2934EB0300397996 /* DDW3CHTTPHeadersWriter+apiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "DDW3CHTTPHeadersWriter+apiTests.m"; sourceTree = ""; }; - A79B0F5A292B7C06008742B3 /* OTelHTTPHeadersWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTelHTTPHeadersWriterTests.swift; sourceTree = ""; }; - A79B0F5E292BA435008742B3 /* OTelHTTPHeadersWriter+objc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OTelHTTPHeadersWriter+objc.swift"; sourceTree = ""; }; - A79B0F60292BB071008742B3 /* OTelHTTPHeadersReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTelHTTPHeadersReaderTests.swift; sourceTree = ""; }; - A79B0F63292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "DDOTelHTTPHeadersWriter+apiTests.m"; sourceTree = ""; }; - A7F773D32924EA2D00AC1A62 /* OTelHTTPHeaders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTelHTTPHeaders.swift; sourceTree = ""; }; - A7F773DB29253F8B00AC1A62 /* OTelHTTPHeadersWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OTelHTTPHeadersWriter.swift; sourceTree = ""; }; - A7F773DC29253F8B00AC1A62 /* OTelHTTPHeadersReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OTelHTTPHeadersReader.swift; sourceTree = ""; }; + A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersWriterTests.swift; sourceTree = ""; }; + A79B0F5E292BA435008742B3 /* B3HTTPHeadersWriter+objc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "B3HTTPHeadersWriter+objc.swift"; sourceTree = ""; }; + A79B0F60292BB071008742B3 /* B3HTTPHeadersReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersReaderTests.swift; sourceTree = ""; }; + A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "DDB3HTTPHeadersWriter+apiTests.m"; sourceTree = ""; }; + A7F773D32924EA2D00AC1A62 /* B3HTTPHeaders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = B3HTTPHeaders.swift; sourceTree = ""; }; + A7F773DB29253F8B00AC1A62 /* B3HTTPHeadersWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersWriter.swift; sourceTree = ""; }; + A7F773DC29253F8B00AC1A62 /* B3HTTPHeadersReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = B3HTTPHeadersReader.swift; sourceTree = ""; }; B3BBBCB0265E71C600943419 /* VitalMemoryReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalMemoryReader.swift; sourceTree = ""; }; B3BBBCBB265E71D100943419 /* VitalMemoryReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalMemoryReaderTests.swift; sourceTree = ""; }; B3FC3C0626526EFF00DEED9E /* VitalInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalInfo.swift; sourceTree = ""; }; @@ -4013,7 +4015,7 @@ isa = PBXGroup; children = ( 6132BF4B24A49C8F00D7BD17 /* HTTPHeadersWriter+objc.swift */, - A79B0F5E292BA435008742B3 /* OTelHTTPHeadersWriter+objc.swift */, + A79B0F5E292BA435008742B3 /* B3HTTPHeadersWriter+objc.swift */, A728ADAA2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift */, ); path = Propagation; @@ -4183,6 +4185,7 @@ children = ( 61441C942461A649003D8BB8 /* DebugLoggingViewController.swift */, 61441C932461A649003D8BB8 /* DebugTracingViewController.swift */, + 617699202A8A7DF50030022B /* DebugManualTraceInjectionViewController.swift */, 61E5333724B84EE2003D6C4E /* DebugRUMViewController.swift */, 61F74AF326F20E4600E5F5ED /* DebugCrashReportingWithRUMViewController.swift */, 618236882710560900125326 /* DebugWebviewViewController.swift */, @@ -4559,7 +4562,7 @@ 6147989B2A459E2B0095CB02 /* DDTrace+apiTests.m */, 61B5E42A26DFC433000B0A5F /* DDNSURLSessionDelegate+apiTests.m */, D2B3F051282E826A00C2B5EE /* DDHTTPHeadersWriter+apiTests.m */, - A79B0F63292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m */, + A79B0F63292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m */, A728ADAD2934EB0300397996 /* DDW3CHTTPHeadersWriter+apiTests.m */, D2A434AB2A8E416F0028E329 /* DDSessionReplay+apiTests.m */, ); @@ -4941,24 +4944,24 @@ path = W3C; sourceTree = ""; }; - A7F773D929253F5900AC1A62 /* OpenTracing */ = { + A7F773D929253F5900AC1A62 /* Datadog */ = { isa = PBXGroup; children = ( 618E13B02524B8F80098C6B0 /* TracingHTTPHeaders.swift */, 61C5A88324509A0C00DA608C /* HTTPHeadersWriter.swift */, 618E13A92524B8700098C6B0 /* HTTPHeadersReader.swift */, ); - path = OpenTracing; + path = Datadog; sourceTree = ""; }; - A7F773DA29253F6200AC1A62 /* OpenTelemetry */ = { + A7F773DA29253F6200AC1A62 /* B3 */ = { isa = PBXGroup; children = ( - A7F773D32924EA2D00AC1A62 /* OTelHTTPHeaders.swift */, - A7F773DB29253F8B00AC1A62 /* OTelHTTPHeadersWriter.swift */, - A7F773DC29253F8B00AC1A62 /* OTelHTTPHeadersReader.swift */, + A7F773D32924EA2D00AC1A62 /* B3HTTPHeaders.swift */, + A7F773DB29253F8B00AC1A62 /* B3HTTPHeadersWriter.swift */, + A7F773DC29253F8B00AC1A62 /* B3HTTPHeadersReader.swift */, ); - path = OpenTelemetry; + path = B3; sourceTree = ""; }; B3FC3C0426526EE900DEED9E /* RUMVitals */ = { @@ -5634,8 +5637,8 @@ D2EBEDD229B8A58E00B15732 /* TracePropagationHeadersReader.swift */, D2160CC029C0DED100FAA9A5 /* URLSession */, A728AD992934CE2800397996 /* W3C */, - A7F773DA29253F6200AC1A62 /* OpenTelemetry */, - A7F773D929253F5900AC1A62 /* OpenTracing */, + A7F773DA29253F6200AC1A62 /* B3 */, + A7F773D929253F5900AC1A62 /* Datadog */, ); path = NetworkInstrumentation; sourceTree = ""; @@ -5651,8 +5654,8 @@ D2160CD229C0DF6700FAA9A5 /* URLSessionTaskInterceptionTests.swift */, 61E45BCE2450A6EC00F2C652 /* TraceIDTests.swift */, 61B558D32469CDD8001460D3 /* TraceIDGeneratorTests.swift */, - A79B0F5A292B7C06008742B3 /* OTelHTTPHeadersWriterTests.swift */, - A79B0F60292BB071008742B3 /* OTelHTTPHeadersReaderTests.swift */, + A79B0F5A292B7C06008742B3 /* B3HTTPHeadersWriterTests.swift */, + A79B0F60292BB071008742B3 /* B3HTTPHeadersReaderTests.swift */, A728ADA22934DB5000397996 /* W3CHTTPHeadersWriterTests.swift */, A728ADA52934DF2400397996 /* W3CHTTPHeadersReaderTests.swift */, ); @@ -7390,7 +7393,7 @@ D2DA23CD298D5EDD00C6C7E6 /* _InternalProxyTests.swift in Sources */, 61133C5B2423990D00786299 /* DirectoryTests.swift in Sources */, 610ABD4C2A6930CA00AFEA34 /* TelemetryCoreIntegrationTests.swift in Sources */, - A79B0F64292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m in Sources */, + A79B0F64292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */, D2B3F052282E827700C2B5EE /* DDHTTPHeadersWriter+apiTests.m in Sources */, D20605B92875729E0047275C /* ContextValuePublisherMock.swift in Sources */, D24C9C4D29A7BA3F002057CF /* LogsMocks.swift in Sources */, @@ -7443,7 +7446,7 @@ 6132BF4924A49B6800D7BD17 /* DDSpanContext+objc.swift in Sources */, 6132BF4224A38D2400D7BD17 /* OTTracer+objc.swift in Sources */, A728ADAB2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift in Sources */, - A79B0F66292BD7CA008742B3 /* OTelHTTPHeadersWriter+objc.swift in Sources */, + A79B0F66292BD7CA008742B3 /* B3HTTPHeadersWriter+objc.swift in Sources */, 61133C0E2423983800786299 /* Datadog+objc.swift in Sources */, 61133C102423983800786299 /* Logs+objc.swift in Sources */, 615A4A8324A3431600233986 /* Trace+objc.swift in Sources */, @@ -7619,6 +7622,7 @@ 61020C2C2758E853005EEAEA /* DebugBackgroundEventsViewController.swift in Sources */, D2F44FC2299BD5600074B0D9 /* UIViewController+KeyboardControlling.swift in Sources */, 61441C992461A649003D8BB8 /* DebugLoggingViewController.swift in Sources */, + 617699212A8A7DF50030022B /* DebugManualTraceInjectionViewController.swift in Sources */, 617247AF25DA9BEA007085B3 /* CrashReportingObjcHelpers.m in Sources */, 61776CED273BEA5500F93802 /* DebugRUMSessionViewController.swift in Sources */, 61776D4E273E6D9F00F93802 /* SwiftUI.swift in Sources */, @@ -7794,7 +7798,7 @@ D263BCAF29DAFFEB00FA0E21 /* PerformancePresetOverride.swift in Sources */, D23039E7298D5236001A1FA3 /* NetworkConnectionInfo.swift in Sources */, D23039E9298D5236001A1FA3 /* TrackingConsent.swift in Sources */, - D2EBEE2629BA160F00B15732 /* OTelHTTPHeaders.swift in Sources */, + D2EBEE2629BA160F00B15732 /* B3HTTPHeaders.swift in Sources */, D23354FC2A42E32000AFCAE2 /* InternalExtended.swift in Sources */, D23039F3298D5236001A1FA3 /* DynamicCodingKey.swift in Sources */, D23039FE298D5236001A1FA3 /* FeatureRequestBuilder.swift in Sources */, @@ -7828,7 +7832,7 @@ D2DE63532A30A7CA00441A54 /* CoreRegistry.swift in Sources */, D2EBEE2829BA160F00B15732 /* W3CHTTPHeadersWriter.swift in Sources */, D23039EA298D5236001A1FA3 /* DeviceInfo.swift in Sources */, - D2EBEE2329BA160F00B15732 /* OTelHTTPHeadersReader.swift in Sources */, + D2EBEE2329BA160F00B15732 /* B3HTTPHeadersReader.swift in Sources */, D23039F8298D5236001A1FA3 /* InternalLogger.swift in Sources */, D2303A01298D5236001A1FA3 /* DateFormatting.swift in Sources */, D23039F1298D5236001A1FA3 /* AnyDecodable.swift in Sources */, @@ -7842,7 +7846,7 @@ D23039FF298D5236001A1FA3 /* Foundation+Datadog.swift in Sources */, D2F8235329915E12003C7E99 /* DatadogSite.swift in Sources */, D2D3199A29E98D970004F169 /* DefaultJSONEncoder.swift in Sources */, - D2EBEE2729BA160F00B15732 /* OTelHTTPHeadersWriter.swift in Sources */, + D2EBEE2729BA160F00B15732 /* B3HTTPHeadersWriter.swift in Sources */, D23039E2298D5236001A1FA3 /* UserInfo.swift in Sources */, D23039FB298D5236001A1FA3 /* URLRequestBuilder.swift in Sources */, D23039F6298D5236001A1FA3 /* Attributes.swift in Sources */, @@ -8450,7 +8454,7 @@ 61A2CC222A443D330000FF25 /* DDRUMConfigurationTests.swift in Sources */, 6176991C2A86121B0030022B /* HTTPClientMock.swift in Sources */, D29294E4291D652D00F8EFF9 /* ApplicationVersionPublisherTests.swift in Sources */, - A79B0F65292BD074008742B3 /* DDOTelHTTPHeadersWriter+apiTests.m in Sources */, + A79B0F65292BD074008742B3 /* DDB3HTTPHeadersWriter+apiTests.m in Sources */, D2CB6F4327C520D400A62B57 /* DDLogsTests.swift in Sources */, D2CB6F4527C520D400A62B57 /* TracerTests.swift in Sources */, D2CB6F4627C520D400A62B57 /* CoreMocks.swift in Sources */, @@ -8514,7 +8518,7 @@ D2CB6F9B27C5217A00A62B57 /* DDSpanContext+objc.swift in Sources */, D2CB6F9C27C5217A00A62B57 /* OTTracer+objc.swift in Sources */, A728ADAC2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift in Sources */, - A79B0F67292BD7CC008742B3 /* OTelHTTPHeadersWriter+objc.swift in Sources */, + A79B0F67292BD7CC008742B3 /* B3HTTPHeadersWriter+objc.swift in Sources */, D2CB6F9E27C5217A00A62B57 /* Datadog+objc.swift in Sources */, D2CB6F9F27C5217A00A62B57 /* Logs+objc.swift in Sources */, D2CB6FA027C5217A00A62B57 /* Trace+objc.swift in Sources */, @@ -8574,7 +8578,7 @@ D263BCB029DAFFEB00FA0E21 /* PerformancePresetOverride.swift in Sources */, D2DA2359298D57AA00C6C7E6 /* NetworkConnectionInfo.swift in Sources */, D2DA235A298D57AA00C6C7E6 /* TrackingConsent.swift in Sources */, - D2EBEE3429BA161100B15732 /* OTelHTTPHeaders.swift in Sources */, + D2EBEE3429BA161100B15732 /* B3HTTPHeaders.swift in Sources */, D23354FD2A42E32000AFCAE2 /* InternalExtended.swift in Sources */, D2DA235B298D57AA00C6C7E6 /* DynamicCodingKey.swift in Sources */, D2DA235C298D57AA00C6C7E6 /* FeatureRequestBuilder.swift in Sources */, @@ -8608,7 +8612,7 @@ D2DE63542A30A7CA00441A54 /* CoreRegistry.swift in Sources */, D2EBEE3629BA161100B15732 /* W3CHTTPHeadersWriter.swift in Sources */, D2DA236D298D57AA00C6C7E6 /* DeviceInfo.swift in Sources */, - D2EBEE3129BA161100B15732 /* OTelHTTPHeadersReader.swift in Sources */, + D2EBEE3129BA161100B15732 /* B3HTTPHeadersReader.swift in Sources */, D2DA236E298D57AA00C6C7E6 /* InternalLogger.swift in Sources */, D2DA236F298D57AA00C6C7E6 /* DateFormatting.swift in Sources */, D2DA2370298D57AA00C6C7E6 /* AnyDecodable.swift in Sources */, @@ -8622,7 +8626,7 @@ D2DA2375298D57AA00C6C7E6 /* Foundation+Datadog.swift in Sources */, D2F8235429915E12003C7E99 /* DatadogSite.swift in Sources */, D2D3199B29E98D970004F169 /* DefaultJSONEncoder.swift in Sources */, - D2EBEE3529BA161100B15732 /* OTelHTTPHeadersWriter.swift in Sources */, + D2EBEE3529BA161100B15732 /* B3HTTPHeadersWriter.swift in Sources */, D2DA2376298D57AA00C6C7E6 /* UserInfo.swift in Sources */, D2DA2377298D57AA00C6C7E6 /* URLRequestBuilder.swift in Sources */, D2DA2378298D57AA00C6C7E6 /* Attributes.swift in Sources */, @@ -8650,7 +8654,7 @@ files = ( D2160CD629C0DF6700FAA9A5 /* URLSessionSwizzlerTests.swift in Sources */, D26416B62A30E84F00BCD9F7 /* CoreRegistryTest.swift in Sources */, - D2EBEE3C29BA163E00B15732 /* OTelHTTPHeadersWriterTests.swift in Sources */, + D2EBEE3C29BA163E00B15732 /* B3HTTPHeadersWriterTests.swift in Sources */, D21AE6BC29E5EDAF0064BF29 /* TelemetryTests.swift in Sources */, D2DA23A3298D58F400C6C7E6 /* AnyEncodableTests.swift in Sources */, D263BCB429DB014900FA0E21 /* FixedWidthInteger+ConvenienceTests.swift in Sources */, @@ -8671,7 +8675,7 @@ D2160CDC29C0DF6700FAA9A5 /* HostsSanitizerTests.swift in Sources */, D2F44FB8299AA1DA0074B0D9 /* DataCompressionTests.swift in Sources */, D2160CE029C0DF6700FAA9A5 /* URLSessionDelegateAsSuperclassTests.swift in Sources */, - D2EBEE3B29BA163E00B15732 /* OTelHTTPHeadersReaderTests.swift in Sources */, + D2EBEE3B29BA163E00B15732 /* B3HTTPHeadersReaderTests.swift in Sources */, D2DA23A9298D58F400C6C7E6 /* FeatureBaggageTests.swift in Sources */, D2A783DA29A530EF003B03BB /* SwiftExtensionsTests.swift in Sources */, D2160CD429C0DF6700FAA9A5 /* NetworkInstrumentationFeatureTests.swift in Sources */, @@ -8687,7 +8691,7 @@ files = ( D2160CD729C0DF6700FAA9A5 /* URLSessionSwizzlerTests.swift in Sources */, D26416B72A30E84F00BCD9F7 /* CoreRegistryTest.swift in Sources */, - D2EBEE4029BA163F00B15732 /* OTelHTTPHeadersWriterTests.swift in Sources */, + D2EBEE4029BA163F00B15732 /* B3HTTPHeadersWriterTests.swift in Sources */, D21AE6BD29E5EDAF0064BF29 /* TelemetryTests.swift in Sources */, D2DA23B1298D59DC00C6C7E6 /* AnyEncodableTests.swift in Sources */, D263BCB529DB014900FA0E21 /* FixedWidthInteger+ConvenienceTests.swift in Sources */, @@ -8708,7 +8712,7 @@ D2160CDD29C0DF6700FAA9A5 /* HostsSanitizerTests.swift in Sources */, D2F44FB9299AA1DB0074B0D9 /* DataCompressionTests.swift in Sources */, D2160CE129C0DF6700FAA9A5 /* URLSessionDelegateAsSuperclassTests.swift in Sources */, - D2EBEE3F29BA163F00B15732 /* OTelHTTPHeadersReaderTests.swift in Sources */, + D2EBEE3F29BA163F00B15732 /* B3HTTPHeadersReaderTests.swift in Sources */, D2DA23B7298D59DC00C6C7E6 /* FeatureBaggageTests.swift in Sources */, D2A783D929A530EF003B03BB /* SwiftExtensionsTests.swift in Sources */, D2160CD529C0DF6700FAA9A5 /* NetworkInstrumentationFeatureTests.swift in Sources */, diff --git a/Datadog/E2ETests/Tracing/TracerE2ETests.swift b/Datadog/E2ETests/Tracing/TracerE2ETests.swift index 4e272c1350..1e48e276b7 100644 --- a/Datadog/E2ETests/Tracing/TracerE2ETests.swift +++ b/Datadog/E2ETests/Tracing/TracerE2ETests.swift @@ -5,7 +5,6 @@ */ import DatadogCore -import DatadogInternal import DatadogTrace class TracerE2ETests: E2ETests { diff --git a/Datadog/Example/Base.lproj/Main iOS.storyboard b/Datadog/Example/Base.lproj/Main iOS.storyboard index d018ef6429..45f77d1e5e 100644 --- a/Datadog/Example/Base.lproj/Main iOS.storyboard +++ b/Datadog/Example/Base.lproj/Main iOS.storyboard @@ -1,9 +1,9 @@ - + - + @@ -65,8 +65,28 @@ + + + + + + + + + + + + + + - + @@ -1662,6 +1682,34 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Datadog/Example/Debugging/DebugManualTraceInjectionViewController.swift b/Datadog/Example/Debugging/DebugManualTraceInjectionViewController.swift new file mode 100644 index 0000000000..2d56e0d42f --- /dev/null +++ b/Datadog/Example/Debugging/DebugManualTraceInjectionViewController.swift @@ -0,0 +1,153 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import SwiftUI +import DatadogTrace + +@available(iOS 14, *) +internal class DebugManualTraceInjectionViewController: UIHostingController { + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder, rootView: DebugManualTraceInjectionView()) + } +} + +private var currentSession: URLSession? = nil + +@available(iOS 14.0, *) +internal struct DebugManualTraceInjectionView: View { + enum TraceHeaderType: String, CaseIterable { + case datadog = "Datadog" + case w3c = "W3C" + case b3Single = "B3-Single" + case b3Multiple = "B3-Multiple" + } + + @State private var spanName = "network request" + @State private var requestURL = "http://127.0.0.1:8000" + @State private var selectedTraceHeaderType: TraceHeaderType = .datadog + @State private var sampleRate: Float = 100.0 + @State private var isRequestPending = false + + private let session: URLSession = URLSession( + configuration: .ephemeral, + delegate: DDURLSessionDelegate(), + delegateQueue: nil + ) + + var body: some View { + let isButtonDisabled = isRequestPending || spanName.isEmpty || requestURL.isEmpty + + VStack() { + VStack(spacing: 8) { + Text("Trace injection") + .font(.caption.weight(.bold)) + .frame(maxWidth: .infinity, alignment: .leading) + + Text("After tapping \"SEND REQUEST\", a POST request will be sent to the given URL. The request will be traced using the chosen tracing header type and sample rate. A span with specified name will be sent to Datadog.") + .font(.caption.weight(.light)) + .frame(maxWidth: .infinity, alignment: .leading) + } + .padding() + + Form { + Section(header: Text("Traced URL:")) { + TextField("", text: $requestURL) + } + Section(header: Text("Span name:")) { + TextField("", text: $spanName) + } + Picker("Trace header type:", selection: $selectedTraceHeaderType) { + ForEach(TraceHeaderType.allCases, id: \.self) { headerType in + Text(headerType.rawValue) + } + } + .pickerStyle(.inline) + Section(header: Text("Trace sample Rate")) { + Slider( + value: $sampleRate, + in: 0...100, step: 1, + minimumValueLabel: Text("0"), + maximumValueLabel: Text("100") + ) { + Text("Sample Rate") + } + } + } + + Spacer() + + Button(action: { prepareAndSendRequest() }) { + Text("SEND REQUEST") + .fontWeight(.bold) + .foregroundColor(.white) + } + .frame(maxWidth: .infinity) + .padding() + .background(isButtonDisabled ? Color.gray : Color.datadogPurple) + .cornerRadius(10) + .disabled(isButtonDisabled) + .padding(.horizontal, 8) + .padding(.bottom, 30) + } + } + + private func prepareAndSendRequest() { + guard let url = URL(string: requestURL) else { + print("🔥 POST Request not sent - invalid url: \(requestURL)") + return + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + + let span = Tracer.shared().startRootSpan(operationName: spanName) + + switch selectedTraceHeaderType { + case .datadog: + let writer = HTTPHeadersWriter(sampleRate: sampleRate) + Tracer.shared().inject(spanContext: span.context, writer: writer) + writer.traceHeaderFields.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) } + case .w3c: + let writer = W3CHTTPHeadersWriter(sampleRate: sampleRate) + Tracer.shared().inject(spanContext: span.context, writer: writer) + writer.traceHeaderFields.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) } + case .b3Single: + let writer = B3HTTPHeadersWriter(sampleRate: sampleRate, injectEncoding: .single) + Tracer.shared().inject(spanContext: span.context, writer: writer) + writer.traceHeaderFields.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) } + case .b3Multiple: + let writer = B3HTTPHeadersWriter(sampleRate: sampleRate, injectEncoding: .multiple) + Tracer.shared().inject(spanContext: span.context, writer: writer) + writer.traceHeaderFields.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) } + } + + send(request: request) { + span.finish() + print("✅ Request sent to \(requestURL)") + } + } + + private func send(request: URLRequest, completion: @escaping () -> Void) { + isRequestPending = true + let task = session.dataTask(with: request) { _, _, _ in + completion() + DispatchQueue.main.async { self.isRequestPending = false } + } + task.resume() + } +} + +// MARK - Preview + +@available(iOS 14.0, *) + +struct DebugTraceInjectionView_Previews: PreviewProvider { + static var previews: some View { + NavigationView { + DebugManualTraceInjectionView() + } + } +} diff --git a/Datadog/Example/Debugging/DebugWebviewViewController.swift b/Datadog/Example/Debugging/DebugWebviewViewController.swift index 9130c59ec3..507371a16c 100644 --- a/Datadog/Example/Debugging/DebugWebviewViewController.swift +++ b/Datadog/Example/Debugging/DebugWebviewViewController.swift @@ -6,7 +6,6 @@ import UIKit import WebKit -import DatadogInternal import DatadogRUM import DatadogWebViewTracking diff --git a/Datadog/Example/Utils/ConsoleOutputInterceptor.swift b/Datadog/Example/Utils/ConsoleOutputInterceptor.swift index f38797c4ff..ebf6937311 100644 --- a/Datadog/Example/Utils/ConsoleOutputInterceptor.swift +++ b/Datadog/Example/Utils/ConsoleOutputInterceptor.swift @@ -6,7 +6,6 @@ #if DEBUG -import DatadogInternal import UIKit class ConsoleOutputInterceptor { diff --git a/DatadogCore/Tests/Datadog/TracerTests.swift b/DatadogCore/Tests/Datadog/TracerTests.swift index 997441a563..d56f931d0f 100644 --- a/DatadogCore/Tests/Datadog/TracerTests.swift +++ b/DatadogCore/Tests/Datadog/TracerTests.swift @@ -744,14 +744,14 @@ class TracerTests: XCTestCase { XCTAssertEqual(httpHeadersWriter.traceHeaderFields, expectedHTTPHeaders2) } - func testItInjectsSpanContextWithOTelHTTPHeadersWriter_usingMultipleHeaders() { + func testItInjectsSpanContextWithB3HTTPHeadersWriter_usingMultipleHeaders() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let spanContext1 = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: 3, baggageItems: .mockAny()) let spanContext2 = DDSpanContext(traceID: 4, spanID: 5, parentSpanID: 6, baggageItems: .mockAny()) let spanContext3 = DDSpanContext(traceID: 77, spanID: 88, parentSpanID: nil, baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) XCTAssertEqual(httpHeadersWriter.traceHeaderFields, [:]) // When @@ -790,14 +790,14 @@ class TracerTests: XCTestCase { XCTAssertEqual(httpHeadersWriter.traceHeaderFields, expectedHTTPHeaders3) } - func testItInjectsSpanContextWithOTelHTTPHeadersWriter_usingSingleHeader() { + func testItInjectsSpanContextWithB3HTTPHeadersWriter_usingSingleHeader() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let spanContext1 = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: 3, baggageItems: .mockAny()) let spanContext2 = DDSpanContext(traceID: 4, spanID: 5, parentSpanID: 6, baggageItems: .mockAny()) let spanContext3 = DDSpanContext(traceID: 77, spanID: 88, parentSpanID: nil, baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) XCTAssertEqual(httpHeadersWriter.traceHeaderFields, [:]) // When @@ -828,12 +828,12 @@ class TracerTests: XCTestCase { XCTAssertEqual(httpHeadersWriter.traceHeaderFields, expectedHTTPHeaders3) } - func testItInjectsRejectedSpanContextWithOTelHTTPHeadersWriter_usingSingleHeader() { + func testItInjectsRejectedSpanContextWithB3HTTPHeadersWriter_usingSingleHeader() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let spanContext = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: .mockAny(), baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockRejectAll()) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockRejectAll()) XCTAssertEqual(httpHeadersWriter.traceHeaderFields, [:]) // When @@ -846,12 +846,12 @@ class TracerTests: XCTestCase { XCTAssertEqual(httpHeadersWriter.traceHeaderFields, expectedHTTPHeaders) } - func testItInjectsRejectedSpanContextWithOTelHTTPHeadersWriter_usingMultipleHeader() { + func testItInjectsRejectedSpanContextWithB3HTTPHeadersWriter_usingMultipleHeader() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let spanContext = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: .mockAny(), baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockRejectAll(), injectEncoding: .multiple) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockRejectAll(), injectEncoding: .multiple) XCTAssertEqual(httpHeadersWriter.traceHeaderFields, [:]) // When @@ -956,15 +956,15 @@ class TracerTests: XCTestCase { XCTAssertNil(extractedSpanContext?.dd.parentSpanID) } - func testItExtractsSpanContextWithOTelHTTPHeadersReader_forMultipleHeaders() { + func testItExtractsSpanContextWithB3HTTPHeadersReader_forMultipleHeaders() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let injectedSpanContext = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: 3, baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) tracer.inject(spanContext: injectedSpanContext, writer: httpHeadersWriter) - let httpHeadersReader = OTelHTTPHeadersReader( + let httpHeadersReader = B3HTTPHeadersReader( httpHeaderFields: httpHeadersWriter.traceHeaderFields ) let extractedSpanContext = tracer.extract(reader: httpHeadersReader) @@ -974,15 +974,15 @@ class TracerTests: XCTestCase { XCTAssertEqual(extractedSpanContext?.dd.parentSpanID, injectedSpanContext.dd.parentSpanID) } - func testItExtractsSpanContextWithOTelHTTPHeadersReader_forSingleHeader() { + func testItExtractsSpanContextWithB3HTTPHeadersReader_forSingleHeader() { Trace.enable(with: config, in: core) let tracer = Tracer.shared(in: core) let injectedSpanContext = DDSpanContext(traceID: 1, spanID: 2, parentSpanID: 3, baggageItems: .mockAny()) - let httpHeadersWriter = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) + let httpHeadersWriter = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) tracer.inject(spanContext: injectedSpanContext, writer: httpHeadersWriter) - let httpHeadersReader = OTelHTTPHeadersReader( + let httpHeadersReader = B3HTTPHeadersReader( httpHeaderFields: httpHeadersWriter.traceHeaderFields ) let extractedSpanContext = tracer.extract(reader: httpHeadersReader) diff --git a/DatadogCore/Tests/DatadogObjc/DDTracerTests.swift b/DatadogCore/Tests/DatadogObjc/DDTracerTests.swift index bf1c0a5b1b..b633963c90 100644 --- a/DatadogCore/Tests/DatadogObjc/DDTracerTests.swift +++ b/DatadogCore/Tests/DatadogObjc/DDTracerTests.swift @@ -203,7 +203,7 @@ class DDTracerTests: XCTestCase { swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDHTTPHeadersWriter(samplingRate: 100) + let objcWriter = DDHTTPHeadersWriter(sampleRate: 100) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -221,7 +221,7 @@ class DDTracerTests: XCTestCase { swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDHTTPHeadersWriter(samplingRate: 0) + let objcWriter = DDHTTPHeadersWriter(sampleRate: 0) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -235,7 +235,7 @@ class DDTracerTests: XCTestCase { let objcTracer = DDTracer.shared() let objcSpanContext = DDSpanContextObjc(swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2)) - let objcValidWriter = DDHTTPHeadersWriter(samplingRate: 100) + let objcValidWriter = DDHTTPHeadersWriter(sampleRate: 100) let objcInvalidFormat = "foo" XCTAssertThrowsError( try objcTracer.inject(objcSpanContext, format: objcInvalidFormat, carrier: objcValidWriter) @@ -248,14 +248,14 @@ class DDTracerTests: XCTestCase { ) } - func testInjectingSpanContextToValidCarrierAndFormatForOTel() throws { + func testInjectingSpanContextToValidCarrierAndFormatForB3() throws { Trace.enable(with: config) let objcTracer = DDTracer.shared() let objcSpanContext = DDSpanContextObjc( swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDOTelHTTPHeadersWriter(samplingRate: 100) + let objcWriter = DDB3HTTPHeadersWriter(sampleRate: 100) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -264,14 +264,14 @@ class DDTracerTests: XCTestCase { XCTAssertEqual(objcWriter.traceHeaderFields, expectedHTTPHeaders) } - func testInjectingRejectedSpanContextToValidCarrierAndFormatForOTel() throws { + func testInjectingRejectedSpanContextToValidCarrierAndFormatForB3() throws { Trace.enable(with: config) let objcTracer = DDTracer.shared() let objcSpanContext = DDSpanContextObjc( swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDOTelHTTPHeadersWriter(samplingRate: 0) + let objcWriter = DDB3HTTPHeadersWriter(sampleRate: 0) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -280,12 +280,12 @@ class DDTracerTests: XCTestCase { XCTAssertEqual(objcWriter.traceHeaderFields, expectedHTTPHeaders) } - func testInjectingSpanContextToInvalidCarrierOrFormatForOTel() throws { + func testInjectingSpanContextToInvalidCarrierOrFormatForB3() throws { Trace.enable(with: config) let objcTracer = DDTracer.shared() let objcSpanContext = DDSpanContextObjc(swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2)) - let objcValidWriter = DDOTelHTTPHeadersWriter(samplingRate: 100) + let objcValidWriter = DDB3HTTPHeadersWriter(sampleRate: 100) let objcInvalidFormat = "foo" XCTAssertThrowsError( try objcTracer.inject(objcSpanContext, format: objcInvalidFormat, carrier: objcValidWriter) @@ -305,7 +305,7 @@ class DDTracerTests: XCTestCase { swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDW3CHTTPHeadersWriter(samplingRate: 100) + let objcWriter = DDW3CHTTPHeadersWriter(sampleRate: 100) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -321,7 +321,7 @@ class DDTracerTests: XCTestCase { swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2) ) - let objcWriter = DDW3CHTTPHeadersWriter(samplingRate: 0) + let objcWriter = DDW3CHTTPHeadersWriter(sampleRate: 0) try objcTracer.inject(objcSpanContext, format: OT.formatTextMap, carrier: objcWriter) let expectedHTTPHeaders = [ @@ -335,7 +335,7 @@ class DDTracerTests: XCTestCase { let objcTracer = DDTracer.shared() let objcSpanContext = DDSpanContextObjc(swiftSpanContext: DDSpanContext.mockWith(traceID: 1, spanID: 2)) - let objcValidWriter = DDW3CHTTPHeadersWriter(samplingRate: 100) + let objcValidWriter = DDW3CHTTPHeadersWriter(sampleRate: 100) let objcInvalidFormat = "foo" XCTAssertThrowsError( try objcTracer.inject(objcSpanContext, format: objcInvalidFormat, carrier: objcValidWriter) diff --git a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDOTelHTTPHeadersWriter+apiTests.m b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDB3HTTPHeadersWriter+apiTests.m similarity index 72% rename from DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDOTelHTTPHeadersWriter+apiTests.m rename to DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDB3HTTPHeadersWriter+apiTests.m index a2ec4b62d5..57beff0c08 100644 --- a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDOTelHTTPHeadersWriter+apiTests.m +++ b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDB3HTTPHeadersWriter+apiTests.m @@ -7,19 +7,19 @@ #import @import DatadogObjc; -@interface DDOTelHTTPHeadersWriter_apiTests : XCTestCase +@interface DDB3HTTPHeadersWriter_apiTests : XCTestCase @end /* * `DatadogObjc` APIs smoke tests - only check if the interface is available to Objc. */ -@implementation DDOTelHTTPHeadersWriter_apiTests +@implementation DDB3HTTPHeadersWriter_apiTests #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" - (void)testInitWithSamplingRate { - [[DDOTelHTTPHeadersWriter alloc] initWithSamplingRate:100 injectEncoding:DDInjectEncodingSingle]; + [[DDB3HTTPHeadersWriter alloc] initWithSampleRate:100 injectEncoding:DDInjectEncodingSingle]; } #pragma clang diagnostic pop diff --git a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDHTTPHeadersWriter+apiTests.m b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDHTTPHeadersWriter+apiTests.m index 4d39edf4b2..cab2afaeb6 100644 --- a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDHTTPHeadersWriter+apiTests.m +++ b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDHTTPHeadersWriter+apiTests.m @@ -19,7 +19,7 @@ @implementation DDHTTPHeadersWriter_apiTests #pragma clang diagnostic ignored "-Wunused-value" - (void)testInitWithSamplingRate { - [[DDHTTPHeadersWriter alloc] initWithSamplingRate:50]; + [[DDHTTPHeadersWriter alloc] initWithSampleRate:50]; } #pragma clang diagnostic pop diff --git a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDW3CHTTPHeadersWriter+apiTests.m b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDW3CHTTPHeadersWriter+apiTests.m index 1ad07d22a2..f75ea8ce27 100644 --- a/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDW3CHTTPHeadersWriter+apiTests.m +++ b/DatadogCore/Tests/DatadogObjc/ObjcAPITests/DDW3CHTTPHeadersWriter+apiTests.m @@ -19,7 +19,7 @@ @implementation DDW3CHTTPHeadersWriter_apiTests #pragma clang diagnostic ignored "-Wunused-value" - (void)testInitWithSamplingRate { - [[DDW3CHTTPHeadersWriter alloc] initWithSamplingRate:50]; + [[DDW3CHTTPHeadersWriter alloc] initWithSampleRate:50]; } #pragma clang diagnostic pop diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeaders.swift b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeaders.swift similarity index 93% rename from DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeaders.swift rename to DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeaders.swift index fbc628e038..0d2886a2ab 100644 --- a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeaders.swift +++ b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeaders.swift @@ -6,9 +6,12 @@ import Foundation -/// Open Telemetry propagation headers as explained in +@available(*, deprecated, renamed: "B3HTTPHeaders") +public typealias OTelHTTPHeaders = B3HTTPHeaders + +/// B3 propagation headers as explained in /// https://github.com/openzipkin/b3-propagation/blob/master/RATIONALE.md -public enum OTelHTTPHeaders { +public enum B3HTTPHeaders { public enum Multiple { /// The `X-B3-TraceId` header is encoded as 32 or 16 lower-hex characters. /// For example, a 128-bit TraceId header might look like: `X-B3-TraceId: 463ac35c9f6413ad48485a3953bb6124`. diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersReader.swift b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersReader.swift similarity index 69% rename from DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersReader.swift rename to DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersReader.swift index 3ca0604b48..528943d0a7 100644 --- a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersReader.swift +++ b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersReader.swift @@ -6,7 +6,10 @@ import Foundation -public class OTelHTTPHeadersReader: TracePropagationHeadersReader { +@available(*, deprecated, renamed: "B3HTTPHeadersReader") +public typealias OTelHTTPHeadersReader = B3HTTPHeadersReader + +public class B3HTTPHeadersReader: TracePropagationHeadersReader { private let httpHeaderFields: [String: String] public init(httpHeaderFields: [String: String]) { @@ -14,20 +17,20 @@ public class OTelHTTPHeadersReader: TracePropagationHeadersReader { } public func read() -> (traceID: TraceID, spanID: SpanID, parentSpanID: SpanID?)? { - if let traceIDValue = httpHeaderFields[OTelHTTPHeaders.Multiple.traceIDField], - let spanIDValue = httpHeaderFields[OTelHTTPHeaders.Multiple.spanIDField], + if let traceIDValue = httpHeaderFields[B3HTTPHeaders.Multiple.traceIDField], + let spanIDValue = httpHeaderFields[B3HTTPHeaders.Multiple.spanIDField], let traceID = TraceID(traceIDValue, representation: .hexadecimal), let spanID = TraceID(spanIDValue, representation: .hexadecimal) { return ( traceID: traceID, spanID: spanID, - parentSpanID: httpHeaderFields[OTelHTTPHeaders.Multiple.parentSpanIDField] + parentSpanID: httpHeaderFields[B3HTTPHeaders.Multiple.parentSpanIDField] .flatMap { TraceID($0, representation: .hexadecimal) } ) } - let b3Value = httpHeaderFields[OTelHTTPHeaders.Single.b3Field]? - .components(separatedBy: OTelHTTPHeaders.Constants.b3Separator) + let b3Value = httpHeaderFields[B3HTTPHeaders.Single.b3Field]? + .components(separatedBy: B3HTTPHeaders.Constants.b3Separator) if let traceIDValue = b3Value?[safe: 0], let spanIDValue = b3Value?[safe: 1], diff --git a/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersWriter.swift b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersWriter.swift new file mode 100644 index 0000000000..b6b219d9e6 --- /dev/null +++ b/DatadogInternal/Sources/NetworkInstrumentation/B3/B3HTTPHeadersWriter.swift @@ -0,0 +1,143 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import Foundation + +@available(*, deprecated, renamed: "B3HTTPHeadersWriter") +public typealias OTelHTTPHeadersWriter = B3HTTPHeadersWriter + +/// The `B3HTTPHeadersWriter` class facilitates the injection of trace propagation headers into network requests +/// targeted at a backend expecting [B3 propagation format](https://github.com/openzipkin/b3-propagation). +/// +/// Usage: +/// +/// var request = URLRequest(...) +/// +/// let writer = B3HTTPHeadersWriter(injectEncoding: .single) +/// let span = Tracer.shared().startRootSpan(operationName: "network request") +/// Tracer.shared().inject(spanContext: span.context, writer: writer) +/// +/// writer.traceHeaderFields.forEach { (field, value) in +/// request.setValue(value, forHTTPHeaderField: field) +/// } +/// +/// // call span.finish() when the request completes +/// +public class B3HTTPHeadersWriter: TracePropagationHeadersWriter { + /// Enumerates B3 header encoding options. + /// + /// There are two encodings of B3 propagation: + /// [Single Header](https://github.com/openzipkin/b3-propagation#single-header) + /// and [Multiple Header](https://github.com/openzipkin/b3-propagation#multiple-headers). + /// + /// Multiple header encoding employs an `X-B3-` prefixed header per item in the trace context. + /// Single header delimits the context into a single entry named `B3`. + /// The single-header variant takes precedence over the multiple header one when extracting fields. + public enum InjectEncoding { + /// Encoding that employs `X-B3-*` prefixed headers per item in the trace context. + /// + /// See: [Multiple Header](https://github.com/openzipkin/b3-propagation#multiple-headers). + case multiple + /// Encoding that uses a single `B3` header to transport the trace context. + /// + /// See: [Single Header](https://github.com/openzipkin/b3-propagation#single-header) + case single + } + + /// A dictionary containing the required HTTP Headers for propagating trace information. + /// + /// Usage: + /// + /// writer.traceHeaderFields.forEach { (field, value) in + /// request.setValue(value, forHTTPHeaderField: field) + /// } + /// + public private(set) var traceHeaderFields: [String: String] = [:] + + /// The tracing sampler. + /// + /// The sample rate determines the `X-B3-Sampled` header field value + /// and whether `X-B3-TraceId`, `X-B3-SpanId`, and `X-B3-ParentSpanId` are propagated. + private let sampler: Sampler + + /// The telemetry header encoding used by the writer. + private let injectEncoding: InjectEncoding + + /// Initializes the headers writer. + /// + /// - Parameter samplingRate: The sampling rate applied for headers injection. + /// - Parameter injectEncoding: The B3 header encoding type, with `.single` as the default. + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:injectEncoding:)` instead.") + public convenience init( + samplingRate: Float, + injectEncoding: InjectEncoding = .single + ) { + self.init(sampleRate: samplingRate, injectEncoding: injectEncoding) + } + + /// Initializes the headers writer. + /// + /// - Parameter sampleRate: The sampling rate applied for headers injection, with 20% as the default. + /// - Parameter injectEncoding: The B3 header encoding type, with `.single` as the default. + public convenience init( + sampleRate: Float = 20, + injectEncoding: InjectEncoding = .single + ) { + self.init( + sampler: Sampler(samplingRate: sampleRate), + injectEncoding: injectEncoding + ) + } + + /// Initializes the headers writer. + /// + /// - Parameter sampler: The sampler used for headers injection. + /// - Parameter injectEncoding: The B3 header encoding type, with `.single` as the default. + public init( + sampler: Sampler, + injectEncoding: InjectEncoding = .single + ) { + self.sampler = sampler + self.injectEncoding = injectEncoding + } + + /// Writes the trace ID, span ID, and optional parent span ID into the trace propagation headers. + /// + /// - Parameter traceID: The trace ID. + /// - Parameter spanID: The span ID. + /// - Parameter parentSpanID: The parent span ID, if applicable. + public func write(traceID: TraceID, spanID: SpanID, parentSpanID: SpanID?) { + let samplingPriority = sampler.sample() + + typealias Constants = B3HTTPHeaders.Constants + + switch injectEncoding { + case .multiple: + traceHeaderFields = [ + B3HTTPHeaders.Multiple.sampledField: samplingPriority ? Constants.sampledValue : Constants.unsampledValue + ] + + if samplingPriority { + traceHeaderFields[B3HTTPHeaders.Multiple.traceIDField] = String(traceID, representation: .hexadecimal32Chars) + traceHeaderFields[B3HTTPHeaders.Multiple.spanIDField] = String(spanID, representation: .hexadecimal16Chars) + traceHeaderFields[B3HTTPHeaders.Multiple.parentSpanIDField] = parentSpanID.map { String($0, representation: .hexadecimal16Chars) } + } + case .single: + if samplingPriority { + traceHeaderFields[B3HTTPHeaders.Single.b3Field] = [ + String(traceID, representation: .hexadecimal32Chars), + String(spanID, representation: .hexadecimal16Chars), + samplingPriority ? Constants.sampledValue : Constants.unsampledValue, + parentSpanID.map { String($0, representation: .hexadecimal16Chars) } + ] + .compactMap { $0 } + .joined(separator: Constants.b3Separator) + } else { + traceHeaderFields[B3HTTPHeaders.Single.b3Field] = Constants.unsampledValue + } + } + } +} diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/HTTPHeadersReader.swift b/DatadogInternal/Sources/NetworkInstrumentation/Datadog/HTTPHeadersReader.swift similarity index 100% rename from DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/HTTPHeadersReader.swift rename to DatadogInternal/Sources/NetworkInstrumentation/Datadog/HTTPHeadersReader.swift diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/HTTPHeadersWriter.swift b/DatadogInternal/Sources/NetworkInstrumentation/Datadog/HTTPHeadersWriter.swift similarity index 54% rename from DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/HTTPHeadersWriter.swift rename to DatadogInternal/Sources/NetworkInstrumentation/Datadog/HTTPHeadersWriter.swift index 3cdd7646cf..6a23257f14 100644 --- a/DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/HTTPHeadersWriter.swift +++ b/DatadogInternal/Sources/NetworkInstrumentation/Datadog/HTTPHeadersWriter.swift @@ -6,16 +6,16 @@ import Foundation -/// The `HTTPHeadersWriter` should be used to inject trace propagation headers to -/// the network requests send to the backend instrumented with Datadog APM. +/// The `HTTPHeadersWriter` class facilitates the injection of trace propagation headers into network requests +/// targeted at a backend instrumented with Datadog and expecting `x-datadog-*` headers. /// /// Usage: /// /// var request = URLRequest(...) /// /// let writer = HTTPHeadersWriter() -/// let span = DatadogTracer.shared().startSpan("network request") -/// writer.inject(spanContext: span.context) +/// let span = Tracer.shared().startRootSpan(operationName: "network request") +/// Tracer.shared().inject(spanContext: span.context, writer: writer) /// /// writer.traceHeaderFields.forEach { (field, value) in /// request.setValue(value, forHTTPHeaderField: field) @@ -23,10 +23,8 @@ import Foundation /// /// // call span.finish() when the request completes /// -/// public class HTTPHeadersWriter: TracePropagationHeadersWriter { - /// A dictionary with HTTP Headers required to propagate the trace started in the mobile app - /// to the backend instrumented with Datadog APM. + /// A dictionary containing the required HTTP Headers for propagating trace information. /// /// Usage: /// @@ -42,22 +40,33 @@ public class HTTPHeadersWriter: TracePropagationHeadersWriter { /// and if `x-datadog-trace-id` and `x-datadog-parent-id` are propagated. private let sampler: Sampler - /// Creates a `HTTPHeadersWriter` to inject traces propagation headers - /// to network request. + /// Initializes the headers writer. /// - /// - Parameter samplingRate: Tracing sampling rate. 20% by default. - public init(samplingRate: Float = 20) { - self.sampler = Sampler(samplingRate: samplingRate) + /// - Parameter samplingRate: The sampling rate applied for headers injection. + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:)` instead.") + public convenience init(samplingRate: Float) { + self.init(sampleRate: samplingRate) } - /// Creates a `HTTPHeadersWriter` to inject traces propagation headers - /// to network request. + /// Initializes the headers writer. /// - /// - Parameter sampler: Tracing sampler responsible for randomizing the sample. + /// - Parameter sampleRate: The sampling rate applied for headers injection, with 20% as the default. + public convenience init(sampleRate: Float = 20) { + self.init(sampler: Sampler(samplingRate: sampleRate)) + } + + /// Initializes the headers writer. + /// + /// - Parameter sampler: The sampler used for headers injection. public init(sampler: Sampler) { self.sampler = sampler } + /// Writes the trace ID, span ID, and optional parent span ID into the trace propagation headers. + /// + /// - Parameter traceID: The trace ID. + /// - Parameter spanID: The span ID. + /// - Parameter parentSpanID: The parent span ID, if applicable. public func write(traceID: TraceID, spanID: SpanID, parentSpanID: SpanID?) { let samplingPriority = sampler.sample() diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/TracingHTTPHeaders.swift b/DatadogInternal/Sources/NetworkInstrumentation/Datadog/TracingHTTPHeaders.swift similarity index 100% rename from DatadogInternal/Sources/NetworkInstrumentation/OpenTracing/TracingHTTPHeaders.swift rename to DatadogInternal/Sources/NetworkInstrumentation/Datadog/TracingHTTPHeaders.swift diff --git a/DatadogInternal/Sources/NetworkInstrumentation/NetworkInstrumentationFeature.swift b/DatadogInternal/Sources/NetworkInstrumentation/NetworkInstrumentationFeature.swift index 722f886db8..5309d351fc 100644 --- a/DatadogInternal/Sources/NetworkInstrumentation/NetworkInstrumentationFeature.swift +++ b/DatadogInternal/Sources/NetworkInstrumentation/NetworkInstrumentationFeature.swift @@ -175,7 +175,7 @@ extension NetworkInstrumentationFeature { if tracingHeaderTypes.contains(.datadog) { reader = HTTPHeadersReader(httpHeaderFields: headers) } else if tracingHeaderTypes.contains(.b3) || tracingHeaderTypes.contains(.b3multi) { - reader = OTelHTTPHeadersReader(httpHeaderFields: headers) + reader = B3HTTPHeadersReader(httpHeaderFields: headers) } else { reader = W3CHTTPHeadersReader(httpHeaderFields: headers) } diff --git a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersWriter.swift b/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersWriter.swift deleted file mode 100644 index 886081515d..0000000000 --- a/DatadogInternal/Sources/NetworkInstrumentation/OpenTelemetry/OTelHTTPHeadersWriter.swift +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. - * This product includes software developed at Datadog (https://www.datadoghq.com/). - * Copyright 2019-Present Datadog, Inc. - */ - -import Foundation - -/// The `OTelHTTPHeadersWriter` should be used to inject trace propagation headers to -/// the network requests send to the backend instrumented with Open Telemetry. -/// The injected headers conform to [Open Telemetry](https://github.com/openzipkin/b3-propagation) standard. -/// -/// Usage: -/// -/// var request = URLRequest(...) -/// -/// let writer = OTelHTTPHeadersWriter(injectEncoding: .single) -/// let span = DatadogTracer.shared().startSpan("network request") -/// writer.inject(spanContext: span.context) -/// -/// writer.traceHeaderFields.forEach { (field, value) in -/// request.setValue(value, forHTTPHeaderField: field) -/// } -/// -/// // call span.finish() when the request completes -/// -/// -public class OTelHTTPHeadersWriter: TracePropagationHeadersWriter { - /// Open Telemetry header encoding. - /// - /// There are two encodings of B3: - /// [Single Header](https://github.com/openzipkin/b3-propagation#single-header) - /// and [Multiple Header](https://github.com/openzipkin/b3-propagation#multiple-headers). - /// - /// Multiple header encoding uses an `X-B3-` prefixed header per item in the trace context. - /// Single header delimits the context into into a single entry named b3. - /// The single-header variant takes precedence over the multiple header one when extracting fields. - public enum InjectEncoding { - case multiple, single - } - - /// A dictionary with HTTP Headers required to propagate the trace started in the mobile app - /// to the backend instrumented with Open Telemetry. - /// - /// Usage: - /// - /// writer.traceHeaderFields.forEach { (field, value) in - /// request.setValue(value, forHTTPHeaderField: field) - /// } - /// - public private(set) var traceHeaderFields: [String: String] = [:] - - /// The tracing sampler. - /// - /// This value will decide of the `X-B3-Sampled` header field value - /// and if `X-B3-TraceId`, `X-B3-SpanId` and `X-B3-ParentSpanId` are propagated. - private let sampler: Sampler - - /// Determines the type of telemetry header type used by the writer. - private let injectEncoding: InjectEncoding - - /// Creates a `OTelHTTPHeadersWriter` to inject traces propagation headers - /// to network request. - /// - /// - Parameter samplingRate: Tracing sampling rate. 20% by default. - /// - Parameter injectEncoding: Determines the type of telemetry header type used by the writer. - public init( - samplingRate: Float = 20, - injectEncoding: InjectEncoding = .single - ) { - self.sampler = Sampler(samplingRate: samplingRate) - self.injectEncoding = injectEncoding - } - - /// Creates a `OTelHTTPHeadersWriter` to inject traces propagation headers - /// to network request. - /// - /// - Parameter sampler: Tracing sampler responsible for randomizing the sample. - /// - Parameter injectEncoding: Determines the type of telemetry header type used by the writer. - public init( - sampler: Sampler, - injectEncoding: InjectEncoding = .single - ) { - self.sampler = sampler - self.injectEncoding = injectEncoding - } - - public func write(traceID: TraceID, spanID: SpanID, parentSpanID: SpanID?) { - let samplingPriority = sampler.sample() - - typealias Constants = OTelHTTPHeaders.Constants - - switch injectEncoding { - case .multiple: - traceHeaderFields = [ - OTelHTTPHeaders.Multiple.sampledField: samplingPriority ? Constants.sampledValue : Constants.unsampledValue - ] - - if samplingPriority { - traceHeaderFields[OTelHTTPHeaders.Multiple.traceIDField] = String(traceID, representation: .hexadecimal32Chars) - traceHeaderFields[OTelHTTPHeaders.Multiple.spanIDField] = String(spanID, representation: .hexadecimal16Chars) - traceHeaderFields[OTelHTTPHeaders.Multiple.parentSpanIDField] = parentSpanID.map { String($0, representation: .hexadecimal16Chars) } - } - case .single: - if samplingPriority { - traceHeaderFields[OTelHTTPHeaders.Single.b3Field] = [ - String(traceID, representation: .hexadecimal32Chars), - String(spanID, representation: .hexadecimal16Chars), - samplingPriority ? Constants.sampledValue : Constants.unsampledValue, - parentSpanID.map { String($0, representation: .hexadecimal16Chars) } - ] - .compactMap { $0 } - .joined(separator: Constants.b3Separator) - } else { - traceHeaderFields[OTelHTTPHeaders.Single.b3Field] = Constants.unsampledValue - } - } - } -} diff --git a/DatadogInternal/Sources/NetworkInstrumentation/W3C/W3CHTTPHeadersWriter.swift b/DatadogInternal/Sources/NetworkInstrumentation/W3C/W3CHTTPHeadersWriter.swift index c8b71c50c5..bd97c9136d 100644 --- a/DatadogInternal/Sources/NetworkInstrumentation/W3C/W3CHTTPHeadersWriter.swift +++ b/DatadogInternal/Sources/NetworkInstrumentation/W3C/W3CHTTPHeadersWriter.swift @@ -6,17 +6,16 @@ import Foundation -/// The `W3CHTTPHeadersWriter` should be used to inject trace propagation headers to -/// the network requests send to the backend instrumented with W3C trace context. -/// The injected headers conform to [W3C](https://www.w3.org/TR/trace-context/) standard. +/// The `W3CHTTPHeadersWriter` class facilitates the injection of trace propagation headers into network requests +/// targeted at a backend expecting [W3C propagation format](https://github.com/openzipkin/b3-propagation). /// /// Usage: /// /// var request = URLRequest(...) /// /// let writer = W3CHTTPHeadersWriter() -/// let span = DatadogTracer.shared().startSpan("network request") -/// writer.inject(spanContext: span.context) +/// let span = Tracer.shared().startRootSpan(operationName: "network request") +/// Tracer.shared().inject(spanContext: span.context, writer: writer) /// /// writer.traceHeaderFields.forEach { (field, value) in /// request.setValue(value, forHTTPHeaderField: field) @@ -24,10 +23,8 @@ import Foundation /// /// // call span.finish() when the request completes /// -/// public class W3CHTTPHeadersWriter: TracePropagationHeadersWriter { - /// A dictionary with HTTP Headers required to propagate the trace started in the mobile app - /// to the backend instrumented with W3C trace context. + /// A dictionary containing the required HTTP Headers for propagating trace information. /// /// Usage: /// @@ -43,22 +40,33 @@ public class W3CHTTPHeadersWriter: TracePropagationHeadersWriter { /// and if `trace-id`, `span-id` are propagated. private let sampler: Sampler - /// Creates a `W3CHTTPHeadersWriter` to inject traces propagation headers - /// to network request. + /// Initializes the headers writer. /// - /// - Parameter samplingRate: Tracing sampling rate. 20% by default. - public init(samplingRate: Float = 20) { - self.sampler = Sampler(samplingRate: samplingRate) + /// - Parameter samplingRate: The sampling rate applied for headers injection. + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:)` instead.") + public convenience init(samplingRate: Float) { + self.init(sampleRate: samplingRate) } - /// Creates a `W3CHTTPHeadersWriter` to inject traces propagation headers - /// to network request. + /// Initializes the headers writer. /// - /// - Parameter sampler: Tracing sampler responsible for randomizing the sample. + /// - Parameter sampleRate: The sampling rate applied for headers injection, with 20% as the default. + public convenience init(sampleRate: Float = 20) { + self.init(sampler: Sampler(samplingRate: sampleRate)) + } + + /// Initializes the headers writer. + /// + /// - Parameter sampler: The sampler used for headers injection. public init(sampler: Sampler) { self.sampler = sampler } + /// Writes the trace ID, span ID, and optional parent span ID into the trace propagation headers. + /// + /// - Parameter traceID: The trace ID. + /// - Parameter spanID: The span ID. + /// - Parameter parentSpanID: The parent span ID, if applicable. public func write(traceID: TraceID, spanID: SpanID, parentSpanID: SpanID?) { typealias Constants = W3CHTTPHeaders.Constants diff --git a/DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersReaderTests.swift b/DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersReaderTests.swift similarity index 52% rename from DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersReaderTests.swift rename to DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersReaderTests.swift index 93774b0e7d..7c4b5331ee 100644 --- a/DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersReaderTests.swift +++ b/DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersReaderTests.swift @@ -7,71 +7,71 @@ import XCTest import DatadogInternal -class OTelHTTPHeadersReaderTests: XCTestCase { - func testOTelHTTPHeadersReaderreadsSingleHeader() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: ["b3": "4d2-929-1-162e"]) +class B3HTTPHeadersReaderTests: XCTestCase { + func testItReadsSingleHeader() { + let reader = B3HTTPHeadersReader(httpHeaderFields: ["b3": "4d2-929-1-162e"]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertEqual(ids?.traceID, 1_234) XCTAssertEqual(ids?.spanID, 2_345) XCTAssertEqual(ids?.parentSpanID, 5_678) } - func testOTelHTTPHeadersReaderreadsSingleHeaderWithSampling() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: ["b3": "0"]) + func testItReadsSingleHeaderWithSampling() { + let reader = B3HTTPHeadersReader(httpHeaderFields: ["b3": "0"]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertNil(ids?.traceID) XCTAssertNil(ids?.spanID) XCTAssertNil(ids?.parentSpanID) } - func testOTelHTTPHeadersReaderreadsSingleHeaderWithoutOptionalValues() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: ["b3": "4d2-929"]) + func testItReadsSingleHeaderWithoutOptionalValues() { + let reader = B3HTTPHeadersReader(httpHeaderFields: ["b3": "4d2-929"]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertEqual(ids?.traceID, 1_234) XCTAssertEqual(ids?.spanID, 2_345) XCTAssertNil(ids?.parentSpanID) } - func testOTelHTTPHeadersReaderreadsMultipleHeader() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: [ + func testItReadsMultipleHeader() { + let reader = B3HTTPHeadersReader(httpHeaderFields: [ "X-B3-TraceId": "4d2", "X-B3-SpanId": "929", "X-B3-Sampled": "1", "X-B3-ParentSpanId": "162e" ]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertEqual(ids?.traceID, 1_234) XCTAssertEqual(ids?.spanID, 2_345) XCTAssertEqual(ids?.parentSpanID, 5_678) } - func testOTelHTTPHeadersReaderreadsMultipleHeaderWithSampling() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: [ + func testItReadsMultipleHeaderWithSampling() { + let reader = B3HTTPHeadersReader(httpHeaderFields: [ "X-B3-Sampled": "0" ]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertNil(ids?.traceID) XCTAssertNil(ids?.spanID) XCTAssertNil(ids?.parentSpanID) } - func testOTelHTTPHeadersReaderreadsMultipleHeaderWithoutOptionalValues() { - let oTelHTTPHeadersReader = OTelHTTPHeadersReader(httpHeaderFields: [ + func testItReadsMultipleHeaderWithoutOptionalValues() { + let reader = B3HTTPHeadersReader(httpHeaderFields: [ "X-B3-TraceId": "4d2", "X-B3-SpanId": "929" ]) - let ids = oTelHTTPHeadersReader.read() + let ids = reader.read() XCTAssertEqual(ids?.traceID, 1_234) XCTAssertEqual(ids?.spanID, 2_345) diff --git a/DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersWriterTests.swift b/DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersWriterTests.swift new file mode 100644 index 0000000000..40a3a02ac9 --- /dev/null +++ b/DatadogInternal/Tests/NetworkInstrumentation/B3HTTPHeadersWriterTests.swift @@ -0,0 +1,109 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import XCTest +@testable import DatadogInternal + +class B3HTTPHeadersWriterTests: XCTestCase { + func testItWritesSingleHeader() { + let sampler: Sampler = .mockKeepAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .single + ) + + writer.write( + traceID: 1_234, + spanID: 2_345, + parentSpanID: 5_678 + ) + + let headers = writer.traceHeaderFields + XCTAssertEqual(headers[B3HTTPHeaders.Single.b3Field], "000000000000000000000000000004d2-0000000000000929-1-000000000000162e") + } + + func testItWritesSingleHeaderWithSampling() { + let sampler: Sampler = .mockRejectAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .single + ) + + writer.write( + traceID: 1_234, + spanID: 2_345, + parentSpanID: 5_678 + ) + + let headers = writer.traceHeaderFields + XCTAssertEqual(headers[B3HTTPHeaders.Single.b3Field], "0") + } + + func testItWritesSingleHeaderWithoutOptionalValues() { + let sampler: Sampler = .mockKeepAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .single + ) + writer.write(traceID: 1_234, spanID: 2_345) + + let headers = writer.traceHeaderFields + XCTAssertEqual(headers[B3HTTPHeaders.Single.b3Field], "000000000000000000000000000004d2-0000000000000929-1") + } + + func testItWritesMultipleHeader() { + let sampler: Sampler = .mockKeepAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .multiple + ) + writer.write( + traceID: 1_234, + spanID: 2_345, + parentSpanID: 5_678 + ) + + let headers = writer.traceHeaderFields + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.traceIDField], "000000000000000000000000000004d2") + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.spanIDField], "0000000000000929") + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.sampledField], "1") + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.parentSpanIDField], "000000000000162e") + } + + func testItWritesMultipleHeaderWithSampling() { + let sampler: Sampler = .mockRejectAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .multiple + ) + writer.write( + traceID: 1_234, + spanID: 2_345, + parentSpanID: 5_678 + ) + + let headers = writer.traceHeaderFields + XCTAssertNil(headers[B3HTTPHeaders.Multiple.traceIDField]) + XCTAssertNil(headers[B3HTTPHeaders.Multiple.spanIDField]) + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.sampledField], "0") + XCTAssertNil(headers[B3HTTPHeaders.Multiple.parentSpanIDField]) + } + + func testItWritesMultipleHeaderWithoutOptionalValues() { + let sampler: Sampler = .mockKeepAll() + let writer = B3HTTPHeadersWriter( + sampler: sampler, + injectEncoding: .multiple + ) + writer.write(traceID: 1_234, spanID: 2_345) + + let headers = writer.traceHeaderFields + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.traceIDField], "000000000000000000000000000004d2") + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.spanIDField], "0000000000000929") + XCTAssertEqual(headers[B3HTTPHeaders.Multiple.sampledField], "1") + XCTAssertNil(headers[B3HTTPHeaders.Multiple.parentSpanIDField]) + } +} diff --git a/DatadogInternal/Tests/NetworkInstrumentation/NetworkInstrumentationFeatureTests.swift b/DatadogInternal/Tests/NetworkInstrumentation/NetworkInstrumentationFeatureTests.swift index 20861aea5c..24684b92d0 100644 --- a/DatadogInternal/Tests/NetworkInstrumentation/NetworkInstrumentationFeatureTests.swift +++ b/DatadogInternal/Tests/NetworkInstrumentation/NetworkInstrumentationFeatureTests.swift @@ -263,7 +263,7 @@ class NetworkInstrumentationFeatureTests: XCTestCase { func testGivenOpenTelemetry_b3single_whenInterceptingRequests_itInjectsTrace() throws { // Given var request: URLRequest = .mockWith(url: "https://test.com") - let writer = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) + let writer = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .single) handler.firstPartyHosts = .init(["test.com": [.b3]]) // When @@ -285,7 +285,7 @@ class NetworkInstrumentationFeatureTests: XCTestCase { func testGivenOpenTelemetry_b3multi_whenInterceptingRequests_itInjectsTrace() throws { // Given var request: URLRequest = .mockWith(url: "https://test.com") - let writer = OTelHTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) + let writer = B3HTTPHeadersWriter(sampler: .mockKeepAll(), injectEncoding: .multiple) handler.firstPartyHosts = .init(["test.com": [.b3multi]]) // When diff --git a/DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersWriterTests.swift b/DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersWriterTests.swift deleted file mode 100644 index d57334cda4..0000000000 --- a/DatadogInternal/Tests/NetworkInstrumentation/OTelHTTPHeadersWriterTests.swift +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. - * This product includes software developed at Datadog (https://www.datadoghq.com/). - * Copyright 2019-Present Datadog, Inc. - */ - -import XCTest -@testable import DatadogInternal - -class OTelHTTPHeadersWriterTests: XCTestCase { - func testOTelHTTPHeadersWriterwritesSingleHeader() { - let sampler: Sampler = .mockKeepAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .single - ) - - oTelHTTPHeadersWriter.write( - traceID: 1_234, - spanID: 2_345, - parentSpanID: 5_678 - ) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertEqual(headers[OTelHTTPHeaders.Single.b3Field], "000000000000000000000000000004d2-0000000000000929-1-000000000000162e") - } - - func testOTelHTTPHeadersWriterwritesSingleHeaderWithSampling() { - let sampler: Sampler = .mockRejectAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .single - ) - - oTelHTTPHeadersWriter.write( - traceID: 1_234, - spanID: 2_345, - parentSpanID: 5_678 - ) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertEqual(headers[OTelHTTPHeaders.Single.b3Field], "0") - } - - func testOTelHTTPHeadersWriterwritesSingleHeaderWithoutOptionalValues() { - let sampler: Sampler = .mockKeepAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .single - ) - oTelHTTPHeadersWriter.write(traceID: 1_234, spanID: 2_345) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertEqual(headers[OTelHTTPHeaders.Single.b3Field], "000000000000000000000000000004d2-0000000000000929-1") - } - - func testOTelHTTPHeadersWriterwritesMultipleHeader() { - let sampler: Sampler = .mockKeepAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .multiple - ) - oTelHTTPHeadersWriter.write( - traceID: 1_234, - spanID: 2_345, - parentSpanID: 5_678 - ) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.traceIDField], "000000000000000000000000000004d2") - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.spanIDField], "0000000000000929") - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.sampledField], "1") - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.parentSpanIDField], "000000000000162e") - } - - func testOTelHTTPHeadersWriterwritesMultipleHeaderWithSampling() { - let sampler: Sampler = .mockRejectAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .multiple - ) - oTelHTTPHeadersWriter.write( - traceID: 1_234, - spanID: 2_345, - parentSpanID: 5_678 - ) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertNil(headers[OTelHTTPHeaders.Multiple.traceIDField]) - XCTAssertNil(headers[OTelHTTPHeaders.Multiple.spanIDField]) - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.sampledField], "0") - XCTAssertNil(headers[OTelHTTPHeaders.Multiple.parentSpanIDField]) - } - - func testOTelHTTPHeadersWriterwritesMultipleHeaderWithoutOptionalValues() { - let sampler: Sampler = .mockKeepAll() - let oTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - sampler: sampler, - injectEncoding: .multiple - ) - oTelHTTPHeadersWriter.write(traceID: 1_234, spanID: 2_345) - - let headers = oTelHTTPHeadersWriter.traceHeaderFields - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.traceIDField], "000000000000000000000000000004d2") - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.spanIDField], "0000000000000929") - XCTAssertEqual(headers[OTelHTTPHeaders.Multiple.sampledField], "1") - XCTAssertNil(headers[OTelHTTPHeaders.Multiple.parentSpanIDField]) - } -} diff --git a/DatadogObjc/Sources/Tracing/Propagation/B3HTTPHeadersWriter+objc.swift b/DatadogObjc/Sources/Tracing/Propagation/B3HTTPHeadersWriter+objc.swift new file mode 100644 index 0000000000..2bb596ecf3 --- /dev/null +++ b/DatadogObjc/Sources/Tracing/Propagation/B3HTTPHeadersWriter+objc.swift @@ -0,0 +1,58 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2019-Present Datadog, Inc. + */ + +import Foundation +import class DatadogInternal.B3HTTPHeadersWriter + +@objc +public enum DDInjectEncoding: Int { + case multiple = 0 + case single = 1 +} + +private extension B3HTTPHeadersWriter.InjectEncoding { + init(_ value: DDInjectEncoding) { + switch value { + case .single: + self = .single + case .multiple: + self = .multiple + } + } +} + +@objc +@available(*, deprecated, renamed: "DDB3HTTPHeadersWriter") +public class DDOTelHTTPHeadersWriter: DDB3HTTPHeadersWriter {} + +@objc +public class DDB3HTTPHeadersWriter: NSObject { + let swiftB3HTTPHeadersWriter: B3HTTPHeadersWriter + + @objc public var traceHeaderFields: [String: String] { + swiftB3HTTPHeadersWriter.traceHeaderFields + } + + @objc + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:injectEncoding:)` instead.") + public convenience init( + samplingRate: Float, + injectEncoding: DDInjectEncoding = .single + ) { + self.init(sampleRate: samplingRate, injectEncoding: injectEncoding) + } + + @objc + public init( + sampleRate: Float = 20, + injectEncoding: DDInjectEncoding = .single + ) { + swiftB3HTTPHeadersWriter = B3HTTPHeadersWriter( + sampleRate: sampleRate, + injectEncoding: .init(injectEncoding) + ) + } +} diff --git a/DatadogObjc/Sources/Tracing/Propagation/HTTPHeadersWriter+objc.swift b/DatadogObjc/Sources/Tracing/Propagation/HTTPHeadersWriter+objc.swift index 15b2bcd0a4..46e4b00ad0 100644 --- a/DatadogObjc/Sources/Tracing/Propagation/HTTPHeadersWriter+objc.swift +++ b/DatadogObjc/Sources/Tracing/Propagation/HTTPHeadersWriter+objc.swift @@ -16,7 +16,13 @@ public class DDHTTPHeadersWriter: NSObject { } @objc - public init(samplingRate: Float = 20) { - swiftHTTPHeadersWriter = HTTPHeadersWriter(samplingRate: samplingRate) + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:)` instead.") + public convenience init(samplingRate: Float) { + self.init(sampleRate: samplingRate) + } + + @objc + public init(sampleRate: Float = 20) { + swiftHTTPHeadersWriter = HTTPHeadersWriter(sampleRate: sampleRate) } } diff --git a/DatadogObjc/Sources/Tracing/Propagation/OTelHTTPHeadersWriter+objc.swift b/DatadogObjc/Sources/Tracing/Propagation/OTelHTTPHeadersWriter+objc.swift deleted file mode 100644 index 6ee9941158..0000000000 --- a/DatadogObjc/Sources/Tracing/Propagation/OTelHTTPHeadersWriter+objc.swift +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. - * This product includes software developed at Datadog (https://www.datadoghq.com/). - * Copyright 2019-Present Datadog, Inc. - */ - -import Foundation -import class DatadogInternal.OTelHTTPHeadersWriter - -@objc -public enum DDInjectEncoding: Int { - case multiple = 0 - case single = 1 -} - -private extension OTelHTTPHeadersWriter.InjectEncoding { - init(_ value: DDInjectEncoding) { - switch value { - case .single: - self = .single - case .multiple: - self = .multiple - } - } -} - -@objc -public class DDOTelHTTPHeadersWriter: NSObject { - let swiftOTelHTTPHeadersWriter: OTelHTTPHeadersWriter - - @objc public var traceHeaderFields: [String: String] { - swiftOTelHTTPHeadersWriter.traceHeaderFields - } - - @objc - public init( - samplingRate: Float = 20, - injectEncoding: DDInjectEncoding = .single - ) { - swiftOTelHTTPHeadersWriter = OTelHTTPHeadersWriter( - samplingRate: samplingRate, - injectEncoding: .init(injectEncoding) - ) - } -} diff --git a/DatadogObjc/Sources/Tracing/Propagation/W3CHTTPHeadersWriter+objc.swift b/DatadogObjc/Sources/Tracing/Propagation/W3CHTTPHeadersWriter+objc.swift index a11b4c0c58..4aa06aa565 100644 --- a/DatadogObjc/Sources/Tracing/Propagation/W3CHTTPHeadersWriter+objc.swift +++ b/DatadogObjc/Sources/Tracing/Propagation/W3CHTTPHeadersWriter+objc.swift @@ -16,7 +16,13 @@ public class DDW3CHTTPHeadersWriter: NSObject { } @objc - public init(samplingRate: Float = 20) { - swiftW3CHTTPHeadersWriter = W3CHTTPHeadersWriter(samplingRate: samplingRate) + @available(*, deprecated, message: "This will be removed in future versions of the SDK. Use `init(sampleRate:)` instead.") + public convenience init(samplingRate: Float) { + self.init(sampleRate: samplingRate) + } + + @objc + public init(sampleRate: Float = 20) { + swiftW3CHTTPHeadersWriter = W3CHTTPHeadersWriter(sampleRate: sampleRate) } } diff --git a/DatadogObjc/Sources/Tracing/Trace+objc.swift b/DatadogObjc/Sources/Tracing/Trace+objc.swift index 88d96e7101..df3922f091 100644 --- a/DatadogObjc/Sources/Tracing/Trace+objc.swift +++ b/DatadogObjc/Sources/Tracing/Trace+objc.swift @@ -197,13 +197,13 @@ public class DDTracer: NSObject, DatadogObjc.OTTracer { spanContext: ddspanContext.swiftSpanContext, writer: objcWriter.swiftHTTPHeadersWriter ) - } else if let objcWriter = carrier as? DDOTelHTTPHeadersWriter, format == OT.formatTextMap { + } else if let objcWriter = carrier as? DDB3HTTPHeadersWriter, format == OT.formatTextMap { guard let ddspanContext = spanContext.dd else { return } swiftTracer.inject( spanContext: ddspanContext.swiftSpanContext, - writer: objcWriter.swiftOTelHTTPHeadersWriter + writer: objcWriter.swiftB3HTTPHeadersWriter ) } else if let objcWriter = carrier as? DDW3CHTTPHeadersWriter, format == OT.formatTextMap { guard let ddspanContext = spanContext.dd else { diff --git a/DatadogRUM/Sources/Instrumentation/Resources/URLSessionRUMResourcesHandler.swift b/DatadogRUM/Sources/Instrumentation/Resources/URLSessionRUMResourcesHandler.swift index 0e4f78761c..10a92419a5 100644 --- a/DatadogRUM/Sources/Instrumentation/Resources/URLSessionRUMResourcesHandler.swift +++ b/DatadogRUM/Sources/Instrumentation/Resources/URLSessionRUMResourcesHandler.swift @@ -154,12 +154,12 @@ extension DistributedTracing { // To make sure the generated traces from RUM don’t affect APM Index Spans counts. request.setValue("rum", forHTTPHeaderField: TracingHTTPHeaders.originField) case .b3: - writer = OTelHTTPHeadersWriter( + writer = B3HTTPHeadersWriter( sampler: sampler, injectEncoding: .single ) case .b3multi: - writer = OTelHTTPHeadersWriter( + writer = B3HTTPHeadersWriter( sampler: sampler, injectEncoding: .multiple ) diff --git a/DatadogRUM/Tests/Instrumentation/Resources/URLSessionRUMResourcesHandlerTests.swift b/DatadogRUM/Tests/Instrumentation/Resources/URLSessionRUMResourcesHandlerTests.swift index f7d1686a08..c6e967cdd5 100644 --- a/DatadogRUM/Tests/Instrumentation/Resources/URLSessionRUMResourcesHandlerTests.swift +++ b/DatadogRUM/Tests/Instrumentation/Resources/URLSessionRUMResourcesHandlerTests.swift @@ -67,7 +67,7 @@ class URLSessionRUMResourcesHandlerTests: XCTestCase { ) XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.originField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Single.b3Field), "00000000000000000000000000000001-0000000000000001-1") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Single.b3Field), "00000000000000000000000000000001-0000000000000001-1") } func testGivenFirstPartyInterception_withSampledTrace_itInjectB3MultiTraceHeaders() throws { @@ -87,10 +87,10 @@ class URLSessionRUMResourcesHandlerTests: XCTestCase { ) XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.originField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.traceIDField), "00000000000000000000000000000001") - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.spanIDField), "0000000000000001") - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.parentSpanIDField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.sampledField), "1") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.traceIDField), "00000000000000000000000000000001") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.spanIDField), "0000000000000001") + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.parentSpanIDField)) + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.sampledField), "1") } func testGivenFirstPartyInterception_withSampledTrace_itInjectW3CTraceHeaders() throws { @@ -152,7 +152,7 @@ class URLSessionRUMResourcesHandlerTests: XCTestCase { ) XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.originField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Single.b3Field), "0") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Single.b3Field), "0") } func testGivenFirstPartyInterception_withRejectedTrace_itDoesNotInjectB3MultiTraceHeaders() throws { @@ -172,10 +172,10 @@ class URLSessionRUMResourcesHandlerTests: XCTestCase { ) XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.originField)) - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.traceIDField)) - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.spanIDField)) - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.parentSpanIDField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.sampledField), "0") + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.traceIDField)) + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.spanIDField)) + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.parentSpanIDField)) + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.sampledField), "0") } func testGivenFirstPartyInterception_withRejectedTrace_itDoesNotInjectW3CTraceHeaders() throws { diff --git a/DatadogTrace/Sources/DDFormat.swift b/DatadogTrace/Sources/DDFormat.swift index 785db3de65..01d52cb045 100644 --- a/DatadogTrace/Sources/DDFormat.swift +++ b/DatadogTrace/Sources/DDFormat.swift @@ -9,11 +9,11 @@ import DatadogInternal extension HTTPHeadersReader: OTFormatReader {} extension W3CHTTPHeadersReader: OTFormatReader {} -extension OTelHTTPHeadersReader: OTFormatReader {} +extension B3HTTPHeadersReader: OTFormatReader {} extension HTTPHeadersWriter: OTFormatWriter {} extension W3CHTTPHeadersWriter: OTFormatWriter {} -extension OTelHTTPHeadersWriter: OTFormatWriter {} +extension B3HTTPHeadersWriter: OTFormatWriter {} extension TracePropagationHeadersWriter where Self: OTFormatWriter { public func inject(spanContext: OTSpanContext) { diff --git a/DatadogTrace/Sources/Integrations/TracingURLSessionHandler.swift b/DatadogTrace/Sources/Integrations/TracingURLSessionHandler.swift index 989e7ee184..f6f53b139d 100644 --- a/DatadogTrace/Sources/Integrations/TracingURLSessionHandler.swift +++ b/DatadogTrace/Sources/Integrations/TracingURLSessionHandler.swift @@ -43,12 +43,12 @@ internal struct TracingURLSessionHandler: DatadogURLSessionHandler { case .datadog: writer = HTTPHeadersWriter(sampler: tracingSampler) case .b3: - writer = OTelHTTPHeadersWriter( + writer = B3HTTPHeadersWriter( sampler: tracingSampler, injectEncoding: .single ) case .b3multi: - writer = OTelHTTPHeadersWriter( + writer = B3HTTPHeadersWriter( sampler: tracingSampler, injectEncoding: .multiple ) diff --git a/DatadogTrace/Sources/TraceConfiguration.swift b/DatadogTrace/Sources/TraceConfiguration.swift index ef94ec2ffd..21c7d58414 100644 --- a/DatadogTrace/Sources/TraceConfiguration.swift +++ b/DatadogTrace/Sources/TraceConfiguration.swift @@ -12,6 +12,10 @@ import DatadogInternal @_exported import class DatadogInternal.DatadogURLSessionDelegate @_exported import typealias DatadogInternal.DDURLSessionDelegate @_exported import protocol DatadogInternal.__URLSessionDelegateProviding + +@_exported import class DatadogInternal.HTTPHeadersWriter +@_exported import class DatadogInternal.B3HTTPHeadersWriter +@_exported import class DatadogInternal.W3CHTTPHeadersWriter // swiftlint:enable duplicate_imports extension Trace { diff --git a/DatadogTrace/Tests/TracingURLSessionHandlerTests.swift b/DatadogTrace/Tests/TracingURLSessionHandlerTests.swift index 42ad94f7a2..38439854bb 100644 --- a/DatadogTrace/Tests/TracingURLSessionHandlerTests.swift +++ b/DatadogTrace/Tests/TracingURLSessionHandlerTests.swift @@ -65,11 +65,11 @@ class TracingURLSessionHandlerTests: XCTestCase { XCTAssertEqual(request.value(forHTTPHeaderField: TracingHTTPHeaders.traceIDField), "1") XCTAssertEqual(request.value(forHTTPHeaderField: TracingHTTPHeaders.parentSpanIDField), "1") XCTAssertEqual(request.value(forHTTPHeaderField: TracingHTTPHeaders.samplingPriorityField), "1") - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.traceIDField), "00000000000000000000000000000001") - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.spanIDField), "0000000000000001") - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.parentSpanIDField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.sampledField), "1") - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Single.b3Field), "00000000000000000000000000000001-0000000000000001-1") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.traceIDField), "00000000000000000000000000000001") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.spanIDField), "0000000000000001") + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.parentSpanIDField)) + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.sampledField), "1") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Single.b3Field), "00000000000000000000000000000001-0000000000000001-1") XCTAssertEqual(request.value(forHTTPHeaderField: W3CHTTPHeaders.traceparent), "00-00000000000000000000000000000001-0000000000000001-01") } @@ -96,11 +96,11 @@ class TracingURLSessionHandlerTests: XCTestCase { XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.traceIDField)) XCTAssertNil(request.value(forHTTPHeaderField: TracingHTTPHeaders.parentSpanIDField)) XCTAssertEqual(request.value(forHTTPHeaderField: TracingHTTPHeaders.samplingPriorityField), "0") - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.traceIDField)) - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.spanIDField)) - XCTAssertNil(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.parentSpanIDField)) - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Multiple.sampledField), "0") - XCTAssertEqual(request.value(forHTTPHeaderField: OTelHTTPHeaders.Single.b3Field), "0") + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.traceIDField)) + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.spanIDField)) + XCTAssertNil(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.parentSpanIDField)) + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Multiple.sampledField), "0") + XCTAssertEqual(request.value(forHTTPHeaderField: B3HTTPHeaders.Single.b3Field), "0") XCTAssertEqual(request.value(forHTTPHeaderField: W3CHTTPHeaders.traceparent), "00-00000000000000000000000000000001-0000000000000001-00") }