Skip to content

Commit b347f76

Browse files
Merge pull request #2470 from DataDog/simaoseica/RUM-11136/move-session-properties-to-ddtags
RUM-11136: Move ddtags query parameters to RUM events
2 parents 2d23bb6 + 00ea0c8 commit b347f76

18 files changed

Lines changed: 196 additions & 50 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Unreleased
22
- [FEATURE] Send Accessibility attributes in View Updates. See [#2410][]
33
- [IMPROVEMENT] Add missing `versionMajor` property to the `DDLogEventOperatingSystem` definition in Objective-C. See [#2463][]
4+
- [IMPROVEMENT] Add `ddtags` to RUM events. See [#2436][]
45

56
# 3.0.0 / 02-09-2025
67

@@ -956,6 +957,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO
956957
[#2455]: https://github.com/DataDog/dd-sdk-ios/pull/2455
957958
[#2463]: https://github.com/DataDog/dd-sdk-ios/pull/2463
958959
[#2410]: https://github.com/DataDog/dd-sdk-ios/pull/2410
960+
[#2436]: https://github.com/DataDog/dd-sdk-ios/pull/2436
959961

960962
[@00fa9a]: https://github.com/00FA9A
961963
[@britton-earnin]: https://github.com/Britton-Earnin

Datadog/Datadog.xcodeproj/project.pbxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6740,6 +6740,7 @@
67406740
D2DA239C298D58F300C6C7E6 /* Context */ = {
67416741
isa = PBXGroup;
67426742
children = (
6743+
11E4B7172E4DF87F005C1767 /* DatadogContextTests.swift */,
67436744
D2DA239D298D58F300C6C7E6 /* AppStateHistoryTests.swift */,
67446745
D2DA239E298D58F300C6C7E6 /* DeviceInfoTests.swift */,
67456746
6174D6152BFDF29B00EC7469 /* BundleTypeTests.swift */,
@@ -10128,6 +10129,7 @@
1012810129
D2DA23A3298D58F400C6C7E6 /* AnyEncodableTests.swift in Sources */,
1012910130
3CCECDAF2BC688120013C125 /* SpanIDGeneratorTests.swift in Sources */,
1013010131
D263BCB429DB014900FA0E21 /* FixedWidthInteger+ConvenienceTests.swift in Sources */,
10132+
11E4B7182E4DF88A005C1767 /* DatadogContextTests.swift in Sources */,
1013110133
960A0D402D6F88A0004BB999 /* ReflectorTests.swift in Sources */,
1013210134
6174D6162BFDF29B00EC7469 /* BundleTypeTests.swift in Sources */,
1013310135
116F84062CFDD06700705755 /* SampleRateTests.swift in Sources */,
@@ -10194,6 +10196,7 @@
1019410196
D284C7412C2059F3005142CC /* ObjcExceptionTests.swift in Sources */,
1019510197
D2C5D5292B83FD5400B63F36 /* WebViewMessageTests.swift in Sources */,
1019610198
D20731CE29A52E8700ECBF94 /* SamplerTests.swift in Sources */,
10199+
11E4B7192E4DF88A005C1767 /* DatadogContextTests.swift in Sources */,
1019710200
D2160CEA29C0E00200FAA9A5 /* MethodSwizzlerTests.swift in Sources */,
1019810201
D2EBEE4229BA163F00B15732 /* W3CHTTPHeadersReaderTests.swift in Sources */,
1019910202
D2160CDD29C0DF6700FAA9A5 /* HostsSanitizerTests.swift in Sources */,

Datadog/IntegrationUnitTests/RUM/RUMAttributesIntegrationTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class RUMAttributesIntegrationTests: XCTestCase {
1919
rumConfig = RUM.Configuration(applicationID: .mockAny())
2020
}
2121

22-
override func tearDownWithError() throws {
22+
override func tearDownWithError() throws {
2323
try core.flushAndTearDown()
2424
core = nil
2525
super.tearDown()

DatadogCore/Tests/Datadog/RUM/RUMFeatureTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class RUMFeatureTests: XCTestCase {
9191
XCTAssertEqual(
9292
requestURL.query,
9393
"""
94-
ddsource=\(randomSource)&ddtags=service:\(randomServiceName),version:\(randomApplicationVersion),sdk_version:\(randomSDKVersion),env:\(randomEnvironmentName),retry_count:1
94+
ddsource=\(randomSource)&ddtags=retry_count:1
9595
"""
9696
)
9797
XCTAssertEqual(

DatadogInternal/Sources/Context/DatadogContext.swift

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,14 @@ public struct DatadogContext {
158158
) {
159159
self.site = site
160160
self.clientToken = clientToken
161-
self.service = service
162-
self.env = env
163-
self.version = version
161+
self.service = service.sanitizedToDDTags()
162+
self.env = env.sanitizedToDDTags()
163+
self.version = version.sanitizedToDDTags()
164164
self.buildNumber = buildNumber
165165
self.buildId = buildId
166-
self.variant = variant
166+
self.variant = variant?.sanitizedToDDTags()
167167
self.source = source
168-
self.sdkVersion = sdkVersion
168+
self.sdkVersion = sdkVersion.sanitizedToDDTags()
169169
self.ciAppOrigin = ciAppOrigin
170170
self.serverTimeOffset = serverTimeOffset
171171
self.applicationName = applicationName
@@ -197,6 +197,24 @@ public protocol AdditionalContext {
197197
static var key: String { get }
198198
}
199199

200+
extension DatadogContext {
201+
/// Datadog tags to send in the events.
202+
public var ddTags: String {
203+
var tags = [
204+
"service": service,
205+
"version": version,
206+
"sdk_version": sdkVersion,
207+
"env": env
208+
]
209+
210+
if let variant {
211+
tags["variant"] = variant
212+
}
213+
214+
return tags.map { "\($0.key):\($0.value)" }.joined(separator: ",")
215+
}
216+
}
217+
200218
extension DatadogContext {
201219
/// Gets an additional context value of `Context` type.
202220
///
@@ -228,3 +246,9 @@ extension DatadogContext {
228246
additionalContext[Context.key] = nil
229247
}
230248
}
249+
250+
extension String {
251+
func sanitizedToDDTags() -> String {
252+
self.replacingOccurrences(of: "[,:]", with: "", options: .regularExpression)
253+
}
254+
}

DatadogInternal/Sources/Models/CrashReporting/CrashContext.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ public struct CrashContext: Codable, Equatable {
108108
lastLogAttributes: LogEventAttributes?
109109
) {
110110
self.serverTimeOffset = serverTimeOffset
111-
self.service = service
112-
self.env = env
113-
self.version = version
111+
self.service = service.sanitizedToDDTags()
112+
self.env = env.sanitizedToDDTags()
113+
self.version = version.sanitizedToDDTags()
114114
self.buildNumber = buildNumber
115115
self.device = device
116116
self.os = os
117-
self.sdkVersion = service
117+
self.sdkVersion = service.sanitizedToDDTags()
118118
self.source = source
119119
self.trackingConsent = trackingConsent
120120
self.userInfo = userInfo
@@ -179,3 +179,18 @@ public struct CrashContext: Codable, Equatable {
179179
lhs.appLaunchDate == rhs.appLaunchDate
180180
}
181181
}
182+
183+
extension CrashContext {
184+
/// Datadog tags to send in the error events.
185+
public var ddTags: String {
186+
let tags = [
187+
"service": service,
188+
"version": version,
189+
"sdk_version": sdkVersion,
190+
"env": env
191+
]
192+
193+
return tags.map { "\($0.key):\($0.value)" }
194+
.joined(separator: ",")
195+
}
196+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2019-Present Datadog, Inc.
5+
*/
6+
7+
import DatadogInternal
8+
import TestUtilities
9+
import XCTest
10+
11+
final class DatadogContextTests: XCTestCase {
12+
// MARK: - Test ddtags
13+
14+
func testDatadogDDTags() throws {
15+
// Given
16+
let service: String = .mockRandom()
17+
let env: String = .mockRandom()
18+
let version: String = .mockRandom()
19+
let sdkVersion: String = .mockRandom()
20+
let variant: String = .mockRandom()
21+
let datadogContext: DatadogContext = .mockWith(
22+
service: service,
23+
env: env,
24+
version: version,
25+
variant: variant,
26+
sdkVersion: sdkVersion
27+
)
28+
29+
// Then
30+
let ddTagsArray = datadogContext.ddTags.split(separator: ",")
31+
32+
let ddTags = ddTagsArray.reduce(into: [:]) {
33+
let item = $1.split(separator: ":")
34+
$0[String(item[0])] = String(item[1])
35+
}
36+
37+
XCTAssertEqual(ddTags["service"] as! String, service)
38+
XCTAssertEqual(ddTags["env"] as! String, env)
39+
XCTAssertEqual(ddTags["version"] as! String, version)
40+
XCTAssertEqual(ddTags["sdk_version"] as! String, sdkVersion)
41+
XCTAssertEqual(ddTags["variant"] as! String, variant)
42+
}
43+
44+
func testDatadogSanitizedDDTags() throws {
45+
// Given
46+
let service = "service:with:colons"
47+
let env = "prod,dev"
48+
let version = "1,2,3"
49+
let sdkVersion = "3,2,1"
50+
let variant = "variant,with,commas:"
51+
let datadogContext: DatadogContext = .mockWith(
52+
service: service,
53+
env: env,
54+
version: version,
55+
variant: variant,
56+
sdkVersion: sdkVersion
57+
)
58+
59+
// Then
60+
let ddTagsArray = datadogContext.ddTags.split(separator: ",")
61+
62+
let ddTags = ddTagsArray.reduce(into: [:]) {
63+
let item = $1.split(separator: ":")
64+
$0[String(item[0])] = String(item[1])
65+
}
66+
67+
XCTAssertEqual(ddTags["service"] as! String, "servicewithcolons")
68+
XCTAssertEqual(ddTags["env"] as! String, "proddev")
69+
XCTAssertEqual(ddTags["version"] as! String, "123")
70+
XCTAssertEqual(ddTags["sdk_version"] as! String, "321")
71+
XCTAssertEqual(ddTags["variant"] as! String, "variantwithcommas")
72+
}
73+
74+
func testDatadogDDTagsWithoutVariant() throws {
75+
// Given
76+
let service: String = .mockRandom()
77+
let env: String = .mockRandom()
78+
let version: String = .mockRandom()
79+
let sdkVersion: String = .mockRandom()
80+
let datadogContext: DatadogContext = .mockWith(
81+
service: service,
82+
env: env,
83+
version: version,
84+
variant: nil,
85+
sdkVersion: sdkVersion
86+
)
87+
88+
// Then
89+
let ddTagsArray = datadogContext.ddTags.split(separator: ",")
90+
91+
let ddTags = ddTagsArray.reduce(into: [:]) {
92+
let item = $1.split(separator: ":")
93+
$0[String(item[0])] = String(item[1])
94+
}
95+
96+
XCTAssertEqual(ddTags["service"] as! String, service)
97+
XCTAssertEqual(ddTags["env"] as! String, env)
98+
XCTAssertEqual(ddTags["version"] as! String, version)
99+
XCTAssertEqual(ddTags["sdk_version"] as! String, sdkVersion)
100+
XCTAssertNil(ddTags["variant"])
101+
}
102+
}

DatadogRUM/Sources/FatalErrorBuilder.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ internal struct FatalErrorBuilder {
8383
contextInfo: contextInfo
8484
),
8585
date: errorDate.timeIntervalSince1970.toInt64Milliseconds,
86+
ddtags: context.ddTags,
8687
device: lastRUMView.device,
8788
display: nil,
8889
error: .init(
@@ -161,6 +162,7 @@ internal struct FatalErrorBuilder {
161162
container: original.container,
162163
context: original.context,
163164
date: errorDate.timeIntervalSince1970.toInt64Milliseconds - 1, // -1ms to put the fatal error after view in RUM session
165+
ddtags: context.ddTags,
164166
device: original.device,
165167
display: original.display,
166168
os: original.os,

DatadogRUM/Sources/Feature/RequestBuilder.swift

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,7 @@ internal struct RequestBuilder: FeatureRequestBuilder {
2727
with context: DatadogContext,
2828
execution: ExecutionContext
2929
) throws -> URLRequest {
30-
var tags = [
31-
"service:\(context.service)",
32-
"version:\(context.version)",
33-
"sdk_version:\(context.sdkVersion)",
34-
"env:\(context.env)"
35-
]
36-
37-
if let variant = context.variant {
38-
tags.append("variant:\(variant)")
39-
}
40-
41-
tags.append("retry_count:\(execution.attempt + 1)")
30+
var tags = ["retry_count:\(execution.attempt + 1)"]
4231
if let previousResponseCode = execution.previousResponseCode {
4332
tags.append("last_failure_status:\(previousResponseCode)")
4433
}

DatadogRUM/Sources/Integrations/CrashReportReceiver.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ internal struct CrashReportReceiver: FeatureMessageReceiver {
335335
// See https://github.com/DataDog/dd-sdk-ios/pull/1834 for more context.
336336
context: context.lastRUMAttributes,
337337
date: startDate.timeIntervalSince1970.toInt64Milliseconds,
338+
ddtags: context.ddTags,
338339
device: context.device,
339340
display: nil,
340341
// RUMM-2197: In very rare cases, the OS info computed below might not be exactly the one

0 commit comments

Comments
 (0)