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

[Issue #125] Enable DatadogCore and DatadogLogs to compile on watchOS platform #1918

13 changes: 13 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,16 @@ Smoke Tests (macOS):
- ./tools/runner-setup.sh --xcode "$XCODE" # temporary, waiting for AMI
- make clean repo-setup ENV=ci
- make spm-build-macos

Smoke Tests (watchOS):
stage: smoke-test
tags:
- macos:ventura
- specific:true
variables:
XCODE: "15.2.0"
OS: "10.2"
script:
- ./tools/runner-setup.sh --xcode "$XCODE" --watchOS --os "$OS" # temporary, waiting for AMI
- make clean repo-setup ENV=ci
- make spm-build-watchos
18 changes: 18 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1680,6 +1680,12 @@
E1C853142AA9B9A300C74BCF /* TelemetryMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C853132AA9B9A300C74BCF /* TelemetryMocks.swift */; };
E1C853152AA9B9A300C74BCF /* TelemetryMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C853132AA9B9A300C74BCF /* TelemetryMocks.swift */; };
E1D5AEA724B4D45B007F194B /* Versioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D5AEA624B4D45A007F194B /* Versioning.swift */; };
E2AA55E42C32C6AF002FEF28 /* DeviceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E32C32C6AF002FEF28 /* DeviceProtocol.swift */; };
E2AA55E52C32C6AF002FEF28 /* DeviceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E32C32C6AF002FEF28 /* DeviceProtocol.swift */; };
E2AA55E72C32C6D9002FEF28 /* ApplicationNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E62C32C6D9002FEF28 /* ApplicationNotifications.swift */; };
E2AA55E82C32C6D9002FEF28 /* ApplicationNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E62C32C6D9002FEF28 /* ApplicationNotifications.swift */; };
E2AA55EA2C32C76A002FEF28 /* WatchKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E92C32C76A002FEF28 /* WatchKitExtensions.swift */; };
E2AA55EC2C32C78B002FEF28 /* WatchKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AA55E92C32C76A002FEF28 /* WatchKitExtensions.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -3026,6 +3032,9 @@
E1D202E924C065CF00D1AF3A /* ActiveSpansPool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveSpansPool.swift; sourceTree = "<group>"; };
E1D203FB24C1884500D1AF3A /* ActiveSpansPoolTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveSpansPoolTests.swift; sourceTree = "<group>"; };
E1D5AEA624B4D45A007F194B /* Versioning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Versioning.swift; sourceTree = "<group>"; };
E2AA55E32C32C6AF002FEF28 /* DeviceProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceProtocol.swift; sourceTree = "<group>"; };
E2AA55E62C32C6D9002FEF28 /* ApplicationNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationNotifications.swift; sourceTree = "<group>"; };
E2AA55E92C32C76A002FEF28 /* WatchKitExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WatchKitExtensions.swift; sourceTree = "<group>"; };
F637AED12697404200516F32 /* UIKitRUMUserActionsPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitRUMUserActionsPredicate.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -5813,6 +5822,7 @@
D23039B2298D5235001A1FA3 /* Context */ = {
isa = PBXGroup;
children = (
E2AA55E62C32C6D9002FEF28 /* ApplicationNotifications.swift */,
D23039B3298D5235001A1FA3 /* AppState.swift */,
D23039B4298D5235001A1FA3 /* UserInfo.swift */,
D23039B5298D5235001A1FA3 /* BatteryStatus.swift */,
Expand All @@ -5823,6 +5833,7 @@
D23039BA298D5235001A1FA3 /* DatadogContext.swift */,
D23039BB298D5235001A1FA3 /* TrackingConsent.swift */,
D23039BC298D5235001A1FA3 /* DeviceInfo.swift */,
E2AA55E32C32C6AF002FEF28 /* DeviceProtocol.swift */,
D23039BE298D5235001A1FA3 /* LaunchTime.swift */,
D2F8235229915E12003C7E99 /* DatadogSite.swift */,
6174D6122BFDF16C00EC7469 /* BundleType.swift */,
Expand Down Expand Up @@ -6256,6 +6267,7 @@
D23039D9298D5235001A1FA3 /* DateFormatting.swift */,
613C6B8F2768FDDE00870CBF /* Sampler.swift */,
D23039DC298D5235001A1FA3 /* DDError.swift */,
E2AA55E92C32C76A002FEF28 /* WatchKitExtensions.swift */,
61133BBA2423979B00786299 /* SwiftExtensions.swift */,
D29A9F9429DDB1DB005C54A4 /* UIKitExtensions.swift */,
);
Expand Down Expand Up @@ -8576,6 +8588,7 @@
D23039F9298D5236001A1FA3 /* CoreLogger.swift in Sources */,
D2160CA229C0DE5700FAA9A5 /* NetworkInstrumentationFeature.swift in Sources */,
D2EBEE1F29BA160F00B15732 /* HTTPHeadersReader.swift in Sources */,
E2AA55E72C32C6D9002FEF28 /* ApplicationNotifications.swift in Sources */,
D263BCAF29DAFFEB00FA0E21 /* PerformancePresetOverride.swift in Sources */,
D23039E7298D5236001A1FA3 /* NetworkConnectionInfo.swift in Sources */,
D23039E9298D5236001A1FA3 /* TrackingConsent.swift in Sources */,
Expand All @@ -8589,6 +8602,7 @@
D2160CC929C0DED100FAA9A5 /* DatadogURLSessionDelegate.swift in Sources */,
D2EBEE2929BA160F00B15732 /* HTTPHeadersWriter.swift in Sources */,
D2432CF929EDB22C00D93657 /* Flushable.swift in Sources */,
E2AA55E42C32C6AF002FEF28 /* DeviceProtocol.swift in Sources */,
D23039F7298D5236001A1FA3 /* AttributesSanitizer.swift in Sources */,
D23039EB298D5236001A1FA3 /* DatadogFeature.swift in Sources */,
D2BEEDBA2B33638F0065F3AC /* NetworkInstrumentationSwizzler.swift in Sources */,
Expand Down Expand Up @@ -8621,6 +8635,7 @@
D2160CF429C0EDFC00FAA9A5 /* UploadPerformancePreset.swift in Sources */,
D23039E1298D5236001A1FA3 /* AppState.swift in Sources */,
D2DE63532A30A7CA00441A54 /* CoreRegistry.swift in Sources */,
E2AA55EA2C32C76A002FEF28 /* WatchKitExtensions.swift in Sources */,
D2EBEE2829BA160F00B15732 /* W3CHTTPHeadersWriter.swift in Sources */,
D23039EA298D5236001A1FA3 /* DeviceInfo.swift in Sources */,
D2EBEE2329BA160F00B15732 /* B3HTTPHeadersReader.swift in Sources */,
Expand Down Expand Up @@ -9543,6 +9558,7 @@
D2DA2358298D57AA00C6C7E6 /* CoreLogger.swift in Sources */,
D2160CA329C0DE5700FAA9A5 /* NetworkInstrumentationFeature.swift in Sources */,
D2EBEE2D29BA161100B15732 /* HTTPHeadersReader.swift in Sources */,
E2AA55E82C32C6D9002FEF28 /* ApplicationNotifications.swift in Sources */,
D263BCB029DAFFEB00FA0E21 /* PerformancePresetOverride.swift in Sources */,
D2DA2359298D57AA00C6C7E6 /* NetworkConnectionInfo.swift in Sources */,
D2DA235A298D57AA00C6C7E6 /* TrackingConsent.swift in Sources */,
Expand All @@ -9556,6 +9572,7 @@
D2160CCA29C0DED100FAA9A5 /* DatadogURLSessionDelegate.swift in Sources */,
D2EBEE3729BA161100B15732 /* HTTPHeadersWriter.swift in Sources */,
D2432CFA29EDB22C00D93657 /* Flushable.swift in Sources */,
E2AA55E52C32C6AF002FEF28 /* DeviceProtocol.swift in Sources */,
D2DA235D298D57AA00C6C7E6 /* AttributesSanitizer.swift in Sources */,
D2DA235E298D57AA00C6C7E6 /* DatadogFeature.swift in Sources */,
D2BEEDBB2B3363900065F3AC /* NetworkInstrumentationSwizzler.swift in Sources */,
Expand Down Expand Up @@ -9588,6 +9605,7 @@
D2160CF529C0EDFC00FAA9A5 /* UploadPerformancePreset.swift in Sources */,
D2DA236C298D57AA00C6C7E6 /* AppState.swift in Sources */,
D2DE63542A30A7CA00441A54 /* CoreRegistry.swift in Sources */,
E2AA55EC2C32C78B002FEF28 /* WatchKitExtensions.swift in Sources */,
D2EBEE3629BA161100B15732 /* W3CHTTPHeadersWriter.swift in Sources */,
D2DA236D298D57AA00C6C7E6 /* DeviceInfo.swift in Sources */,
D2EBEE3129BA161100B15732 /* B3HTTPHeadersReader.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions DatadogCore.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Pod::Spec.new do |s|
s.swift_version = '5.9'
s.ios.deployment_target = '12.0'
s.tvos.deployment_target = '12.0'
s.watchos.deployment_target = '7.0'

s.source = { :git => "https://github.com/DataDog/dd-sdk-ios.git", :tag => s.version.to_s }

Expand Down
27 changes: 17 additions & 10 deletions DatadogCore/Sources/Core/Context/ApplicationStatePublisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
#if canImport(UIKit)
import UIKit
import DatadogInternal
#if canImport(WatchKit)
import WatchKit
#endif

internal final class ApplicationStatePublisher: ContextValuePublisher {
typealias Snapshot = AppStateHistory.Snapshot

private static var currentApplicationState: UIApplication.State {
private static var currentApplicationState: ApplicationState {
#if canImport(WatchKit)
WKExtension.dd.shared.applicationState
#else
UIApplication.dd.managedShared?.applicationState ?? .active // fallback to most expected state
#endif
}

/// The default publisher queue.
Expand Down Expand Up @@ -85,7 +92,7 @@ internal final class ApplicationStatePublisher: ContextValuePublisher {
/// - dateProvider: The date provider for the Application state snapshot timestamp.
/// - notificationCenter: The notification center where this publisher observes `UIApplication` notifications.
convenience init(
applicationState: UIApplication.State = ApplicationStatePublisher.currentApplicationState,
applicationState: ApplicationState = ApplicationStatePublisher.currentApplicationState,
queue: DispatchQueue = ApplicationStatePublisher.defaultQueue,
dateProvider: DateProvider = SystemDateProvider(),
notificationCenter: NotificationCenter = .default
Expand All @@ -100,10 +107,10 @@ internal final class ApplicationStatePublisher: ContextValuePublisher {

func publish(to receiver: @escaping ContextValueReceiver<AppStateHistory>) {
queue.async { self.receiver = receiver }
notificationCenter.addObserver(self, selector: #selector(applicationDidBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationWillResignActive), name: UIApplication.willResignActiveNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationDidBecomeActive), name: ApplicationNotifications.didBecomeActive, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationWillResignActive), name: ApplicationNotifications.willResignActive, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationDidEnterBackground), name: ApplicationNotifications.didEnterBackground, object: nil)
notificationCenter.addObserver(self, selector: #selector(applicationWillEnterForeground), name: ApplicationNotifications.willEnterForeground, object: nil)
}

@objc
Expand Down Expand Up @@ -135,10 +142,10 @@ internal final class ApplicationStatePublisher: ContextValuePublisher {
}

func cancel() {
notificationCenter.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
notificationCenter.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
notificationCenter.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil)
notificationCenter.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil)
notificationCenter.removeObserver(self, name: ApplicationNotifications.didBecomeActive, object: nil)
notificationCenter.removeObserver(self, name: ApplicationNotifications.willResignActive, object: nil)
notificationCenter.removeObserver(self, name: ApplicationNotifications.didEnterBackground, object: nil)
notificationCenter.removeObserver(self, name: ApplicationNotifications.willEnterForeground, object: nil)
queue.async { self.receiver = nil }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal protocol BackgroundTaskCoordinator {
import UIKit
import DatadogInternal

#if !os(watchOS)
/// Bridge protocol that calls corresponding `UIApplication` interface for background tasks. Allows easier testablity.
internal protocol UIKitAppBackgroundTaskCoordinator {
func beginBgTask(_ handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
Expand Down Expand Up @@ -69,6 +70,7 @@ internal class AppBackgroundTaskCoordinator: BackgroundTaskCoordinator {
self.currentTaskId = nil
}
}
#endif

/// Bridge protocol that matches `ProcessInfo` interface for background activity. Allows easier testablity.
internal protocol ProcessInfoActivityCoordinator {
Expand Down
4 changes: 4 additions & 0 deletions DatadogCore/Sources/Core/Upload/FeatureUpload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ internal struct FeatureUpload {
let backgroundTaskCoordinator: BackgroundTaskCoordinator?
switch (backgroundTasksEnabled, isRunFromExtension) {
case (true, false):
#if os(watchOS)
backgroundTaskCoordinator = ExtensionBackgroundTaskCoordinator()
#else
backgroundTaskCoordinator = AppBackgroundTaskCoordinator()
#endif
case (true, true):
backgroundTaskCoordinator = ExtensionBackgroundTaskCoordinator()
case (false, _):
Expand Down
2 changes: 2 additions & 0 deletions DatadogCore/Sources/Core/Upload/URLSessionClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ internal class URLSessionClient: HTTPClient {
configuration.urlCache = nil
configuration.connectionProxyDictionary = proxyConfiguration

#if !os(watchOS)
// URLSession does not set the `Proxy-Authorization` header automatically when using a proxy
// configuration. We manually set the HTTP basic authentication header.
if let user = proxyConfiguration?[kCFProxyUsernameKey] as? String,
let password = proxyConfiguration?[kCFProxyPasswordKey] as? String {
let authorization = basicHTTPAuthentication(username: user, password: password)
configuration.httpAdditionalHeaders = ["Proxy-Authorization": authorization]
}
#endif

self.init(session: URLSession(configuration: configuration))
}
Expand Down
6 changes: 6 additions & 0 deletions DatadogCore/Sources/Kronos/KronosDNSResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ internal final class KronosDNSResolver {
timeout: TimeInterval = kDefaultTimeout,
completion: @escaping ([KronosInternetAddress]) -> Void
) {
#if os(watchOS)
completion([])
#else
let callback: CFHostClientCallBack = { host, _, _, info in
guard let info = info else {
return
Expand Down Expand Up @@ -79,8 +82,10 @@ internal final class KronosDNSResolver {
CFHostSetClient(hostReference, callback, &clientContext)
CFHostScheduleWithRunLoop(hostReference, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
CFHostStartInfoResolution(hostReference, .addresses, nil)
#endif
}

#if !os(watchOS)
@objc
private func onTimeout() {
defer {
Expand All @@ -99,4 +104,5 @@ internal final class KronosDNSResolver {
CFHostUnscheduleFromRunLoop(hostReference, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
CFHostSetClient(hostReference, nil, nil)
}
#endif
}
1 change: 1 addition & 0 deletions DatadogInternal.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Pod::Spec.new do |s|
s.swift_version = '5.9'
s.ios.deployment_target = '12.0'
s.tvos.deployment_target = '12.0'
s.watchos.deployment_target = '7.0'

s.source = { :git => "https://github.com/DataDog/dd-sdk-ios.git", :tag => s.version.to_s }

Expand Down
10 changes: 9 additions & 1 deletion DatadogInternal/Sources/Context/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,16 @@ extension AppStateHistory {

import UIKit

#if canImport(WatchKit)
import WatchKit

public typealias ApplicationState = WKApplicationState
#else
public typealias ApplicationState = UIApplication.State
#endif

extension AppState {
public init(_ state: UIApplication.State) {
public init(_ state: ApplicationState) {
switch state {
case .active:
self = .active
Expand Down
49 changes: 49 additions & 0 deletions DatadogInternal/Sources/Context/ApplicationNotifications.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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

#if canImport(UIKit)
import UIKit
#if canImport(WatchKit)
import WatchKit
#endif

/// Convenient wrapper to get system notifications independent from platform
public enum ApplicationNotifications {
public static var didBecomeActive: Notification.Name {
#if canImport(WatchKit)
WKExtension.applicationDidBecomeActiveNotification
#else
UIApplication.didBecomeActiveNotification
#endif
}

public static var willResignActive: Notification.Name {
#if canImport(WatchKit)
WKExtension.applicationWillResignActiveNotification
#else
UIApplication.willResignActiveNotification
#endif
}

public static var didEnterBackground: Notification.Name {
#if canImport(WatchKit)
WKExtension.applicationDidEnterBackgroundNotification
#else
UIApplication.didEnterBackgroundNotification
#endif
}

public static var willEnterForeground: Notification.Name {
#if canImport(WatchKit)
WKExtension.applicationWillEnterForegroundNotification
#else
UIApplication.willEnterForegroundNotification
#endif
}
}
#endif
10 changes: 5 additions & 5 deletions DatadogInternal/Sources/Context/DeviceInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ import MachO
import UIKit

extension DeviceInfo {
/// Creates device info based on UIKit description.
/// Creates device info based on device description.
///
/// - Parameters:
/// - processInfo: The current process information.
/// - device: The `UIDevice` description.
/// - device: The `DeviceProtocol` description.
public init(
processInfo: ProcessInfo = .processInfo,
device: UIDevice = .current,
device: DeviceProtocol = DeviceFactory.current,
sysctl: SysctlProviding = Sysctl()
) {
var architecture = "unknown"
Expand All @@ -96,7 +96,7 @@ extension DeviceInfo {

#if !targetEnvironment(simulator)
let model = try? sysctl.model()
// Real iOS device
// Real device
self.init(
name: device.model,
model: model ?? device.model,
Expand All @@ -111,7 +111,7 @@ extension DeviceInfo {
)
#else
let model = processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] ?? device.model
// iOS Simulator - battery monitoring doesn't work on Simulator, so return "always OK" value
// Simulator - battery monitoring doesn't work on Simulator, so return "always OK" value
self.init(
name: device.model,
model: "\(model) Simulator",
Expand Down
Loading