From 2f954250b210f937f8a56662f2078168a47b6401 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Thu, 21 Aug 2025 11:06:21 +0200 Subject: [PATCH 1/7] docs(apple): Add docs for structured logs --- docs/platforms/apple/common/index.mdx | 39 ++++++++- docs/platforms/apple/common/logs/index.mdx | 26 ++++++ platform-includes/logs/options/apple.mdx | 46 ++++++++++ platform-includes/logs/requirements/apple.mdx | 1 + platform-includes/logs/setup/apple.mdx | 21 +++++ platform-includes/logs/usage/apple.mdx | 85 +++++++++++++++++++ 6 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 docs/platforms/apple/common/logs/index.mdx create mode 100644 platform-includes/logs/options/apple.mdx create mode 100644 platform-includes/logs/requirements/apple.mdx create mode 100644 platform-includes/logs/setup/apple.mdx create mode 100644 platform-includes/logs/usage/apple.mdx diff --git a/docs/platforms/apple/common/index.mdx b/docs/platforms/apple/common/index.mdx index 67c03558641fdd..1b7d1fdde9964d 100644 --- a/docs/platforms/apple/common/index.mdx +++ b/docs/platforms/apple/common/index.mdx @@ -36,13 +36,13 @@ Select which Sentry features you'd like to install in addition to Error Monitori - + - + @@ -123,6 +123,11 @@ func application(_ application: UIApplication, options.sessionReplay.onErrorSampleRate = 1.0 options.sessionReplay.sessionSampleRate = 0.1 // ___PRODUCT_OPTION_END___ session-replay + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true + // ___PRODUCT_OPTION_END___ logs } return true @@ -160,6 +165,11 @@ func application(_ application: UIApplication, options.sessionReplay.onErrorSampleRate = 1.0; options.sessionReplay.sessionSampleRate = 0.1; // ___PRODUCT_OPTION_END___ session-replay + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = YES; + // ___PRODUCT_OPTION_END___ logs }]; return YES; @@ -198,6 +208,11 @@ struct SwiftUIApp: App { options.sessionReplay.onErrorSampleRate = 1.0 options.sessionReplay.sessionSampleRate = 0.1 // ___PRODUCT_OPTION_END___ session-replay + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true + // ___PRODUCT_OPTION_END___ logs } } } @@ -232,6 +247,11 @@ func application(_ application: UIApplication, $0.sessionSampleRate = 1 } // ___PRODUCT_OPTION_END___ profiling + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true + // ___PRODUCT_OPTION_END___ logs } return true @@ -263,6 +283,11 @@ func application(_ application: UIApplication, profiling.sessionSampleRate = 1.f; }; // ___PRODUCT_OPTION_END___ profiling + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = YES; + // ___PRODUCT_OPTION_END___ logs }]; return YES; @@ -295,6 +320,11 @@ struct SwiftUIApp: App { $0.sessionSampleRate = 1 } // ___PRODUCT_OPTION_END___ profiling + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true + // ___PRODUCT_OPTION_END___ logs } } } @@ -324,6 +354,11 @@ func applicationDidFinishLaunching() { // We recommend adjusting this value in production. options.tracesSampleRate = 1 // ___PRODUCT_OPTION_END___ performance + // ___PRODUCT_OPTION_START___ logs + + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true + // ___PRODUCT_OPTION_END___ logs } } ``` diff --git a/docs/platforms/apple/common/logs/index.mdx b/docs/platforms/apple/common/logs/index.mdx new file mode 100644 index 00000000000000..cb9856b18584eb --- /dev/null +++ b/docs/platforms/apple/common/logs/index.mdx @@ -0,0 +1,26 @@ +--- +title: Set Up Logs +sidebar_title: Logs +description: "Structured logs allow you to send, view and query logs sent from your applications within Sentry." +sidebar_order: 5755 +--- + + + +With Sentry Structured Logs, you can send text based log information from your applications to Sentry. Once in Sentry, these logs can be viewed alongside relevant errors, searched by text-string, or searched using their individual attributes. + +## Requirements + + + +## Setup + + + +## Usage + + + +## Options + + diff --git a/platform-includes/logs/options/apple.mdx b/platform-includes/logs/options/apple.mdx new file mode 100644 index 00000000000000..26b1f1e08f24b2 --- /dev/null +++ b/platform-includes/logs/options/apple.mdx @@ -0,0 +1,46 @@ +#### beforeSendLog + +To filter logs, or update them before they are sent to Sentry, you can use the `beforeSendLog` option. + +```swift {tabTitle:Swift} +import Sentry + +SentrySDK.start { options in + options.dsn = "___PUBLIC_DSN___" + options.experimental.enableLogs = true + + options.beforeSendLog = { log in + if log.level == .info { + // Filter out all info logs + return nil + } + return log + } +} +``` + +```objc {tabTitle:Objective-C} +@import Sentry; + +[SentrySDK startWithConfigureOptions:^(SentryOptions *options) { + options.dsn = @"___PUBLIC_DSN___"; + options.experimental.enableLogs = YES; + + options.beforeSendLog = ^SentryLog* (SentryLog *log) { + if (log.level == SentryStructuredLogLevelInfo) { + // Filter out all info logs + return nil; + } + return log; + }; +}]; +``` + +The `beforeSendLog` function receives a log object, and should return the log object if you want it to be sent to Sentry, or `nil` if you want to discard it. + +The log object has the following properties: + +- `level`: The log level (trace, debug, info, warn, error, fatal) +- `message`: The message to be logged +- `timestamp`: The timestamp of the log +- `attributes`: The attributes of the log diff --git a/platform-includes/logs/requirements/apple.mdx b/platform-includes/logs/requirements/apple.mdx new file mode 100644 index 00000000000000..287fe4dd5da5b9 --- /dev/null +++ b/platform-includes/logs/requirements/apple.mdx @@ -0,0 +1 @@ +Logs for Apple platforms are supported in Sentry Cocoa SDK version `8.55.0` and above. Logs are still experimental and the API may change in the future. diff --git a/platform-includes/logs/setup/apple.mdx b/platform-includes/logs/setup/apple.mdx new file mode 100644 index 00000000000000..34d1c4a6bfdcda --- /dev/null +++ b/platform-includes/logs/setup/apple.mdx @@ -0,0 +1,21 @@ +To enable logging, you need to initialize the SDK with the experimental `enableLogs` option set to `true`. + +```swift {tabTitle:Swift} +import Sentry + +SentrySDK.start { options in + options.dsn = "___PUBLIC_DSN___" + // Enable logs to be sent to Sentry + options.experimental.enableLogs = true +} +``` + +```objc {tabTitle:Objective-C} +@import Sentry; + +[SentrySDK startWithConfigureOptions:^(SentryOptions *options) { + options.dsn = @"___PUBLIC_DSN___"; + // Enable logs to be sent to Sentry + options.experimental.enableLogs = YES; +}]; +``` diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx new file mode 100644 index 00000000000000..3837b8516b8f7c --- /dev/null +++ b/platform-includes/logs/usage/apple.mdx @@ -0,0 +1,85 @@ +Once the feature is enabled on the SDK and the SDK is initialized, you can send logs using the `Sentry.logger` APIs. + +The `Sentry.logger` namespace exposes six methods that you can use to log messages at different log levels: `trace`, `debug`, `info`, `warn`, `error`, and `fatal`. Supported types for attributes are Strings, Int, Double, and Bool. + +```swift {tabTitle:Swift} +import Sentry + +let logger = SentrySDK.logger + +// Log messages without attributes +logger.trace("Starting database connection") +logger.debug("Cache miss for user") +logger.info("Updated profile") + +// Log messages with attributes +logger.trace("Starting database connection", attributes: ["database": "users"]) +logger.debug("Cache miss for user", attributes: ["userId": 123]) +logger.info("Updated profile", attributes: ["profileId": 345]) +logger.warn("Rate limit reached for endpoint", attributes: [ + "endpoint": "/api/results/", + "isEnterprise": false +]) +logger.error("Failed to process payment", attributes: [ + "orderId": "order_123", + "amount": 99.99 +]) +logger.fatal("Database connection pool exhausted", attributes: [ + "database": "users", + "activeConnections": 100 +]) +``` + +```objc {tabTitle:Objective-C} +@import Sentry; + +SentryLogger *logger = SentrySDK.logger; + +// Log messages without attributes +[logger trace:@"Starting database connection"]; +[logger debug:@"Cache miss for user"]; +[logger info:@"Updated profile"]; + +// Log messages with attributes +[logger trace:@"Starting database connection" attributes:@{@"database": @"users"}]; +[logger debug:@"Cache miss for user" attributes:@{@"userId": @123}]; +[logger info:@"Updated profile" attributes:@{@"profileId": @345}]; +[logger warn:@"Rate limit reached for endpoint" attributes:@{ + @"endpoint": @"/api/results/", + @"isEnterprise": @NO +}]; +[logger error:@"Failed to process payment" attributes:@{ + @"orderId": @"order_123", + @"amount": @99.99 +}]; +[logger fatal:@"Database connection pool exhausted" attributes:@{ + @"database": @"users", + @"activeConnections": @100 +}]; +``` + +## String Interpolation (Swift Only) + +Swift supports automatic extraction of interpolated values as attributes. When you use string interpolation in your log messages, supported types (Strings, Int, Double, and Bool) are automatically extracted and added as attributes with the key format `sentry.message.parameter.{index}`. + +```swift +let userId = "user_123" +let orderCount = 5 +let isPremium = true +let totalAmount = 99.99 + +// String interpolation automatically extracts values as attributes +logger.info("User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)") + +// This is equivalent to manually specifying attributes: +logger.info( + "User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)", + attributes: [ + "sentry.message.template": "User {0} placed {1} orders, premium: {2}, total: ${3}", + "sentry.message.parameter.0": userId, + "sentry.message.parameter.1": orderCount, + "sentry.message.parameter.2": isPremium, + "sentry.message.parameter.3": totalAmount + ] +) +``` From fa81bdcd05b483d9043cd1f4915ddee8f49c4e3b Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Thu, 21 Aug 2025 11:39:57 +0200 Subject: [PATCH 2/7] update title --- platform-includes/logs/usage/apple.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx index 3837b8516b8f7c..d99b42b0adf572 100644 --- a/platform-includes/logs/usage/apple.mdx +++ b/platform-includes/logs/usage/apple.mdx @@ -58,7 +58,7 @@ SentryLogger *logger = SentrySDK.logger; }]; ``` -## String Interpolation (Swift Only) +### String Interpolation (Swift Only) Swift supports automatic extraction of interpolated values as attributes. When you use string interpolation in your log messages, supported types (Strings, Int, Double, and Bool) are automatically extracted and added as attributes with the key format `sentry.message.parameter.{index}`. @@ -73,7 +73,7 @@ logger.info("User \(userId) placed \(orderCount) orders, premium: \(isPremium), // This is equivalent to manually specifying attributes: logger.info( - "User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)", + "User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)", attributes: [ "sentry.message.template": "User {0} placed {1} orders, premium: {2}, total: ${3}", "sentry.message.parameter.0": userId, From 89e148f47b8759c5665874539094bd531b3b3405 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Thu, 21 Aug 2025 11:46:22 +0200 Subject: [PATCH 3/7] update how message is passed --- platform-includes/logs/usage/apple.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx index d99b42b0adf572..aa4090a9ac7ae8 100644 --- a/platform-includes/logs/usage/apple.mdx +++ b/platform-includes/logs/usage/apple.mdx @@ -72,10 +72,11 @@ let totalAmount = 99.99 logger.info("User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)") // This is equivalent to manually specifying attributes: +let message = "User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)" logger.info( - "User \(userId) placed \(orderCount) orders, premium: \(isPremium), total: $\(totalAmount)", + message, attributes: [ - "sentry.message.template": "User {0} placed {1} orders, premium: {2}, total: ${3}", + "sentry.message.template": message, "sentry.message.parameter.0": userId, "sentry.message.parameter.1": orderCount, "sentry.message.parameter.2": isPremium, From 22b682608e87d3cb3128186054d4cce6de153af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Thu, 21 Aug 2025 13:33:26 +0200 Subject: [PATCH 4/7] fix incorrect @NO type Co-authored-by: Karl Heinz Struggl --- platform-includes/logs/usage/apple.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx index aa4090a9ac7ae8..ced047cadf7034 100644 --- a/platform-includes/logs/usage/apple.mdx +++ b/platform-includes/logs/usage/apple.mdx @@ -46,7 +46,7 @@ SentryLogger *logger = SentrySDK.logger; [logger info:@"Updated profile" attributes:@{@"profileId": @345}]; [logger warn:@"Rate limit reached for endpoint" attributes:@{ @"endpoint": @"/api/results/", - @"isEnterprise": @NO + @"isEnterprise": NO }]; [logger error:@"Failed to process payment" attributes:@{ @"orderId": @"order_123", From 029b597410a4f2f344a7ad8a13196175187f2762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Andra=C5=A1ec?= Date: Thu, 21 Aug 2025 13:37:08 +0200 Subject: [PATCH 5/7] revert @NO --- platform-includes/logs/usage/apple.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx index ced047cadf7034..aa4090a9ac7ae8 100644 --- a/platform-includes/logs/usage/apple.mdx +++ b/platform-includes/logs/usage/apple.mdx @@ -46,7 +46,7 @@ SentryLogger *logger = SentrySDK.logger; [logger info:@"Updated profile" attributes:@{@"profileId": @345}]; [logger warn:@"Rate limit reached for endpoint" attributes:@{ @"endpoint": @"/api/results/", - @"isEnterprise": NO + @"isEnterprise": @NO }]; [logger error:@"Failed to process payment" attributes:@{ @"orderId": @"order_123", From 27c1788567e443cfd0f6a325faae3be4f00db565 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Mon, 25 Aug 2025 10:18:21 +0200 Subject: [PATCH 6/7] update spacing --- docs/platforms/apple/common/index.mdx | 29 +++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/platforms/apple/common/index.mdx b/docs/platforms/apple/common/index.mdx index 1b7d1fdde9964d..efe61f05418b60 100644 --- a/docs/platforms/apple/common/index.mdx +++ b/docs/platforms/apple/common/index.mdx @@ -104,21 +104,21 @@ func application(_ application: UIApplication, // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = true - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = 1 // ___PRODUCT_OPTION_END___ performance - // ___PRODUCT_OPTION_START___ profiling + options.configureProfiling = { $0.lifecycle = .trace $0.sessionSampleRate = 1 } // ___PRODUCT_OPTION_END___ profiling - // ___PRODUCT_OPTION_START___ session-replay + // Record session replays for 100% of errors and 10% of sessions options.sessionReplay.onErrorSampleRate = 1.0 options.sessionReplay.sessionSampleRate = 0.1 @@ -146,21 +146,21 @@ func application(_ application: UIApplication, // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = YES; - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = @1.f; // ___PRODUCT_OPTION_END___ performance - // ___PRODUCT_OPTION_START___ profiling + options.configureProfiling = ^(SentryProfileOptions *profiling) { profiling.lifecycle = SentryProfileLifecycleTrace; profiling.sessionSampleRate = 1.f; }; // ___PRODUCT_OPTION_END___ profiling - // ___PRODUCT_OPTION_START___ session-replay + // Record session replays for 100% of errors and 10% of sessions options.sessionReplay.onErrorSampleRate = 1.0; options.sessionReplay.sessionSampleRate = 0.1; @@ -189,27 +189,26 @@ struct SwiftUIApp: App { // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = true - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = 1 // ___PRODUCT_OPTION_END___ performance - // ___PRODUCT_OPTION_START___ profiling + options.configureProfiling = { $0.lifecycle = .trace $0.sessionSampleRate = 1 } // ___PRODUCT_OPTION_END___ profiling - // ___PRODUCT_OPTION_START___ session-replay // Record session replays for 100% of errors and 10% of sessions options.sessionReplay.onErrorSampleRate = 1.0 options.sessionReplay.sessionSampleRate = 0.1 // ___PRODUCT_OPTION_END___ session-replay - // ___PRODUCT_OPTION_START___ logs + // ___PRODUCT_OPTION_START___ logs // Enable logs to be sent to Sentry options.experimental.enableLogs = true // ___PRODUCT_OPTION_END___ logs @@ -234,14 +233,14 @@ func application(_ application: UIApplication, // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = true - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = 1 // ___PRODUCT_OPTION_END___ performance - // ___PRODUCT_OPTION_START___ profiling + options.configureProfiling = { $0.lifecycle = .trace $0.sessionSampleRate = 1 @@ -307,14 +306,14 @@ struct SwiftUIApp: App { // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = true - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = 1 // ___PRODUCT_OPTION_END___ performance - // ___PRODUCT_OPTION_START___ profiling + options.configureProfiling = { $0.lifecycle = .trace $0.sessionSampleRate = 1 @@ -348,8 +347,8 @@ func applicationDidFinishLaunching() { // Adds IP for users. // For more information, visit: https://docs.sentry.io/platforms/apple/data-management/data-collected/ options.sendDefaultPii = true - // ___PRODUCT_OPTION_START___ performance + // Set tracesSampleRate to 1 to capture 100% of transactions for performance monitoring. // We recommend adjusting this value in production. options.tracesSampleRate = 1 From 43d5e482e1a33136f08803b8955693aec8aa38c0 Mon Sep 17 00:00:00 2001 From: Denis Andrasec Date: Tue, 26 Aug 2025 11:28:26 +0200 Subject: [PATCH 7/7] fix template --- platform-includes/logs/usage/apple.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-includes/logs/usage/apple.mdx b/platform-includes/logs/usage/apple.mdx index aa4090a9ac7ae8..432bf9b684c33a 100644 --- a/platform-includes/logs/usage/apple.mdx +++ b/platform-includes/logs/usage/apple.mdx @@ -76,7 +76,7 @@ let message = "User \(userId) placed \(orderCount) orders, premium: \(isPremium) logger.info( message, attributes: [ - "sentry.message.template": message, + "sentry.message.template": "User {0} placed {1} orders, premium: {2}, total: {3}", "sentry.message.parameter.0": userId, "sentry.message.parameter.1": orderCount, "sentry.message.parameter.2": isPremium,