Skip to content
Draft
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

- Add attributes data to `SentryScope` (#6830)
- Add `SentryScope` attributes into log messages (#6834)
- Add integration to collect Metrics, can be enabled by setting `options.enableMetrics = true` (#6956)
Copy link
Contributor

Choose a reason for hiding this comment

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

  • 🚫 The changelog entry seems to be part of an already released section ## 9.1.0.
    Consider moving the entry to the ## Unreleased section, please.


### Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public enum SentrySDKOverrides: String, CaseIterable {
case .tracing: return SentrySDKOverrides.Tracing.allCases
case .profiling: return SentrySDKOverrides.Profiling.allCases
case .networking: return SentrySDKOverrides.Networking.allCases
case .metrics: return SentrySDKOverrides.Metrics.allCases
}
}

Expand Down Expand Up @@ -167,6 +168,11 @@ public enum SentrySDKOverrides: String, CaseIterable {
case immediateStop = "--io.sentry.profiling.continuous-profiler-immediate-stop"
}
case profiling = "Profiling"

public enum Metrics: String, SentrySDKOverride {
case enable = "--io.sentry.metrics.enable"
}
case metrics = "Metrics"
}

// MARK: Public flag/variable value access
Expand Down Expand Up @@ -348,6 +354,14 @@ extension SentrySDKOverrides.Special {
}
}

extension SentrySDKOverrides.Metrics {
public var overrideType: OverrideType {
switch self {
case .enable: return .boolean
}
}
}

// MARK: Disable Everything Helper

// These are listed exhaustively, without using default cases, so that when new cases are added to the enums above, the compiler helps remind you to annotate what type it is down here.
Expand Down Expand Up @@ -429,4 +443,11 @@ extension SentrySDKOverrides.Special {
}
}

extension SentrySDKOverrides.Metrics {
public var ignoresDisableEverything: Bool {
switch self {
case .enable: return true
}
}
}
// swiftlint:enable file_length
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,12 @@ public struct SentrySDKWrapper {
options.configureUserFeedback = configureFeedback(config:)
#endif // !os(macOS) && !os(tvOS) && !os(watchOS) && !os(visionOS)

// Integration: Logs
options.enableLogs = true

// Integration: Metrics
options.enableMetrics = SentrySDKOverrides.Metrics.enable.boolValue

// Experimental features
options.enableFileManagerSwizzling = !SentrySDKOverrides.Other.disableFileManagerSwizzling.boolValue
options.experimental.enableUnhandledCPPExceptionsV2 = true
Expand Down
3 changes: 3 additions & 0 deletions Samples/Shared/feature-flags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ schemeTemplates:
"--io.sentry.other.reject-view-hierarchy-in-before-capture-view-hierarchy": false
"--io.sentry.other.reject-all-spans": false

# metrics
"--io.sentry.metrics.enable": false

environmentVariables:
# events
- variable: "--io.sentry.events.sampleRate"
Expand Down
24 changes: 24 additions & 0 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,8 @@
D46712622DCD059900D4074A /* SentryRedactDefaultOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46712612DCD059500D4074A /* SentryRedactDefaultOptionsTests.swift */; };
D46712642DCD063800D4074A /* PreviewRedactOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46712632DCD062700D4074A /* PreviewRedactOptionsTests.swift */; };
D468C0622D3669A200964230 /* SentryFileIOTracker+SwiftHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D468C0612D3669A200964230 /* SentryFileIOTracker+SwiftHelpers.swift */; };
D46B041D2EDF168400AF4A0A /* MetricsIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46B041C2EDF167D00AF4A0A /* MetricsIntegration.swift */; };
D46B04202EDF175C00AF4A0A /* MetricsIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46B041F2EDF175600AF4A0A /* MetricsIntegrationTests.swift */; };
D473ACD72D8090FC000F1CC6 /* FileManager+SentryTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D473ACD62D8090FC000F1CC6 /* FileManager+SentryTracing.swift */; };
D480F9D92DE47A50009A0594 /* TestSentryScopePersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D480F9D82DE47A48009A0594 /* TestSentryScopePersistentStore.swift */; };
D480F9DB2DE47AF2009A0594 /* SentryScopePersistentStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D480F9DA2DE47AEB009A0594 /* SentryScopePersistentStoreTests.swift */; };
Expand Down Expand Up @@ -2145,6 +2147,8 @@
D46712612DCD059500D4074A /* SentryRedactDefaultOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactDefaultOptionsTests.swift; sourceTree = "<group>"; };
D46712632DCD062700D4074A /* PreviewRedactOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewRedactOptionsTests.swift; sourceTree = "<group>"; };
D468C0612D3669A200964230 /* SentryFileIOTracker+SwiftHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryFileIOTracker+SwiftHelpers.swift"; sourceTree = "<group>"; };
D46B041C2EDF167D00AF4A0A /* MetricsIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsIntegration.swift; sourceTree = "<group>"; };
D46B041F2EDF175600AF4A0A /* MetricsIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricsIntegrationTests.swift; sourceTree = "<group>"; };
D46D45E12D5F3FD600A1CB35 /* Sentry_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Sentry_Base.xctestplan; sourceTree = "<group>"; };
D46D45E92D5F411700A1CB35 /* SentrySwiftUI_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = SentrySwiftUI_Base.xctestplan; path = Plans/SentrySwiftUI_Base.xctestplan; sourceTree = SOURCE_ROOT; };
D473ACD62D8090FC000F1CC6 /* FileManager+SentryTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+SentryTracing.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3520,6 +3524,7 @@
F498EBA52EE0B8E400F57509 /* SentrySwiftIntegrationInstallerTests.swift */,
843FB3422D156B9900558F18 /* Feedback */,
7BF6505D292B77D100BBA5A8 /* MetricKit */,
D46B041E2EDF173A00AF4A0A /* Metrics */,
D808FB85281AB2EF009A2A33 /* UIEvents */,
D8AB40D92806EBDC00E5E9F7 /* Screenshot */,
0A9BF4E528A123070068D266 /* ViewHierarchy */,
Expand Down Expand Up @@ -4392,6 +4397,22 @@
path = IO;
sourceTree = "<group>";
};
D46B04162EDF167800AF4A0A /* Metrics */ = {
isa = PBXGroup;
children = (
D46B041C2EDF167D00AF4A0A /* MetricsIntegration.swift */,
);
path = Metrics;
sourceTree = "<group>";
};
D46B041E2EDF173A00AF4A0A /* Metrics */ = {
isa = PBXGroup;
children = (
D46B041F2EDF175600AF4A0A /* MetricsIntegrationTests.swift */,
);
path = Metrics;
sourceTree = "<group>";
};
D46D45E22D5F3FD600A1CB35 /* Plans */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -4876,6 +4897,7 @@
isa = PBXGroup;
children = (
925189AB2EDDA6A300557BD1 /* Log */,
D46B04162EDF167800AF4A0A /* Metrics */,
FAB0073C2E9F47DE001C806A /* Session */,
FAE579B42E7DBE9400B710F9 /* SentryGlobalEventProcessor.swift */,
FAD882C12EDAADF90055AA44 /* SwiftAsyncIntegration.swift */,
Expand Down Expand Up @@ -6191,6 +6213,7 @@
62E59A5A2E8FB85300DB7A7B /* SentryTracePropagation.m in Sources */,
FAB007522E9FE2FF001C806A /* SentrySwizzleWrapper.swift in Sources */,
62E300942D5202890037AA3F /* SentryExceptionCodable.swift in Sources */,
D46B041D2EDF168400AF4A0A /* MetricsIntegration.swift in Sources */,
0A2D8D5B289815C0008720F6 /* SentryBaseIntegration.m in Sources */,
639FCF991EBC7B9700778193 /* SentryEvent.m in Sources */,
D820CDB72BB1895F00BA339D /* SentrySessionReplayIntegration.m in Sources */,
Expand Down Expand Up @@ -6278,6 +6301,7 @@
7BFAA6E7297AA16A00E7E02E /* SentryCrashMonitor_CppException_Tests.mm in Sources */,
9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */,
621655662DB12A8900810504 /* SentryCrashMach-OTests.m in Sources */,
D46B04202EDF175C00AF4A0A /* MetricsIntegrationTests.swift in Sources */,
62B220BB2E93A9EC004620FF /* SentryTracePropagationTests.swift in Sources */,
D8B76B0828081461000A58C4 /* TestSentryScreenshotProvider.swift in Sources */,
A8AFFCD22907DA7600967CD7 /* SentryHttpStatusCodeRangeTests.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions SentryTestUtils/Sources/TestOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public extension Options {
attachViewHierarchy = false
enableUIViewControllerTracing = false
#endif
enableMetrics = false
}

static func noIntegrations() -> Options {
Expand Down
5 changes: 5 additions & 0 deletions Sources/Sentry/SentryDependencyContainerSwiftHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ + (BOOL)enableLogs:(SentryOptions *)options
return options.enableLogs;
}

+ (BOOL)enableMetrics:(SentryOptions *)options
{
return options.enableMetrics;
}

+ (NSArray<NSString *> *)enabledFeatures:(SentryOptions *)options
{
return [SentryEnabledFeaturesBuilder getEnabledFeaturesWithOptions:options];
Expand Down
3 changes: 3 additions & 0 deletions Sources/Sentry/SentryOptionsInternal.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ + (BOOL)validateOptions:(NSDictionary<NSString *, id> *)options

[self setBool:options[@"enableLogs"] block:^(BOOL value) { sentryOptions.enableLogs = value; }];

[self setBool:options[@"enableMetrics"]
block:^(BOOL value) { sentryOptions.enableMetrics = value; }];

[self setBool:options[@"enableNetworkBreadcrumbs"]
block:^(BOOL value) { sentryOptions.enableNetworkBreadcrumbs = value; }];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (NSString *)environment:(SentryOptionsObjC *)options;
+ (NSObject *_Nullable)beforeSendLog:(NSObject *)beforeSendLog options:(SentryOptionsObjC *)options;
+ (BOOL)enableLogs:(SentryOptionsObjC *)options;
+ (BOOL)enableMetrics:(SentryOptionsObjC *)options;
+ (NSArray<NSString *> *)enabledFeatures:(SentryOptionsObjC *)options;
+ (BOOL)sendDefaultPii:(SentryOptionsObjC *)options;

Expand Down
3 changes: 2 additions & 1 deletion Sources/Swift/Core/Integrations/Integrations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ private struct AnyIntegration {

var integrations: [AnyIntegration] = [
.init(SwiftAsyncIntegration.self),
.init(SentryAutoSessionTrackingIntegration.self)
.init(SentryAutoSessionTrackingIntegration.self),
.init(MetricsIntegration.self)
]

#if os(iOS) && !SENTRY_NO_UIKIT
Expand Down
3 changes: 3 additions & 0 deletions Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ import Foundation
if options.experimental.enableUnhandledCPPExceptionsV2 {
features.append("unhandledCPPExceptionsV2")
}
if options.enableMetrics {
features.append("metrics")
}

return features
}
Expand Down
13 changes: 13 additions & 0 deletions Sources/Swift/Integrations/Metrics/MetricsIntegration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
final class MetricsIntegration<Dependencies>: NSObject, SwiftIntegration {
init?(with options: Options, dependencies: Dependencies) {
guard options.enableMetrics else { return nil }

SentrySDKLog.debug("Integration initialized")
}

func uninstall() {}

static var name: String {
"SentryMetricsIntegration"
}
}
5 changes: 5 additions & 0 deletions Sources/Swift/Options.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
/// @note Default value is @c false.
@objc public var enableLogs: Bool = false

/// When enabled, the SDK sends metrics to Sentry. Metrics can be captured using the SentrySDK.metrics
/// API, which allows you to send, view and query counters, gauges and measurements.
/// @note Default value is @c false.
@objc public var enableMetrics: Bool = false

/// Use this callback to drop or modify a log before the SDK sends it to Sentry. Return nil to
/// drop the log.
@objc public var beforeSendLog: ((SentryLog) -> SentryLog?)?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Foundation
@_spi(Private) @testable import Sentry
@_spi(Private) import SentryTestUtils
import XCTest

class MetricsIntegrationTests: XCTestCase {

override func tearDown() {
super.tearDown()
clearTestState()
}

// MARK: - Tests

func testStartSDK_whenIntegrationIsNotEnabled_shouldNotBeInstalled() {
// -- Act --
startSDK(isEnabled: false)

// -- Assert --
XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 0)
}

func testStartSDK_whenIntegrationIsEnabled_shouldBeInstalled() {
// -- Act --
startSDK(isEnabled: true)

// -- Assert --
XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 1)
}

// MARK: - Helpers

private func startSDK(isEnabled: Bool, configure: ((Options) -> Void)? = nil) {
SentrySDK.start {
$0.dsn = TestConstants.dsnForTestCase(type: MetricsIntegrationTests.self)
$0.removeAllIntegrations()

$0.enableMetrics = isEnabled

configure?($0)
}
SentrySDKInternal.currentHub().startSession()
}

private func getSut() throws -> MetricsIntegration<SentryDependencyContainer> {
return try XCTUnwrap(SentrySDKInternal.currentHub().installedIntegrations().first as? MetricsIntegration)
}
}
5 changes: 5 additions & 0 deletions Tests/SentryTests/SentryOptionsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ - (void)testEnableLogs
[self testBooleanField:@"enableLogs" defaultValue:NO];
}

- (void)testEnableMetrics
{
[self testBooleanField:@"enableMetrics" defaultValue:NO];
}

- (void)testEnableAutoBreadcrumbTracking
{
[self testBooleanField:@"enableAutoBreadcrumbTracking"];
Expand Down
76 changes: 76 additions & 0 deletions sdk_api.json
Original file line number Diff line number Diff line change
Expand Up @@ -45757,6 +45757,82 @@
}
]
},
{
"kind": "Var",
"name": "enableMetrics",
"printedName": "enableMetrics",
"children": [
{
"kind": "TypeNominal",
"name": "Bool",
"printedName": "Swift.Bool",
"usr": "s:Sb"
}
],
"declKind": "Var",
"usr": "c:@M@Sentry@objc(cs)SentryOptions(py)enableMetrics",
"mangledName": "$s6Sentry7OptionsC13enableMetricsSbvp",
"moduleName": "Sentry",
"declAttributes": [
"Final",
"ObjC",
"HasStorage"
],
"hasStorage": true,
"accessors": [
{
"kind": "Accessor",
"name": "Get",
"printedName": "Get()",
"children": [
{
"kind": "TypeNominal",
"name": "Bool",
"printedName": "Swift.Bool",
"usr": "s:Sb"
}
],
"declKind": "Accessor",
"usr": "c:@M@Sentry@objc(cs)SentryOptions(im)enableMetrics",
"mangledName": "$s6Sentry7OptionsC13enableMetricsSbvg",
"moduleName": "Sentry",
"implicit": true,
"declAttributes": [
"Final",
"ObjC"
],
"accessorKind": "get"
},
{
"kind": "Accessor",
"name": "Set",
"printedName": "Set()",
"children": [
{
"kind": "TypeNominal",
"name": "Void",
"printedName": "()"
},
{
"kind": "TypeNominal",
"name": "Bool",
"printedName": "Swift.Bool",
"usr": "s:Sb"
}
],
"declKind": "Accessor",
"usr": "c:@M@Sentry@objc(cs)SentryOptions(im)setEnableMetrics:",
"mangledName": "$s6Sentry7OptionsC13enableMetricsSbvs",
"moduleName": "Sentry",
"implicit": true,
"declAttributes": [
"Final",
"ObjC"
],
"accessorKind": "set"
}
]
},
{
"kind": "Var",
"name": "beforeSendLog",
Expand Down
Loading