Skip to content

Commit

Permalink
Merge pull request #709 from DataDog/ncreated/RUMM-1744-collect-Krono…
Browse files Browse the repository at this point in the history
…s-telemetry-in-internal-monitoring

RUMM-1744 Collect Kronos telemetry in Internal Monitoring
  • Loading branch information
ncreated authored Jan 11, 2022
2 parents 10b4943 + 62b76a8 commit 79c63be
Show file tree
Hide file tree
Showing 8 changed files with 556 additions and 10 deletions.
24 changes: 24 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@
617B954224BF4E7600E6F443 /* RUMMonitorConfigurationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 617B954124BF4E7600E6F443 /* RUMMonitorConfigurationTests.swift */; };
617CD0DD24CEDDD300B0B557 /* RUMUserActionScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 617CD0DC24CEDDD300B0B557 /* RUMUserActionScopeTests.swift */; };
617CEB392456BC3A00AD4669 /* TracingUUID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 617CEB382456BC3A00AD4669 /* TracingUUID.swift */; };
61815C06278867D1004A666C /* KronosMonitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61815C05278867D1004A666C /* KronosMonitorTests.swift */; };
618236892710560900125326 /* DebugWebviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618236882710560900125326 /* DebugWebviewViewController.swift */; };
6182374325D3DFD5006A375B /* CrashReportingWithRUMIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6182374225D3DFD5006A375B /* CrashReportingWithRUMIntegrationTests.swift */; };
6184751526EFCF1300C7C9C5 /* DatadogTestsObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6184751426EFCF1300C7C9C5 /* DatadogTestsObserver.swift */; };
Expand Down Expand Up @@ -493,6 +494,7 @@
61FF283024BC5E2D000B3D9B /* RUMEventFileOutputTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FF282F24BC5E2D000B3D9B /* RUMEventFileOutputTests.swift */; };
61FF416225EE5FF400CE35EC /* CrashReportingWithLoggingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FF416125EE5FF400CE35EC /* CrashReportingWithLoggingIntegrationTests.swift */; };
61FF9A4525AC5DEA001058CC /* RUMViewIdentity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FF9A4425AC5DEA001058CC /* RUMViewIdentity.swift */; };
61FFFB89278457D400401A28 /* KronosMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FFFB88278457D300401A28 /* KronosMonitor.swift */; };
9E26E6B924C87693000B3270 /* RUMDataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E26E6B824C87693000B3270 /* RUMDataModels.swift */; };
9E2EF44F2694FA14008A7DAE /* VitalInfoSamplerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E2EF44E2694FA14008A7DAE /* VitalInfoSamplerTests.swift */; };
9E307C3224C8846D0039607E /* RUMDataModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E26E6B824C87693000B3270 /* RUMDataModels.swift */; };
Expand Down Expand Up @@ -950,6 +952,7 @@
617B954124BF4E7600E6F443 /* RUMMonitorConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMMonitorConfigurationTests.swift; sourceTree = "<group>"; };
617CD0DC24CEDDD300B0B557 /* RUMUserActionScopeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMUserActionScopeTests.swift; sourceTree = "<group>"; };
617CEB382456BC3A00AD4669 /* TracingUUID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingUUID.swift; sourceTree = "<group>"; };
61815C05278867D1004A666C /* KronosMonitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KronosMonitorTests.swift; sourceTree = "<group>"; };
618236882710560900125326 /* DebugWebviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugWebviewViewController.swift; sourceTree = "<group>"; };
6182374225D3DFD5006A375B /* CrashReportingWithRUMIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportingWithRUMIntegrationTests.swift; sourceTree = "<group>"; };
6184751426EFCF1300C7C9C5 /* DatadogTestsObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatadogTestsObserver.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1175,6 +1178,7 @@
61FF282F24BC5E2D000B3D9B /* RUMEventFileOutputTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMEventFileOutputTests.swift; sourceTree = "<group>"; };
61FF416125EE5FF400CE35EC /* CrashReportingWithLoggingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportingWithLoggingIntegrationTests.swift; sourceTree = "<group>"; };
61FF9A4425AC5DEA001058CC /* RUMViewIdentity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMViewIdentity.swift; sourceTree = "<group>"; };
61FFFB88278457D300401A28 /* KronosMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KronosMonitor.swift; sourceTree = "<group>"; };
9E0542CA25F8EBBE007A3D0B /* Kronos.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Kronos.xcframework; path = ../Carthage/Build/Kronos.xcframework; sourceTree = "<group>"; };
9E26E6B824C87693000B3270 /* RUMDataModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RUMDataModels.swift; sourceTree = "<group>"; };
9E2EF44E2694FA14008A7DAE /* VitalInfoSamplerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VitalInfoSamplerTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2545,6 +2549,14 @@
path = UUIDs;
sourceTree = "<group>";
};
61815C04278867BB004A666C /* Kronos */ = {
isa = PBXGroup;
children = (
61815C05278867D1004A666C /* KronosMonitorTests.swift */,
);
path = Kronos;
sourceTree = "<group>";
};
6182374125D3DFB8006A375B /* CrashReporting */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3107,6 +3119,7 @@
children = (
61F1878325FA121F0022CE9A /* InternalMonitoringFeature.swift */,
61F1878C25FA33A90022CE9A /* InternalMonitor.swift */,
61FFFB8A2784593B00401A28 /* Kronos */,
);
path = InternalMonitoring;
sourceTree = "<group>";
Expand All @@ -3115,6 +3128,7 @@
isa = PBXGroup;
children = (
61F187FB25FA7DD60022CE9A /* InternalMonitoringFeatureTests.swift */,
61815C04278867BB004A666C /* Kronos */,
);
path = InternalMonitoring;
sourceTree = "<group>";
Expand Down Expand Up @@ -3288,6 +3302,14 @@
path = RUMEventOutputs;
sourceTree = "<group>";
};
61FFFB8A2784593B00401A28 /* Kronos */ = {
isa = PBXGroup;
children = (
61FFFB88278457D300401A28 /* KronosMonitor.swift */,
);
path = Kronos;
sourceTree = "<group>";
};
9E06058F26EF904200F5F935 /* LongTasks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -4111,6 +4133,7 @@
61D3E0D3277B23F1008BE766 /* KronosDNSResolver.swift in Sources */,
6149FB3A2529D17F00EE387A /* InternalURLsFilter.swift in Sources */,
611529A525E3DD51004F740E /* ValuePublisher.swift in Sources */,
61FFFB89278457D400401A28 /* KronosMonitor.swift in Sources */,
618DCFD724C7265300589570 /* RUMUUID.swift in Sources */,
61B038662527247800518F3C /* URLSessionInterceptor.swift in Sources */,
61B03898252724DE00518F3C /* TracingHTTPHeaders.swift in Sources */,
Expand Down Expand Up @@ -4347,6 +4370,7 @@
61F1A623249B811200075390 /* Encoding.swift in Sources */,
6114FE3B25768AA90084E372 /* ConsentProviderTests.swift in Sources */,
61133C642423990D00786299 /* LoggerTests.swift in Sources */,
61815C06278867D1004A666C /* KronosMonitorTests.swift in Sources */,
617B953D24BF4D8F00E6F443 /* RUMMonitorTests.swift in Sources */,
D244B3A3271EDACD003E1B29 /* SwiftUIExtensionsTests.swift in Sources */,
61F187FC25FA7DD60022CE9A /* InternalMonitoringFeatureTests.swift in Sources */,
Expand Down
33 changes: 31 additions & 2 deletions Datadog/E2ETests/NTP/KronosE2ETests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,45 @@
@testable import Datadog

class KronosE2ETests: E2ETests {
/// The logger sending additional telemetry on Kronos execution. These logs are available in Mobile Integrations org.
/// The logger sending logs on Kronos execution. These logs are available in Mobile Integrations org.
private var logger: Logger! // swiftlint:disable:this implicitly_unwrapped_optional
/// The logger sending telemetry on internal Kronos execution. These logs are available in Mobile Integrations org.
private var telemetryLogger: Logger! // swiftlint:disable:this implicitly_unwrapped_optional
private let queue = DispatchQueue(label: "kronos-monitor-queue")

override func setUp() {
super.setUp()
logger = Logger
.builder
.set(loggerName: "kronos-e2e")
.build()
telemetryLogger = Logger.builder
.set(loggerName: "kronos-e2e-internal-telemetry")
.sendNetworkInfo(true)
.build()
}

override func tearDown() {
logger = nil
telemetryLogger = nil
super.tearDown()
}

/// Creates kronos monitor for checking connections to all IPs resolved from NTP pool and sending additional telemetry on their statuses.
private func createKronosMonitor() -> KronosMonitor? {
if #available(iOS 14.2, *) {
let monitor = KronosInternalMonitor(
queue: queue,
connectionMonitor: IPConnectionMonitor(queue: queue)
)
// Here we redirect IM's logger to E2E Kronos logger (`telemetryLogger`) to send data to Mobile Integrations org, not IM's org
monitor.export(to: InternalMonitor(sdkLogger: telemetryLogger))
return monitor
} else {
return nil
}
}

/// TODO: RUMM-1859: Add E2E tests for monitoring Kronos in nightly tests
func test_kronos_clock_performs_sync_using_datadog_ntp_pool() { // E2E:wip
/// The result of `KronosClock.sync()`.
Expand Down Expand Up @@ -58,6 +81,7 @@ class KronosE2ETests: E2ETests {
KronosClock.sync(
from: pool,
samples: numberOfSamplesForEachIP,
monitor: createKronosMonitor(),
first: { date, offset in // this closure could not be called if all samples to all servers resulted with failure
result.firstReceivedDate = date
result.firstReceivedOffset = offset
Expand Down Expand Up @@ -122,6 +146,7 @@ class KronosE2ETests: E2ETests {

func performKronosNTPClientQuery() -> KronosNTPClientQueryResult {
let testTimeout: TimeInterval = 30
let monitor = createKronosMonitor()

// Given
let pool = "2.datadog.pool.ntp.org" // a pool resolved to multiple IPv4 and IPv6 addresses (e.g. 4 + 4)
Expand All @@ -136,18 +161,22 @@ class KronosE2ETests: E2ETests {
let completionExpectation = expectation(description: "It completes all samples for all IPs")
var result = KronosNTPClientQueryResult()

monitor?.notifySyncStart(from: pool) // must be notified by hand because normally it's called from `KronosClock.sync()`

KronosNTPClient()
.query(
pool: pool,
numberOfSamples: numberOfSamplesForEachIP,
maximumServers: .max, // query all resolved IPs in the pool - to include both IPv4 and IPv6
timeout: timeoutForEachSample
timeout: timeoutForEachSample,
monitor: monitor
) { offset, completed, total in
result.receivedOffsets.append(offset)
result.numberOfCompletedSamples = completed
result.expectedNumberOfSamples = total

if completed == total {
monitor?.notifySyncEnd(serverOffset: offset) // must be notified by hand because normally it's called from `KronosClock.sync()`
completionExpectation.fulfill()
}
}
Expand Down
11 changes: 10 additions & 1 deletion Sources/Datadog/Core/System/Time/ServerDateProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ internal class NTPServerDateProvider: ServerDateProvider {
/// Server offset publisher.
private let publisher: ValuePublisher<TimeInterval?> = ValuePublisher(initialValue: nil)

/// Monitor collecting Kronos telemetry - only enabled if Internal Monitoring is configured.
private let kronosMonitor: KronosMonitor?

init(kronosMonitor: KronosMonitor? = nil) {
self.kronosMonitor = kronosMonitor
}

/// Returns the server time offset or `nil` if not yet determined.
/// This offset gets more precise while synchronization is pending.
var offset: TimeInterval? {
Expand All @@ -29,6 +36,7 @@ internal class NTPServerDateProvider: ServerDateProvider {
func synchronize(with pool: String, completion: @escaping (TimeInterval?) -> Void) {
KronosClock.sync(
from: pool,
monitor: kronosMonitor,
first: { [weak self] _, offset in
self?.publisher.publishAsync(offset)
},
Expand All @@ -40,7 +48,8 @@ internal class NTPServerDateProvider: ServerDateProvider {
// Kronos only notifies for the first and last samples.
// In case, the last sample does not return an offset, we calculate the offset
// from the returned `now` parameter. The `now` parameter in this callback
// is `Clock.now`, so it is possible to have `now` but not `offset`.
// is `Clock.now` and it can be either offset computed from prior samples or persisted
// in user defaults from previous app session.
if let offset = offset {
self.publisher.publishAsync(offset)
} else if let now = now {
Expand Down
16 changes: 15 additions & 1 deletion Sources/Datadog/Datadog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,19 @@ public class Datadog {
throw ProgrammerError(description: "SDK is already initialized.")
}

let kronosMonitor: KronosMonitor?
#if DD_SDK_ENABLE_INTERNAL_MONITORING
// Collect Kronos telemetry only if internal monitoring is compiled and enabled
kronosMonitor = configuration.internalMonitoring != nil ? KronosInternalMonitor() : nil
#else
kronosMonitor = nil
#endif

let consentProvider = ConsentProvider(initialConsent: initialTrackingConsent)
let dateProvider = SystemDateProvider()
let dateCorrector = DateCorrector(
deviceDateProvider: dateProvider,
serverDateProvider: NTPServerDateProvider()
serverDateProvider: NTPServerDateProvider(kronosMonitor: kronosMonitor)
)
let userInfoProvider = UserInfoProvider()
let networkConnectionInfoProvider = NetworkConnectionInfoProvider()
Expand Down Expand Up @@ -305,6 +313,12 @@ public class Datadog {
Global.crashReporter = CrashReporter(crashReportingFeature: crashReportingFeature)
Global.crashReporter?.sendCrashReportIfFound()
}

// If Internal Monitoring is enabled and Kronos internal monitor is configured,
// export result of NTP sync to IM.
if let internalMonitoringFeature = InternalMonitoringFeature.instance {
kronosMonitor?.export(to: internalMonitoringFeature.monitor)
}
}

internal init(
Expand Down
Loading

0 comments on commit 79c63be

Please sign in to comment.