diff --git a/dart/lib/src/sentry_client.dart b/dart/lib/src/sentry_client.dart index e3809568da..f567508f24 100644 --- a/dart/lib/src/sentry_client.dart +++ b/dart/lib/src/sentry_client.dart @@ -63,7 +63,12 @@ class SentryClient { final rateLimiter = RateLimiter(options); options.transport = HttpTransport(options, rateLimiter); } - if (options.spotlight.enabled) { + // TODO: Web might change soon to use the JS SDK so we can remove it here later on + final enableSpotlight = (options.spotlight.enabled && + (options.platformChecker.isWeb || + options.platformChecker.platform.isLinux || + options.platformChecker.platform.isWindows)); + if (enableSpotlight) { options.transport = SpotlightHttpTransport(options, options.transport); } return SentryClient._(options); diff --git a/dart/lib/src/spotlight.dart b/dart/lib/src/spotlight.dart index b106ed3547..9a914cab20 100644 --- a/dart/lib/src/spotlight.dart +++ b/dart/lib/src/spotlight.dart @@ -8,14 +8,7 @@ class Spotlight { /// The Spotlight Sidecar URL. /// Defaults to http://10.0.2.2:8969/stream due to Emulator on Android. /// Otherwise defaults to http://localhost:8969/stream. - String url; + String? url; - Spotlight({required this.enabled, String? url}) - : url = url ?? _defaultSpotlightUrl(); -} - -String _defaultSpotlightUrl() { - return (PlatformChecker().platform.isAndroid - ? 'http://10.0.2.2:8969/stream' - : 'http://localhost:8969/stream'); + Spotlight({required this.enabled, this.url}); } diff --git a/dart/lib/src/transport/spotlight_http_transport.dart b/dart/lib/src/transport/spotlight_http_transport.dart index 1889bb7339..e44cae44b9 100644 --- a/dart/lib/src/transport/spotlight_http_transport.dart +++ b/dart/lib/src/transport/spotlight_http_transport.dart @@ -8,6 +8,8 @@ import '../http_client/client_provider.dart' if (dart.library.io) '../http_client/io_client_provider.dart'; /// Spotlight HTTP transport decorator that sends Sentry envelopes to both Sentry and Spotlight. +/// This will be used on platforms that do not have native SDK support. +/// Platforms with native SDK support will configure spotlight directly in the native SDK options. class SpotlightHttpTransport extends Transport { final SentryOptions _options; final Transport _transport; @@ -21,8 +23,8 @@ class SpotlightHttpTransport extends Transport { } SpotlightHttpTransport._(this._options, this._transport) - : _requestHandler = HttpTransportRequestHandler( - _options, Uri.parse(_options.spotlight.url)); + : _requestHandler = HttpTransportRequestHandler(_options, + Uri.parse(_options.spotlight.url ?? _defaultSpotlightUrl())); @override Future send(SentryEnvelope envelope) async { @@ -48,3 +50,7 @@ class SpotlightHttpTransport extends Transport { target: 'Spotlight'); } } + +String _defaultSpotlightUrl() { + return 'http://localhost:8969/stream'; +} diff --git a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt index d38872f6ee..8d4e40948d 100644 --- a/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt +++ b/flutter/android/src/main/kotlin/io/sentry/flutter/SentryFlutter.kt @@ -81,6 +81,12 @@ class SentryFlutter( data.getIfNotNull("proguardUuid") { options.proguardUuid = it } + data.getIfNotNull("enableSpotlight") { + options.isEnableSpotlight = it + } + data.getIfNotNull("spotlightUrl") { + options.spotlightConnectionUrl = it + } val nativeCrashHandling = (data["enableNativeCrashHandling"] as? Boolean) ?: true // nativeCrashHandling has priority over anrEnabled diff --git a/flutter/example/android/app/local.properties b/flutter/example/android/app/local.properties new file mode 100644 index 0000000000..127723a8f4 --- /dev/null +++ b/flutter/example/android/app/local.properties @@ -0,0 +1,8 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Tue Sep 10 17:20:30 CEST 2024 +sdk.dir=/Users/giancarlobuenaflor/Library/Android/sdk diff --git a/flutter/example/android/app/src/main/AndroidManifest.xml b/flutter/example/android/app/src/main/AndroidManifest.xml index 1b2b2012cf..800fb96d4c 100644 --- a/flutter/example/android/app/src/main/AndroidManifest.xml +++ b/flutter/example/android/app/src/main/AndroidManifest.xml @@ -8,7 +8,8 @@ android:allowBackup="false" android:label="sentry_flutter_example" android:icon="@mipmap/ic_launcher" - android:extractNativeLibs="true"> + android:extractNativeLibs="true" + android:networkSecurityConfig="@xml/network"> + + + + + 10.0.2.2 + + diff --git a/flutter/example/ios/Runner/AppDelegate.swift b/flutter/example/ios/Runner/AppDelegate.swift index a231cc9c60..c24cacbbb2 100644 --- a/flutter/example/ios/Runner/AppDelegate.swift +++ b/flutter/example/ios/Runner/AppDelegate.swift @@ -2,7 +2,7 @@ import UIKit import Flutter import Sentry -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { private let _channel = "example.flutter.sentry.io" diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index dd870eb587..3254562687 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -90,8 +90,8 @@ Future setupSentry( options.maxResponseBodySize = MaxResponseBodySize.always; options.navigatorKey = navigatorKey; - options.experimental.replay.sessionSampleRate = 1.0; - options.experimental.replay.onErrorSampleRate = 1.0; + // options.experimental.replay.sessionSampleRate = 1.0; + // options.experimental.replay.onErrorSampleRate = 1.0; _isIntegrationTest = isIntegrationTest; if (_isIntegrationTest) { diff --git a/flutter/ios/Classes/SentryFlutter.swift b/flutter/ios/Classes/SentryFlutter.swift index 987528987c..02beabb5df 100644 --- a/flutter/ios/Classes/SentryFlutter.swift +++ b/flutter/ios/Classes/SentryFlutter.swift @@ -70,6 +70,12 @@ public final class SentryFlutter { if let appHangTimeoutIntervalMillis = data["appHangTimeoutIntervalMillis"] as? NSNumber { options.appHangTimeoutInterval = appHangTimeoutIntervalMillis.doubleValue / 1000 } + if let spotlightUrl = data["spotlightUrl"] as? String { + options.spotlightUrl = spotlightUrl + } + if let enableSpotlight = data["enableSpotlight"] as? Bool { + options.enableSpotlight = enableSpotlight + } if let proxy = data["proxy"] as? [String: Any] { guard let host = proxy["host"] as? String, let port = proxy["port"] as? Int, diff --git a/flutter/lib/src/native/sentry_native_channel.dart b/flutter/lib/src/native/sentry_native_channel.dart index 360290230d..ce5f063d37 100644 --- a/flutter/lib/src/native/sentry_native_channel.dart +++ b/flutter/lib/src/native/sentry_native_channel.dart @@ -71,6 +71,8 @@ class SentryNativeChannel 'sessionSampleRate': options.experimental.replay.sessionSampleRate, 'onErrorSampleRate': options.experimental.replay.onErrorSampleRate, }, + 'enableSpotlight': options.spotlight.enabled, + 'spotlightUrl': options.spotlight.url, }); } diff --git a/flutter/test/integrations/init_native_sdk_test.dart b/flutter/test/integrations/init_native_sdk_test.dart index bfce621eb3..46b64a545b 100644 --- a/flutter/test/integrations/init_native_sdk_test.dart +++ b/flutter/test/integrations/init_native_sdk_test.dart @@ -69,6 +69,8 @@ void main() { 'sessionSampleRate': null, 'onErrorSampleRate': null, }, + 'enableSpotlight': false, + 'spotlightUrl': null, }); }); @@ -118,7 +120,9 @@ void main() { pass: '0000', ) ..experimental.replay.sessionSampleRate = 0.1 - ..experimental.replay.onErrorSampleRate = 0.2; + ..experimental.replay.onErrorSampleRate = 0.2 + ..spotlight = + Spotlight(enabled: true, url: 'http://localhost:8969/stream'); fixture.options.sdk.addIntegration('foo'); fixture.options.sdk.addPackage('bar', '1'); @@ -174,6 +178,8 @@ void main() { 'sessionSampleRate': 0.1, 'onErrorSampleRate': 0.2, }, + 'enableSpotlight': true, + 'spotlightUrl': 'http://localhost:8969/stream', }); }); }