Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ extension AppRunStep {
app.initializeSDK(sdkSetup ?? { _ in })
app.enableRUM { rumConfig in
rumSetup?(&rumConfig)
rumConfig.sessionEndedSampleRate = 0 // TODO: RUM-9335 Enable "Session Ended" telemetry after fixing `application.id` value for session stop
rumConfig.telemetrySampleRate = 0
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class RUMSessionEndedMetricIntegrationTests: XCTestCase {
monitor.stopSession()

// Then
let metricAttributes = try XCTUnwrap(core.waitAndReturnSessionEndedMetricEvent()?.attributes)
let event = try XCTUnwrap(core.waitAndReturnSessionEndedMetricEvent())
XCTAssertEqual(event.application?.id, rumConfig.applicationID, "It must report `application.id` even though the session no longer exists")
let metricAttributes = try XCTUnwrap(event.attributes)
XCTAssertTrue(metricAttributes.wasStopped)
}

Expand Down
1 change: 1 addition & 0 deletions DatadogRUM/Sources/Feature/RUMFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ internal final class RUMFeature: DatadogRemoteFeature, RUMSessionSamplerProvider
TelemetryInterceptor(sessionEndedMetric: sessionEndedMetric),
TelemetryReceiver(
featureScope: featureScope,
applicationID: configuration.applicationID,
dateProvider: configuration.dateProvider,
sampler: Sampler(samplingRate: configuration.telemetrySampleRate),
configurationExtraSampler: Sampler(samplingRate: configuration.configurationTelemetrySampleRate)
Expand Down
8 changes: 7 additions & 1 deletion DatadogRUM/Sources/Integrations/TelemetryReceiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ internal final class TelemetryReceiver: FeatureMessageReceiver {

/// RUM feature scope.
let featureScope: FeatureScope
/// The RUM application ID. It is known upfront, so telemetry can be attributed to the application
/// even when no RUM session exists (e.g. after the session expired or was stopped).
let applicationID: String
let dateProvider: DateProvider

/// Sampler for all telemetry events.
Expand All @@ -41,16 +44,19 @@ internal final class TelemetryReceiver: FeatureMessageReceiver {
///
/// - Parameters:
/// - featureScope: RUM feature scope.
/// - applicationID: The RUM application ID.
/// - dateProvider: Current device time provider.
/// - sampler: Telemetry events sampler.
/// - configurationExtraSampler: Extra sampler for configuration events (applied on top of `sampler`).
init(
featureScope: FeatureScope,
applicationID: String,
dateProvider: DateProvider,
sampler: Sampler,
configurationExtraSampler: Sampler
) {
self.featureScope = featureScope
self.applicationID = applicationID
self.dateProvider = dateProvider
self.sampler = sampler
self.configurationExtraSampler = configurationExtraSampler
Expand Down Expand Up @@ -285,7 +291,7 @@ internal final class TelemetryReceiver: FeatureMessageReceiver {
let event = TelemetryDebugEvent(
dd: .init(),
action: rum?.userActionID.map { .init(id: .string(value: $0)) },
application: rum.map { .init(id: $0.applicationID) },
application: .init(id: self.applicationID),
date: date.addingTimeInterval(context.serverTimeOffset).timeIntervalSince1970.dd.toInt64Milliseconds,
effectiveSampleRate: Double(effectiveSampleRate),
experimentalFeatures: nil,
Expand Down
18 changes: 16 additions & 2 deletions DatadogRUM/Tests/Integrations/TelemetryReceiverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ class TelemetryReceiverTests: XCTestCase {
let osMock: OperatingSystem = .mockRandom()
featureScope.contextMock = .mockWith(device: deviceMock, os: osMock)
featureScope.contextMock.set(additionalContext: rumContext)
let receiver = TelemetryReceiver.mockWith(featureScope: featureScope)
let receiver = TelemetryReceiver.mockWith(featureScope: featureScope, applicationID: rumContext.applicationID)

// When
TelemetryMock(with: receiver).metric(name: .mockRandom(), attributes: mockRandomAttributes(), sampleRate: 100)
Expand All @@ -524,7 +524,7 @@ class TelemetryReceiverTests: XCTestCase {
// Given
let rumContext: RUMCoreContext = .mockRandom()
featureScope.contextMock.set(additionalContext: rumContext)
let receiver = TelemetryReceiver.mockWith(featureScope: featureScope)
let receiver = TelemetryReceiver.mockWith(featureScope: featureScope, applicationID: rumContext.applicationID)
let sessionIDOverride = "session-id-override"

// When
Expand All @@ -541,6 +541,20 @@ class TelemetryReceiverTests: XCTestCase {
XCTAssertNil(event?.telemetry.telemetryInfo[SDKMetricFields.sessionIDOverrideKey], "It should delete `sessionIDOverrideKey` from metric attributes")
}

func testSendTelemetryMetricWithNoRUMContext() {
// Given
let applicationID: String = .mockRandom()
let receiver = TelemetryReceiver.mockWith(featureScope: featureScope, applicationID: applicationID)

// When: no RUM context exists, e.g. the session expired or was stopped
TelemetryMock(with: receiver).metric(name: .mockRandom(), attributes: mockRandomAttributes(), sampleRate: 100)

// Then
let event = featureScope.eventsWritten(ofType: TelemetryDebugEvent.self).first
XCTAssertEqual(event?.application?.id, applicationID, "It should attribute the metric to the RUM application even with no session")
XCTAssertNil(event?.session?.id, "It should not report a session ID when no session exists")
}

func testMethodCallTelemetryPropagatesAllData() throws {
// Given
let deviceMock: DeviceInfo = .mockRandom()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1594,12 +1594,14 @@ extension TelemetryReceiver: AnyMockable {

public static func mockWith(
featureScope: FeatureScope = NOPFeatureScope(),
applicationID: String = .mockAny(),
dateProvider: DateProvider = SystemDateProvider(),
sampler: Sampler = .mockKeepAll(),
configurationExtraSampler: Sampler = .mockKeepAll()
) -> Self {
.init(
featureScope: featureScope,
applicationID: applicationID,
dateProvider: dateProvider,
sampler: sampler,
configurationExtraSampler: configurationExtraSampler
Expand Down