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

RUM-6395: Add internal logging/telemetry APIs to ObjC #2073

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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- [IMPROVEMENT] Add ObjC API for the internal logging/telemetry. See [#2073][]

# 2.18.0 / 25-09-2024
- [IMPROVEMENT] Add overwrite required (breaking) param to addViewLoadingTime & usage telemetry. See [#2040][]
- [FEATURE] Prevent "show password" features from revealing sensitive texts in Session Replay. See [#2050][]
Expand Down Expand Up @@ -774,6 +776,7 @@ Release `2.0` introduces breaking changes. Follow the [Migration Guide](MIGRATIO
[#2043]: https://github.com/DataDog/dd-sdk-ios/pull/2043
[#2040]: https://github.com/DataDog/dd-sdk-ios/pull/2040
[#2050]: https://github.com/DataDog/dd-sdk-ios/pull/2050
[#2073]: https://github.com/DataDog/dd-sdk-ios/pull/2073
[@00fa9a]: https://github.com/00FA9A
[@britton-earnin]: https://github.com/Britton-Earnin
[@hengyu]: https://github.com/Hengyu
Expand Down
18 changes: 18 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,12 @@
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 */; };
F603F1262CAE9F760088E6B7 /* DDInternalLogger+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = F603F1252CAE9F760088E6B7 /* DDInternalLogger+objc.swift */; };
F603F1272CAE9F760088E6B7 /* DDInternalLogger+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = F603F1252CAE9F760088E6B7 /* DDInternalLogger+objc.swift */; };
F603F12B2CAEA4FA0088E6B7 /* DDInternalLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F603F1282CAEA4E90088E6B7 /* DDInternalLoggerTests.swift */; };
F603F12C2CAEA7180088E6B7 /* DDInternalLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F603F1282CAEA4E90088E6B7 /* DDInternalLoggerTests.swift */; };
F603F1302CAEA7620088E6B7 /* DDInternalLogger+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F603F12D2CAEA7590088E6B7 /* DDInternalLogger+apiTests.m */; };
F603F1312CAEA7630088E6B7 /* DDInternalLogger+apiTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F603F12D2CAEA7590088E6B7 /* DDInternalLogger+apiTests.m */; };
F6E106542C75E0D000716DC6 /* LogsDataModels+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E106532C75E0D000716DC6 /* LogsDataModels+objc.swift */; };
F6E106552C75E0D000716DC6 /* LogsDataModels+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E106532C75E0D000716DC6 /* LogsDataModels+objc.swift */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -3067,6 +3073,9 @@
E1D5AEA624B4D45A007F194B /* Versioning.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Versioning.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>"; };
F603F1252CAE9F760088E6B7 /* DDInternalLogger+objc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DDInternalLogger+objc.swift"; sourceTree = "<group>"; };
F603F1282CAEA4E90088E6B7 /* DDInternalLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDInternalLoggerTests.swift; sourceTree = "<group>"; };
F603F12D2CAEA7590088E6B7 /* DDInternalLogger+apiTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "DDInternalLogger+apiTests.m"; sourceTree = "<group>"; };
F637AED12697404200516F32 /* UIKitRUMUserActionsPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitRUMUserActionsPredicate.swift; sourceTree = "<group>"; };
F6E106532C75E0D000716DC6 /* LogsDataModels+objc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LogsDataModels+objc.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -4281,6 +4290,7 @@
6111C58025C0080C00F5C4A2 /* RUM */,
6132BF4024A38D0600D7BD17 /* OpenTracing */,
D2A434A72A8E3FFB0028E329 /* SessionReplay */,
F603F1252CAE9F760088E6B7 /* DDInternalLogger+objc.swift */,
);
name = DatadogObjc;
path = ../DatadogObjc/Sources;
Expand Down Expand Up @@ -4319,6 +4329,7 @@
3CCCA5C62ABAF5230029D7BD /* DDURLSessionInstrumentationConfigurationTests.swift */,
D2A434AD2A8E426C0028E329 /* DDSessionReplayTests.swift */,
61D03BDE273404BB00367DE0 /* RUM */,
F603F1282CAEA4E90088E6B7 /* DDInternalLoggerTests.swift */,
);
path = DatadogObjc;
sourceTree = "<group>";
Expand Down Expand Up @@ -5240,6 +5251,7 @@
3C1890132ABDE99200CE9E73 /* DDURLSessionInstrumentationTests+apiTests.m */,
A795069D2B974CAA00AC4814 /* DDSessionReplay+apiTests.m */,
6174D6052BFB9D5500EC7469 /* DDWebViewTracking+apiTests.m */,
F603F12D2CAEA7590088E6B7 /* DDInternalLogger+apiTests.m */,
);
path = ObjcAPITests;
sourceTree = "<group>";
Expand Down Expand Up @@ -8189,6 +8201,7 @@
61133C572423990D00786299 /* FileReaderTests.swift in Sources */,
D2A1EE38287EEB7400D28DFB /* NetworkConnectionInfoPublisherTests.swift in Sources */,
D24C9C7129A7D57A002057CF /* DirectoriesMock.swift in Sources */,
F603F1302CAEA7620088E6B7 /* DDInternalLogger+apiTests.m in Sources */,
D22743E329DEB90B001A7EF9 /* RUMDebuggingTests.swift in Sources */,
614798992A459B2E0095CB02 /* DDTraceConfigurationTests.swift in Sources */,
61DCC84A2C05D4D600CB59E5 /* RUMSessionEndedMetricIntegrationTests.swift in Sources */,
Expand Down Expand Up @@ -8282,6 +8295,7 @@
D2553807288AA84F00727FAD /* UploadMock.swift in Sources */,
D28F836C29C9E7A300EF8EA2 /* TracingURLSessionHandlerTests.swift in Sources */,
D22743E629DEB953001A7EF9 /* UIApplicationSwizzlerTests.swift in Sources */,
F603F12B2CAEA4FA0088E6B7 /* DDInternalLoggerTests.swift in Sources */,
D20FD9D62ACC0934004D3569 /* WebLogIntegrationTests.swift in Sources */,
D21C26D128A64599005DD405 /* MessageBusTests.swift in Sources */,
);
Expand All @@ -8298,6 +8312,7 @@
A728ADAB2934EA2100397996 /* W3CHTTPHeadersWriter+objc.swift in Sources */,
A79B0F66292BD7CA008742B3 /* B3HTTPHeadersWriter+objc.swift in Sources */,
3CCCA5C42ABAF0F80029D7BD /* DDURLSessionInstrumentation+objc.swift in Sources */,
F603F1262CAE9F760088E6B7 /* DDInternalLogger+objc.swift in Sources */,
61133C0E2423983800786299 /* Datadog+objc.swift in Sources */,
3CA852642BF2148200B52CBA /* TraceContextInjection+objc.swift in Sources */,
61133C102423983800786299 /* Logs+objc.swift in Sources */,
Expand Down Expand Up @@ -9492,6 +9507,8 @@
6136CB4B2A69C29C00AC265D /* FilesOrchestrator+MetricsTests.swift in Sources */,
D25085112976E30000E931C3 /* DatadogRemoteFeatureMock.swift in Sources */,
A7CA21842BEBB2E200732571 /* ExtensionBackgroundTaskCoordinatorTests.swift in Sources */,
F603F1312CAEA7630088E6B7 /* DDInternalLogger+apiTests.m in Sources */,
F603F12C2CAEA7180088E6B7 /* DDInternalLoggerTests.swift in Sources */,
D2CB6F3327C520D400A62B57 /* FilesOrchestratorTests.swift in Sources */,
D2FB1258292E0F10005B13F8 /* TrackingConsentPublisherTests.swift in Sources */,
D2CB6F3B27C520D400A62B57 /* NSURLSessionBridge.m in Sources */,
Expand Down Expand Up @@ -9572,6 +9589,7 @@
files = (
F6E106552C75E0D000716DC6 /* LogsDataModels+objc.swift in Sources */,
D2CB6F9927C5217A00A62B57 /* Casting.swift in Sources */,
F603F1272CAE9F760088E6B7 /* DDInternalLogger+objc.swift in Sources */,
D2CB6F9A27C5217A00A62B57 /* RUMDataModels+objc.swift in Sources */,
D2CB6F9B27C5217A00A62B57 /* DDSpanContext+objc.swift in Sources */,
D2CB6F9C27C5217A00A62B57 /* OTTracer+objc.swift in Sources */,
Expand Down
89 changes: 89 additions & 0 deletions DatadogCore/Tests/DatadogObjc/DDInternalLoggerTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 XCTest
import TestUtilities

@testable import DatadogInternal
@testable import DatadogCore
@testable import DatadogObjc

class DDInternalLoggerTests: XCTestCase {
let telemetry = TelemetryReceiverMock()

private var core: PassthroughCoreMock! // swiftlint:disable:this implicitly_unwrapped_optional

override func setUp() {
super.setUp()
core = PassthroughCoreMock(messageReceiver: telemetry)
}

override func tearDown() {
core = nil
super.tearDown()
}

func testObjcTelemetryDebugCallsTelemetryDebug() throws {
CoreRegistry.register(default: core)
defer { CoreRegistry.unregisterDefault() }

// Given
let id: String = .mockAny()
let message: String = .mockAny()

// When
DDInternalLogger.telemetryDebug(id: id, message: message)

// Then
XCTAssertEqual(telemetry.messages.count, 1)
let debug = try XCTUnwrap(telemetry.messages.first?.asDebug, "A debug should be send to `telemetry`.")
XCTAssertEqual(debug.id, id)
XCTAssertEqual(debug.message, message)
}

func testObjcTelemetryErrorCallsTelemetryError() throws {
CoreRegistry.register(default: core)
defer { CoreRegistry.unregisterDefault() }

// Given
let id: String = .mockAny()
let message: String = .mockAny()
let stack: String = .mockAny()
let kind: String = .mockAny()

// When
DDInternalLogger.telemetryError(id: id, message: message, kind: kind, stack: stack)

// Then
XCTAssertEqual(telemetry.messages.count, 1)

let error = try XCTUnwrap(telemetry.messages.first?.asError, "An error should be send to `telemetry`.")
XCTAssertEqual(error.id, id)
XCTAssertEqual(error.message, message)
XCTAssertEqual(error.kind, kind)
XCTAssertEqual(error.stack, stack)
}

func testWhenTelemetryIsSentThroughObjc_thenItForwardsToDDTelemetry() throws {
CoreRegistry.register(default: core)
defer { CoreRegistry.unregisterDefault() }

// When
let randomDebugMessage: String = .mockRandom()
let randomErrorMessage: String = .mockRandom()
DDInternalLogger.telemetryDebug(id: .mockAny(), message: randomDebugMessage)
DDInternalLogger.telemetryError(id: .mockAny(), message: randomErrorMessage, kind: .mockAny(), stack: .mockAny())

// Then
XCTAssertEqual(telemetry.messages.count, 2)

let debug = try XCTUnwrap(telemetry.messages.first?.asDebug, "A debug should be send to `telemetry`.")
XCTAssertEqual(debug.message, randomDebugMessage)

let error = try XCTUnwrap(telemetry.messages.last?.asError, "An error should be send to `telemetry`.")
XCTAssertEqual(error.message, randomErrorMessage)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 <XCTest/XCTest.h>
@import DatadogObjc;

@interface DDInternalLogger_apiTests : XCTestCase
@end

/*
* `DDInternalLogger` APIs smoke tests - only check if the interface is available to Objc.
*/
@implementation DDInternalLogger_apiTests

- (void)testDDInternalLogger {

[DDInternalLogger consolePrint:@"" :DDCoreLoggerLevelWarn];
[DDInternalLogger telemetryDebugWithId:@"" message:@""];
[DDInternalLogger telemetryErrorWithId:@"" message:@"" kind:@"" stack:@""];
}

@end
42 changes: 42 additions & 0 deletions DatadogObjc/Sources/DDInternalLogger+objc.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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
import DatadogInternal
import DatadogCore

@objc
public class DDInternalLogger: NSObject {
/// Function printing `String` content to console. Intended to be used only by SDK components.
@objc
public static func consolePrint(_ message: String, _ level: DDCoreLoggerLevel) {
let coreLoggerLevel: CoreLoggerLevel = switch level {
case .debug: .debug
case .warn: .warn
case .error: .error
case .critical: .critical
}
DatadogInternal.consolePrint(message, coreLoggerLevel)
}

@objc
public static func telemetryDebug(id: String, message: String) {
Datadog._internal.telemetry.debug(id: id, message: message)
}

@objc
public static func telemetryError(id: String, message: String, kind: String?, stack: String?) {
Datadog._internal.telemetry.error(id: id, message: message, kind: kind, stack: stack)
}
}

@objc
public enum DDCoreLoggerLevel: Int {
case debug
case warn
case error
case critical
}
9 changes: 9 additions & 0 deletions api-surface-objc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
# API surface for DatadogObjc:
# ----------------------------------

public class DDInternalLogger: NSObject
public static func consolePrint(_ message: String, _ level: DDCoreLoggerLevel)
public static func telemetryDebug(id: String, message: String)
public static func telemetryError(id: String, message: String, kind: String?, stack: String?)
public enum DDCoreLoggerLevel: Int
case debug
case warn
case error
case critical
open class DDNSURLSessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDataDelegate
override public init()
public init(additionalFirstPartyHostsWithHeaderTypes: [String: Set<DDTracingHeaderType>])
Expand Down