Skip to content

Commit

Permalink
RUMM-2133 Migrate logging v1
Browse files Browse the repository at this point in the history
  • Loading branch information
maxep committed May 17, 2022
1 parent d04fd1f commit 3466a5b
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 221 deletions.
7 changes: 5 additions & 2 deletions Sources/Datadog/CrashReporting/CrashReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ internal class CrashReporter {

// MARK: - Initialization

convenience init?(crashReportingFeature: CrashReportingFeature) {
convenience init?(
crashReportingFeature: CrashReportingFeature,
loggingFeature: LoggingFeature?
) {
let loggingOrRUMIntegration: CrashReportingIntegration?

// If RUM rum is enabled prefer it for sending crash reports, otherwise use Logging feature.
if let rumFeature = RUMFeature.instance {
loggingOrRUMIntegration = CrashReportingWithRUMIntegration(rumFeature: rumFeature)
} else if let loggingFeature = LoggingFeature.instance {
} else if let loggingFeature = loggingFeature {
loggingOrRUMIntegration = CrashReportingWithLoggingIntegration(loggingFeature: loggingFeature)
} else {
loggingOrRUMIntegration = nil
Expand Down
31 changes: 20 additions & 11 deletions Sources/Datadog/Datadog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ public class Datadog {

/// Clears all data that has not already been sent to Datadog servers.
public static func clearAllData() {
LoggingFeature.instance?.storage.clearAllData()
let logging = defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName)
logging?.storage.clearAllData()
TracingFeature.instance?.storage.clearAllData()
RUMFeature.instance?.storage.clearAllData()
}
Expand All @@ -171,12 +172,20 @@ public class Datadog {
}

let consentProvider = ConsentProvider(initialConsent: initialTrackingConsent)
let userInfoProvider = UserInfoProvider()

// set default DatadogCore then register features
defaultDatadogCore = DatadogCore(
consentProvider: consentProvider,
userInfoProvider: userInfoProvider
)

let dateProvider = SystemDateProvider()
let dateCorrector = DateCorrector(
deviceDateProvider: dateProvider,
serverDateProvider: NTPServerDateProvider()
)
let userInfoProvider = UserInfoProvider()

let networkConnectionInfoProvider = NetworkConnectionInfoProvider()
let carrierInfoProvider = CarrierInfoProvider()
let launchTimeProvider = LaunchTimeProvider()
Expand Down Expand Up @@ -250,6 +259,8 @@ public class Datadog {
commonDependencies: commonDependencies,
telemetry: telemetry
)

defaultDatadogCore.registerFeature(named: LoggingFeature.featureName, instance: logging)
}

if let tracingConfiguration = configuration.tracing {
Expand Down Expand Up @@ -278,7 +289,6 @@ public class Datadog {
)
}

LoggingFeature.instance = logging
TracingFeature.instance = tracing
RUMFeature.instance = rum
CrashReportingFeature.instance = crashReporting
Expand All @@ -289,16 +299,13 @@ public class Datadog {
URLSessionAutoInstrumentation.instance = urlSessionAutoInstrumentation
URLSessionAutoInstrumentation.instance?.enable()

// Only after all features were initialized with no error thrown:
defaultDatadogCore = DatadogCore(
consentProvider: consentProvider,
userInfoProvider: userInfoProvider
)

// After everything is set up, if the Crash Reporting feature was enabled,
// register crash reporter and send crash report if available:
if let crashReportingFeature = CrashReportingFeature.instance {
Global.crashReporter = CrashReporter(crashReportingFeature: crashReportingFeature)
Global.crashReporter = CrashReporter(
crashReportingFeature: crashReportingFeature,
loggingFeature: logging
)
Global.crashReporter?.sendCrashReportIfFound()
}
}
Expand All @@ -321,7 +328,9 @@ public class Datadog {
assert(Datadog.isInitialized, "SDK must be first initialized.")

// Tear down and deinitialize all features:
LoggingFeature.instance?.deinitialize()
let logging = defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName)
logging?.deinitialize()

TracingFeature.instance?.deinitialize()
RUMFeature.instance?.deinitialize()
CrashReportingFeature.instance?.deinitialize()
Expand Down
30 changes: 30 additions & 0 deletions Sources/Datadog/DatadogCore/DatadogCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,36 @@ internal final class DatadogCore {
self.consentProvider = consentProvider
self.userInfoProvider = userInfoProvider
}

/// Sets current user information.
///
/// Those will be added to logs, traces and RUM events automatically.
///
/// - Parameters:
/// - id: User ID, if any
/// - name: Name representing the user, if any
/// - email: User's email, if any
/// - extraInfo: User's custom attributes, if any
func setUserInfo(
id: String? = nil,
name: String? = nil,
email: String? = nil,
extraInfo: [AttributeKey: AttributeValue] = [:]
) {
userInfoProvider.value = UserInfo(
id: id,
name: name,
email: email,
extraInfo: extraInfo
)
}

/// Sets the tracking consent regarding the data collection for the Datadog SDK.
///
/// - Parameter trackingConsent: new consent value, which will be applied for all data collected from now on
func set(trackingConsent: TrackingConsent) {
consentProvider.changeConsent(to: trackingConsent)
}
}

extension DatadogCore: DatadogCoreProtocol {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ public extension WKUserContentController {
/// with the RUM session from native SDK.
///
/// - Parameter hosts: a list of hosts instrumented with Browser SDK to capture Datadog events from
func trackDatadogEvents(in hosts: Set<String>) {
addDatadogMessageHandler(allowedWebViewHosts: hosts, hostsSanitizer: HostsSanitizer())
func trackDatadogEvents(in hosts: Set<String>, sdk core: DatadogCoreProtocol = defaultDatadogCore) {
addDatadogMessageHandler(
allowedWebViewHosts: hosts,
hostsSanitizer: HostsSanitizer(),
loggingFeature: core.feature(named: LoggingFeature.featureName)
)
}

/// Disables Datadog iOS SDK and Datadog Browser SDK integration.
Expand All @@ -44,7 +48,11 @@ public extension WKUserContentController {
}
}

internal func addDatadogMessageHandler(allowedWebViewHosts: Set<String>, hostsSanitizer: HostsSanitizing) {
internal func addDatadogMessageHandler(
allowedWebViewHosts: Set<String>,
hostsSanitizer: HostsSanitizing,
loggingFeature: LoggingFeature?
) {
guard !isTracking else {
userLogger.warn("`trackDatadogEvents(in:)` was called more than once for the same WebView. Second call will be ignored. Make sure you call it only once.")
return
Expand All @@ -55,7 +63,7 @@ public extension WKUserContentController {
let globalRUMMonitor = Global.rum as? RUMMonitor

var logEventConsumer: DefaultWebLogEventConsumer? = nil
if let loggingFeature = LoggingFeature.instance {
if let loggingFeature = loggingFeature {
logEventConsumer = DefaultWebLogEventConsumer(
userLogsWriter: loggingFeature.storage.writer,
dateCorrector: loggingFeature.dateCorrector,
Expand Down
8 changes: 4 additions & 4 deletions Sources/Datadog/Logger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ public class Logger {
}

/// Builds `Logger` object.
public func build() -> Logger {
public func build(in core: DatadogCoreProtocol = defaultDatadogCore) -> Logger {
do {
return try buildOrThrow()
return try buildOrThrow(in: core)
} catch {
consolePrint("\(error)")
return Logger(
Expand All @@ -398,8 +398,8 @@ public class Logger {
}
}

private func buildOrThrow() throws -> Logger {
guard let loggingFeature = LoggingFeature.instance else {
private func buildOrThrow(in core: DatadogCoreProtocol) throws -> Logger {
guard let loggingFeature = core.feature(LoggingFeature.self, named: LoggingFeature.featureName) else {
throw ProgrammerError(
description: Datadog.isInitialized
? "`Logger.builder.build()` produces a non-functional logger, as the logging feature is disabled."
Expand Down
7 changes: 0 additions & 7 deletions Sources/Datadog/Logging/LoggingFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ internal func obtainLoggingFeatureDirectories() throws -> FeatureDirectories {
/// Creates and owns componetns enabling logging feature.
/// Bundles dependencies for other logging-related components created later at runtime (i.e. `Logger`).
internal final class LoggingFeature {
/// Single, shared instance of `LoggingFeature`.
internal static var instance: LoggingFeature?

/// Tells if the feature was enabled by the user in the SDK configuration.
static var isEnabled: Bool { instance != nil }

// MARK: - Configuration

let configuration: FeaturesConfiguration.Logging
Expand Down Expand Up @@ -152,6 +146,5 @@ internal final class LoggingFeature {
internal func deinitialize() {
storage.flushAndTearDown()
upload.flushAndTearDown()
LoggingFeature.instance = nil
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,11 @@ class CrashReporterTests: XCTestCase {
plugin.pendingCrashReport = .mockAny()

// When
XCTAssertNil(LoggingFeature.instance)
XCTAssertNil(RUMFeature.instance)
let crashReporter = CrashReporter(crashReportingFeature: .mockNoOp())
let crashReporter = CrashReporter(
crashReportingFeature: .mockNoOp(),
loggingFeature: nil
)

// Then
XCTAssertNil(crashReporter)
Expand Down
28 changes: 17 additions & 11 deletions Tests/DatadogTests/Datadog/DatadogTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class DatadogTests: XCTestCase {

verify(configuration: defaultBuilder.build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertFalse(RUMFeature.isEnabled, "When using `defaultBuilder` RUM feature should be disabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -125,7 +125,7 @@ class DatadogTests: XCTestCase {
}
verify(configuration: rumBuilder.build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertTrue(RUMFeature.isEnabled, "When using `rumBuilder` RUM feature should be enabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -137,7 +137,7 @@ class DatadogTests: XCTestCase {

verify(configuration: defaultBuilder.enableLogging(false).build()) {
// verify features:
XCTAssertFalse(LoggingFeature.isEnabled)
XCTAssertNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertFalse(RUMFeature.isEnabled, "When using `defaultBuilder` RUM feature should be disabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -148,7 +148,7 @@ class DatadogTests: XCTestCase {
}
verify(configuration: rumBuilder.enableLogging(false).build()) {
// verify features:
XCTAssertFalse(LoggingFeature.isEnabled)
XCTAssertNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertTrue(RUMFeature.isEnabled, "When using `rumBuilder` RUM feature should be enabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -160,7 +160,7 @@ class DatadogTests: XCTestCase {

verify(configuration: defaultBuilder.enableTracing(false).build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertFalse(TracingFeature.isEnabled)
XCTAssertFalse(RUMFeature.isEnabled, "When using `defaultBuilder` RUM feature should be disabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -169,7 +169,7 @@ class DatadogTests: XCTestCase {
}
verify(configuration: rumBuilder.enableTracing(false).build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertFalse(TracingFeature.isEnabled)
XCTAssertTrue(RUMFeature.isEnabled, "When using `rumBuilder` RUM feature should be enabled by default")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -179,7 +179,7 @@ class DatadogTests: XCTestCase {

verify(configuration: defaultBuilder.enableRUM(true).build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertFalse(RUMFeature.isEnabled, "When using `defaultBuilder` RUM feature cannot be enabled")
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand All @@ -190,7 +190,7 @@ class DatadogTests: XCTestCase {
}
verify(configuration: rumBuilder.enableRUM(false).build()) {
// verify features:
XCTAssertTrue(LoggingFeature.isEnabled)
XCTAssertNotNil(defaultDatadogCore.feature(LoggingFeature.self, named: LoggingFeature.featureName))
XCTAssertTrue(TracingFeature.isEnabled)
XCTAssertFalse(RUMFeature.isEnabled)
XCTAssertFalse(CrashReportingFeature.isEnabled)
Expand Down Expand Up @@ -314,9 +314,12 @@ class DatadogTests: XCTestCase {
uploadFrequency: .frequent,
bundleType: .iOSApp
)

let core = defaultDatadogCore
let logging = core.feature(LoggingFeature.self, named: LoggingFeature.featureName)
XCTAssertEqual(logging?.configuration.common.performance, expectedPerformancePreset)
XCTAssertEqual(RUMFeature.instance?.configuration.sessionSampler.samplingRate, 100)
XCTAssertEqual(TracingFeature.instance?.configuration.common.performance, expectedPerformancePreset)
XCTAssertEqual(LoggingFeature.instance?.configuration.common.performance, expectedPerformancePreset)
XCTAssertEqual(Datadog.verbosityLevel, .debug)

// Clear default verbosity after this test
Expand Down Expand Up @@ -435,10 +438,13 @@ class DatadogTests: XCTestCase {
.build()
)

let core = defaultDatadogCore
let logging = core.feature(LoggingFeature.self, named: LoggingFeature.featureName)

// On SDK init, underlying `ConsentAwareDataWriter` performs data migration for each feature, which includes
// data removal in `unauthorised` (`.pending`) directory. To not cause test flakiness, we must ensure that
// mock data is written only after this operation completes - otherwise, migration may delete mocked files.
let loggingWriter = try XCTUnwrap(LoggingFeature.instance?.storage.writer as? ConsentAwareDataWriter)
let loggingWriter = try XCTUnwrap(logging?.storage.writer as? ConsentAwareDataWriter)
let tracingWriter = try XCTUnwrap(TracingFeature.instance?.storage.writer as? ConsentAwareDataWriter)
let rumWriter = try XCTUnwrap(RUMFeature.instance?.storage.writer as? ConsentAwareDataWriter)
loggingWriter.queue.sync {}
Expand All @@ -462,7 +468,7 @@ class DatadogTests: XCTestCase {
Datadog.clearAllData()

// Wait for async clear completion in all features:
(LoggingFeature.instance?.storage.dataOrchestrator as? DataOrchestrator)?.queue.sync {}
(logging?.storage.dataOrchestrator as? DataOrchestrator)?.queue.sync {}
(TracingFeature.instance?.storage.dataOrchestrator as? DataOrchestrator)?.queue.sync {}
(RUMFeature.instance?.storage.dataOrchestrator as? DataOrchestrator)?.queue.sync {}

Expand Down
Loading

0 comments on commit 3466a5b

Please sign in to comment.