Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NTP synchronization by using Kronos. #54

Merged
merged 2 commits into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 49 additions & 8 deletions DatadogSDKTesting.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
E14405DB25DBC3A800FE3D3C /* GitInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14405D825DBC3A800FE3D3C /* GitInfoTests.swift */; };
E14AA0C12555AA61003FA711 /* DDNetworkInstrumentationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14AA0BF2555A9A1003FA711 /* DDNetworkInstrumentationTests.swift */; };
E14AA0CA255AE8D3003FA711 /* SignalUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E14AA0C9255AE8D3003FA711 /* SignalUtilsTests.swift */; };
E150325A271860A8000CD6C5 /* Kronos in Frameworks */ = {isa = PBXBuildFile; productRef = E1503259271860A8000CD6C5 /* Kronos */; };
E150325C271860BF000CD6C5 /* NTPClock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E150325B271860BF000CD6C5 /* NTPClock.swift */; };
E150325D271860BF000CD6C5 /* NTPClock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E150325B271860BF000CD6C5 /* NTPClock.swift */; };
E150325E271860BF000CD6C5 /* NTPClock.swift in Sources */ = {isa = PBXBuildFile; fileRef = E150325B271860BF000CD6C5 /* NTPClock.swift */; };
E1503260271860E0000CD6C5 /* Kronos in Frameworks */ = {isa = PBXBuildFile; productRef = E150325F271860E0000CD6C5 /* Kronos */; };
E1503262271860E7000CD6C5 /* Kronos in Frameworks */ = {isa = PBXBuildFile; productRef = E1503261271860E7000CD6C5 /* Kronos */; };
E15264AF25FA3C16008B8665 /* DDSymbolicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15264AE25FA3C16008B8665 /* DDSymbolicatorTests.swift */; };
E15264B025FA3C16008B8665 /* DDSymbolicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15264AE25FA3C16008B8665 /* DDSymbolicatorTests.swift */; };
E15264B125FA3C16008B8665 /* DDSymbolicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15264AE25FA3C16008B8665 /* DDSymbolicatorTests.swift */; };
Expand Down Expand Up @@ -423,6 +429,7 @@
E14405D825DBC3A800FE3D3C /* GitInfoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitInfoTests.swift; sourceTree = "<group>"; };
E14AA0BF2555A9A1003FA711 /* DDNetworkInstrumentationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDNetworkInstrumentationTests.swift; sourceTree = "<group>"; };
E14AA0C9255AE8D3003FA711 /* SignalUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalUtilsTests.swift; sourceTree = "<group>"; };
E150325B271860BF000CD6C5 /* NTPClock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NTPClock.swift; sourceTree = "<group>"; };
E15264AE25FA3C16008B8665 /* DDSymbolicatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDSymbolicatorTests.swift; sourceTree = "<group>"; };
E157A74D256E9D1D00CBCA52 /* DatadogSDKTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DatadogSDKTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E157A785256E9D3300CBCA52 /* DatadogSDKTesting.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DatadogSDKTesting.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -524,6 +531,7 @@
buildActionMask = 2147483647;
files = (
E157A742256E9D1D00CBCA52 /* CrashReporter in Frameworks */,
E1503260271860E0000CD6C5 /* Kronos in Frameworks */,
E12248E226455E0300305968 /* libURLSessionInstrumentation in Frameworks */,
E157A744256E9D1D00CBCA52 /* SigmaSwiftStatistics in Frameworks */,
E12248EA26455ED800305968 /* libInMemoryExporter in Frameworks */,
Expand All @@ -537,6 +545,7 @@
buildActionMask = 2147483647;
files = (
E157A77A256E9D3300CBCA52 /* CrashReporter in Frameworks */,
E1503262271860E7000CD6C5 /* Kronos in Frameworks */,
E12248E626455E1300305968 /* libURLSessionInstrumentation in Frameworks */,
E157A77C256E9D3300CBCA52 /* SigmaSwiftStatistics in Frameworks */,
E12248EC26455EDE00305968 /* libInMemoryExporter in Frameworks */,
Expand Down Expand Up @@ -566,6 +575,7 @@
buildActionMask = 2147483647;
files = (
E12248DE26455DEB00305968 /* libDatadogExporter in Frameworks */,
E150325A271860A8000CD6C5 /* Kronos in Frameworks */,
E1FB483B253891650083B263 /* CrashReporter in Frameworks */,
E17B7AA8253F02580081D7F3 /* SigmaSwiftStatistics in Frameworks */,
E12248E826455ED100305968 /* libInMemoryExporter in Frameworks */,
Expand Down Expand Up @@ -617,6 +627,7 @@
E12515E4254892C500670D23 /* XCUIApplicationSwizzler.swift */,
E11295BA25F2483D002719E7 /* FileLocator.swift */,
E1A63F5B26789915002F48FA /* CodeOwners.swift */,
E150325B271860BF000CD6C5 /* NTPClock.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -1304,6 +1315,7 @@
E12248DF26455DF700305968 /* libDatadogExporter */,
E12248E126455E0300305968 /* libURLSessionInstrumentation */,
E12248E926455ED800305968 /* libInMemoryExporter */,
E150325F271860E0000CD6C5 /* Kronos */,
);
productName = DatadogSDKTesting;
productReference = E157A74D256E9D1D00CBCA52 /* DatadogSDKTesting.framework */;
Expand All @@ -1330,6 +1342,7 @@
E12248E326455E0B00305968 /* libDatadogExporter */,
E12248E526455E1300305968 /* libURLSessionInstrumentation */,
E12248EB26455EDE00305968 /* libInMemoryExporter */,
E1503261271860E7000CD6C5 /* Kronos */,
);
productName = DatadogSDKTesting;
productReference = E157A785256E9D3300CBCA52 /* DatadogSDKTesting.framework */;
Expand Down Expand Up @@ -1400,6 +1413,7 @@
E12248DB26455DEB00305968 /* libURLSessionInstrumentation */,
E12248DD26455DEB00305968 /* libDatadogExporter */,
E12248E726455ED100305968 /* libInMemoryExporter */,
E1503259271860A8000CD6C5 /* Kronos */,
);
productName = DatadogSDKTesting;
productReference = E1ABA04A25231E2500ED8AEF /* DatadogSDKTesting.framework */;
Expand Down Expand Up @@ -1517,6 +1531,7 @@
E1FB4839253891650083B263 /* XCRemoteSwiftPackageReference "plcrashreporter" */,
E17B7AA6253F02580081D7F3 /* XCRemoteSwiftPackageReference "SigmaSwiftStatistics" */,
E12248DA26455DEB00305968 /* XCRemoteSwiftPackageReference "opentelemetry-swift" */,
E1503258271860A8000CD6C5 /* XCRemoteSwiftPackageReference "Kronos" */,
);
productRefGroup = E1ABA04B25231E2500ED8AEF /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -1745,6 +1760,7 @@
E157A72B256E9D1D00CBCA52 /* FrameworkLoadHandler.swift in Sources */,
E157A72C256E9D1D00CBCA52 /* DDTags.swift in Sources */,
E1665A7425D12D7500BA53CD /* Spawn.swift in Sources */,
E150325D271860BF000CD6C5 /* NTPClock.swift in Sources */,
E157A730256E9D1D00CBCA52 /* SignalUtils.swift in Sources */,
E157A731256E9D1D00CBCA52 /* XCUIApplicationSwizzler.swift in Sources */,
E157A732256E9D1D00CBCA52 /* InternalError.swift in Sources */,
Expand Down Expand Up @@ -1781,6 +1797,7 @@
E157A763256E9D3300CBCA52 /* FrameworkLoadHandler.swift in Sources */,
E157A764256E9D3300CBCA52 /* DDTags.swift in Sources */,
E1665A7525D12D7500BA53CD /* Spawn.swift in Sources */,
E150325E271860BF000CD6C5 /* NTPClock.swift in Sources */,
E157A768256E9D3300CBCA52 /* SignalUtils.swift in Sources */,
E157A769256E9D3300CBCA52 /* XCUIApplicationSwizzler.swift in Sources */,
E157A76A256E9D3300CBCA52 /* InternalError.swift in Sources */,
Expand Down Expand Up @@ -1869,6 +1886,7 @@
E1ABA07625231F4700ED8AEF /* FrameworkLoadHandler.swift in Sources */,
E1ABA07525231F4700ED8AEF /* DDTags.swift in Sources */,
E1665A7325D12D7500BA53CD /* Spawn.swift in Sources */,
E150325C271860BF000CD6C5 /* NTPClock.swift in Sources */,
E13D0BCA2546E29C00C37D56 /* SignalUtils.swift in Sources */,
E12515E5254892C600670D23 /* XCUIApplicationSwizzler.swift in Sources */,
E1AD07A9252F5CB8003705C1 /* InternalError.swift in Sources */,
Expand Down Expand Up @@ -2184,7 +2202,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = "-weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand Down Expand Up @@ -2212,7 +2230,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = "-weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand All @@ -2239,7 +2257,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = "-weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand Down Expand Up @@ -2268,7 +2286,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = "-weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand Down Expand Up @@ -2419,7 +2437,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -2482,7 +2500,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -2512,7 +2530,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = " -weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand All @@ -2539,7 +2557,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 0.9.6-beta.2;
MARKETING_VERSION = "0.9.6-beta.2";
OTHER_LDFLAGS = " -weak-lXCTestSwiftSupport";
PRODUCT_BUNDLE_IDENTIFIER = com.datadoghq.DatadogSDKTesting;
PRODUCT_NAME = DatadogSDKTesting;
Expand Down Expand Up @@ -2805,6 +2823,14 @@
minimumVersion = 1.0.6;
};
};
E1503258271860A8000CD6C5 /* XCRemoteSwiftPackageReference "Kronos" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/MobileNativeFoundation/Kronos";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.0;
};
};
E157A719256E9D1D00CBCA52 /* XCRemoteSwiftPackageReference "plcrashreporter" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/microsoft/plcrashreporter.git";
Expand Down Expand Up @@ -2901,6 +2927,21 @@
package = E12248DA26455DEB00305968 /* XCRemoteSwiftPackageReference "opentelemetry-swift" */;
productName = libInMemoryExporter;
};
E1503259271860A8000CD6C5 /* Kronos */ = {
isa = XCSwiftPackageProductDependency;
package = E1503258271860A8000CD6C5 /* XCRemoteSwiftPackageReference "Kronos" */;
productName = Kronos;
};
E150325F271860E0000CD6C5 /* Kronos */ = {
isa = XCSwiftPackageProductDependency;
package = E1503258271860A8000CD6C5 /* XCRemoteSwiftPackageReference "Kronos" */;
productName = Kronos;
};
E1503261271860E7000CD6C5 /* Kronos */ = {
isa = XCSwiftPackageProductDependency;
package = E1503258271860A8000CD6C5 /* XCRemoteSwiftPackageReference "Kronos" */;
productName = Kronos;
};
E157A718256E9D1D00CBCA52 /* CrashReporter */ = {
isa = XCSwiftPackageProductDependency;
package = E157A719256E9D1D00CBCA52 /* XCRemoteSwiftPackageReference "plcrashreporter" */;
Expand Down
1 change: 1 addition & 0 deletions LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ Component,Origin,License,Copyright
import,opentelemetry-swift,Apache-2.0,Copyright 2020 - OpenTelemetry Authors
import,PLCrashReporter,MIT,Copyright Microsoft Corporation
import,SigmaSwiftStatistics,MIT,Copyright 2015 - Evgenii Neumerzhitckii
import,Kronos,Apache-2.0,Copyright MobileNativeFoundation
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let package = Package(
.package(name: "opentelemetry-swift", url: "https://github.com/open-telemetry/opentelemetry-swift", from: "1.0.5"),
.package(name: "PLCrashReporter", url: "https://github.com/microsoft/plcrashreporter.git", from: "1.9.0"),
.package(name: "SigmaSwiftStatistics", url: "https://github.com/evgenyneu/SigmaSwiftStatistics.git", from: "9.0.2"),
.package(name: "Kronos", url: "https://github.com/MobileNativeFoundation/Kronos", from: "4.0.0"),
],
targets: [
.target(
Expand Down
1 change: 1 addition & 0 deletions Sources/DatadogSDKTesting/DDTracer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ internal class DDTracer {
tracerProvider.updateActiveSampler(Samplers.alwaysOn)
let spanLimits = tracerProvider.getActiveSpanLimits().settingAttributeCountLimit(1024)
tracerProvider.updateActiveSpanLimits(spanLimits)
tracerProvider.updateActiveClock(NTPClock())
Copy link
Member

@ncreated ncreated Oct 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have enough visibility on how otel-swift uses the Clock.now, but one thing we had to mitigate in dd-sdk-ios was Kronos.Clock.now being not monotonic until .sync() resolves all calls to the NTP pool.

In other words, this:

let startTime = Kronos.Clock.now
Thread.sleep(0.1)
let delta =  Kronos.Clock.now - startTime

might give negative delta for the first attempts when NTP sync is being performed and device time is ahead of the NTP time.

When browsing this (start) and this (end) code in otel-swift, I'm not sure if this is not the case here. Is it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otel-swift uses a monotonic clock for each span, which is initialized with the value of the active clock (Kronos clock in this case) that is only called once per span at the start, so durations should never be negative. But those spans can be started from any thread, so I cannot use the Kronos.Clock.now directly, I must evaluate if performance will suffer much from calling it in the main thread since I only call it once per span

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I will start with the simplest implementation, in my framework most of the spans will start at main thread (XCTest observer), and performance should not be so critical

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's definitely the easiest solution 👍, will work if you can make this threading assumption. Otherwise, we solved this (in DataDog/dd-sdk-ios#607) by using our ValuePublisher which uses DispatchQueue. This comes with lock penalty, which we mitigate by using concurrent queue with .barrier for making (rare) writes exclusive and allowing (frequent) simultaneous reads.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I find my solution performance is not good enough I will try to change to your solution, its way better than mine.


let bundle = Bundle.main
let identifier = bundle.bundleIdentifier ?? "com.datadoghq.DatadogSDKTesting"
Expand Down
29 changes: 29 additions & 0 deletions Sources/DatadogSDKTesting/Utils/NTPClock.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 2020-2021 Datadog, Inc.
*/

import Foundation
@_implementationOnly import Kronos
@_implementationOnly import OpenTelemetrySdk

class NTPClock: OpenTelemetrySdk.Clock {
init() {
Kronos.Clock.sync()
}

var now: Date {
if Thread.isMainThread {
return Kronos.Clock.now ?? Date()
} else {
var date = Date()
DispatchQueue.main.sync {
if let now = Kronos.Clock.now {
date = now
}
}
return date
}
}
}