diff --git a/CHANGELOG.md b/CHANGELOG.md index c1148c4570..4917265a24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,9 @@ - Added Scope and Breadcrumb ring buffer #109 - Added Hub to SDK #113 - Ref: Hub passes the Scope to SentryClient -- Feat: sentry options #116 +- Feature: sentry options #116 - Ref: SentryId generates UUID +- Ref: Event now is SentryEvent and added GPU # `package:sentry` changelog diff --git a/dart/example/event_example.dart b/dart/example/event_example.dart index d4a64dc64f..a02c92a9b3 100644 --- a/dart/example/event_example.dart +++ b/dart/example/event_example.dart @@ -1,7 +1,7 @@ import 'package:sentry/src/protocol.dart'; -final event = Event( - loggerName: 'main', +final event = SentryEvent( + logger: 'main', serverName: 'server.dart', release: '1.4.0-preview.1', environment: 'Test', diff --git a/dart/lib/src/browser_client.dart b/dart/lib/src/browser_client.dart index 25ccfd8374..b34c862e9d 100644 --- a/dart/lib/src/browser_client.dart +++ b/dart/lib/src/browser_client.dart @@ -11,7 +11,6 @@ import 'package:http/browser_client.dart'; import 'client.dart'; import 'protocol.dart'; import 'sentry_options.dart'; -import 'utils.dart'; import 'version.dart'; SentryClient createSentryClient(SentryOptions options) => @@ -29,15 +28,8 @@ class SentryBrowserClient extends SentryClient { /// /// If [httpClient] is provided, it is used instead of the default client to /// make HTTP calls to Sentry.io. This is useful in tests. - /// - /// If [clock] is provided, it is used to get time instead of the system - /// clock. This is useful in tests. Should be an implementation of [ClockProvider]. - /// This parameter is dynamic to maintain backwards compatibility with - /// previous use of [Clock](https://pub.dartlang.org/documentation/quiver/latest/quiver.time/Clock-class.html) - /// from [`package:quiver`](https://pub.dartlang.org/packages/quiver). factory SentryBrowserClient(SentryOptions options, {String origin}) { options.httpClient ??= BrowserClient(); - options.clock ??= getUtcDateTime; // origin is necessary for sentry to resolve stacktrace origin ??= '${window.location.origin}/'; diff --git a/dart/lib/src/client.dart b/dart/lib/src/client.dart index 32ad24678e..12ff28b3b1 100644 --- a/dart/lib/src/client.dart +++ b/dart/lib/src/client.dart @@ -12,9 +12,6 @@ import 'stack_trace.dart'; import 'utils.dart'; import 'version.dart'; -/// Used to provide timestamp for logging. -typedef ClockProvider = DateTime Function(); - /// Logs crash reports and events to the Sentry.io service. abstract class SentryClient { /// Creates a new platform appropriate client. @@ -30,15 +27,7 @@ abstract class SentryClient { Sdk sdk, }) : _dsn = Dsn.parse(options.dsn), _platform = platform ?? sdkPlatform, - sdk = sdk ?? Sdk(name: sdkName, version: sdkVersion) { - if (options.clock == null) { - options.clock = getUtcDateTime; - } else { - options.clock = (options.clock is ClockProvider - ? options.clock - : options.clock.get) as ClockProvider; - } - } + sdk = sdk ?? Sdk(name: sdkName, version: sdkVersion); final Dsn _dsn; @@ -107,7 +96,7 @@ abstract class SentryClient { /// Reports an [event] to Sentry.io. Future captureEvent( - Event event, { + SentryEvent event, { StackFrameFilter stackFrameFilter, Scope scope, }) async { @@ -123,7 +112,7 @@ abstract class SentryClient { final data = { 'project': projectId, 'event_id': event.eventId.toString(), - 'timestamp': formatDateAsIso8601WithSecondPrecision(now), + 'timestamp': formatDateAsIso8601WithSecondPrecision(event.timestamp), }; if (options.environmentAttributes != null) { @@ -162,11 +151,15 @@ abstract class SentryClient { } /// Reports the [throwable] and optionally its [stackTrace] to Sentry.io. - Future captureException(dynamic throwable, - {dynamic stackTrace, Scope scope}) { - final event = Event( + Future captureException( + dynamic throwable, { + dynamic stackTrace, + Scope scope, + }) { + final event = SentryEvent( exception: throwable, stackTrace: stackTrace, + timestamp: options.clock(), ); return captureEvent(event, scope: scope); } @@ -179,9 +172,14 @@ abstract class SentryClient { List params, Scope scope, }) { - final event = Event( - message: Message(formatted, template: template, params: params), + final event = SentryEvent( + message: Message( + formatted, + template: template, + params: params, + ), level: level, + timestamp: options.clock(), ); return captureEvent(event, scope: scope); } diff --git a/dart/lib/src/hub.dart b/dart/lib/src/hub.dart index e71190e2c5..a93b09aa71 100644 --- a/dart/lib/src/hub.dart +++ b/dart/lib/src/hub.dart @@ -54,7 +54,7 @@ class Hub { SentryId get lastEventId => _lastEventId; /// Captures the event. - Future captureEvent(Event event) async { + Future captureEvent(SentryEvent event) async { var sentryId = SentryId.empty(); if (!_isEnabled) { diff --git a/dart/lib/src/io_client.dart b/dart/lib/src/io_client.dart index 0e342dd685..a7f5d59297 100644 --- a/dart/lib/src/io_client.dart +++ b/dart/lib/src/io_client.dart @@ -9,7 +9,6 @@ import 'dart:io'; import 'package:sentry/sentry.dart'; import 'client.dart'; -import 'protocol.dart'; SentryClient createSentryClient(SentryOptions options) => SentryIOClient(options); @@ -30,12 +29,6 @@ class SentryIOClient extends SentryClient { /// /// If [httpClient] is provided, it is used instead of the default client to /// make HTTP calls to Sentry.io. This is useful in tests. - /// - /// If [clock] is provided, it is used to get time instead of the system - /// clock. This is useful in tests. Should be an implementation of [ClockProvider]. - /// This parameter is dynamic to maintain backwards compatibility with - /// previous use of [Clock](https://pub.dartlang.org/documentation/quiver/latest/quiver.time/Clock-class.html) - /// from [`package:quiver`](https://pub.dartlang.org/packages/quiver). factory SentryIOClient(SentryOptions options) => SentryIOClient._(options); SentryIOClient._(SentryOptions options) : super.base(options); diff --git a/dart/lib/src/noop_client.dart b/dart/lib/src/noop_client.dart index 8f7f3a4fcc..c5f5c7d438 100644 --- a/dart/lib/src/noop_client.dart +++ b/dart/lib/src/noop_client.dart @@ -34,7 +34,7 @@ class NoOpSentryClient implements SentryClient { Map buildHeaders(String authHeader) => {}; @override - Future captureEvent(Event event, {stackFrameFilter, scope}) => + Future captureEvent(SentryEvent event, {stackFrameFilter, scope}) => Future.value(SentryId.empty()); @override diff --git a/dart/lib/src/noop_hub.dart b/dart/lib/src/noop_hub.dart index 2c479c4492..30dbb422fe 100644 --- a/dart/lib/src/noop_hub.dart +++ b/dart/lib/src/noop_hub.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'client.dart'; import 'hub.dart'; -import 'protocol/event.dart'; +import 'protocol/sentry_event.dart'; import 'protocol/sentry_level.dart'; import 'protocol/sentry_id.dart'; @@ -19,7 +19,8 @@ class NoOpHub implements Hub { void bindClient(SentryClient client) {} @override - Future captureEvent(Event event) => Future.value(SentryId.empty()); + Future captureEvent(SentryEvent event) => + Future.value(SentryId.empty()); @override Future captureException(throwable, {stackTrace}) => diff --git a/dart/lib/src/protocol.dart b/dart/lib/src/protocol.dart index 2aa0d3a3c8..bbf63dda97 100644 --- a/dart/lib/src/protocol.dart +++ b/dart/lib/src/protocol.dart @@ -4,7 +4,7 @@ export 'protocol/browser.dart'; export 'protocol/contexts.dart'; export 'protocol/device.dart'; export 'protocol/dsn.dart'; -export 'protocol/event.dart'; +export 'protocol/sentry_event.dart'; export 'protocol/sentry_level.dart'; export 'protocol/message.dart'; export 'protocol/package.dart'; diff --git a/dart/lib/src/protocol/contexts.dart b/dart/lib/src/protocol/contexts.dart index 898aef185d..2f1cdb5cdc 100644 --- a/dart/lib/src/protocol/contexts.dart +++ b/dart/lib/src/protocol/contexts.dart @@ -2,6 +2,7 @@ import '../protocol.dart'; import 'app.dart'; import 'browser.dart'; import 'device.dart'; +import 'gpu.dart'; import 'runtime.dart'; /// The context interfaces provide additional context data. @@ -17,6 +18,7 @@ class Contexts { this.runtimes, this.app, this.browser, + this.gpu, }); /// This describes the device that caused the event. @@ -48,6 +50,11 @@ class Contexts { /// agent of a web request that triggered the event. final Browser browser; + /// GPU context describes the GPU of the device. + final Gpu gpu; + + // TODO: contexts should accept arbitrary values + /// Produces a [Map] that can be serialized to JSON. Map toJson() { final json = {}; @@ -73,6 +80,11 @@ class Contexts { json['browser'] = browserMap; } + Map gpuMap; + if (gpu != null && (gpuMap = gpu.toJson()).isNotEmpty) { + json['gpu'] = gpuMap; + } + if (runtimes != null) { if (runtimes.length == 1) { final runtime = runtimes[0]; diff --git a/dart/lib/src/protocol/gpu.dart b/dart/lib/src/protocol/gpu.dart new file mode 100644 index 0000000000..c88600b753 --- /dev/null +++ b/dart/lib/src/protocol/gpu.dart @@ -0,0 +1,95 @@ +// https://develop.sentry.dev/sdk/event-payloads/contexts/#gpu-context +// Example: +// "gpu": { +// "name": "AMD Radeon Pro 560", +// "vendor_name": "Apple", +// "memory_size": 4096, +// "api_type": "Metal", +// "multi_threaded_rendering": true, +// "version": "Metal", +// "npot_support": "Full" +// } + +class Gpu { + /// The name of the graphics device. + final String name; + + /// The PCI identifier of the graphics device. + final int id; + + /// The PCI vendor identifier of the graphics device. + final int vendorId; + + /// The vendor name as reported by the graphics device. + final String vendorName; + + /// The total GPU memory available in Megabytes. + final int memorySize; + + /// The device low-level API type. + final String apiType; + + /// Whether the GPU has multi-threaded rendering or not. + final bool multiThreadedRendering; + + /// The Version of the graphics device. + final String version; + + /// The Non-Power-Of-Two-Support support. + final String npotSupport; + + const Gpu({ + this.name, + this.id, + this.vendorId, + this.vendorName, + this.memorySize, + this.apiType, + this.multiThreadedRendering, + this.version, + this.npotSupport, + }); + + /// Produces a [Map] that can be serialized to JSON. + Map toJson() { + final json = {}; + + if (name != null) { + json['name'] = name; + } + + if (id != null) { + json['id'] = id; + } + + if (vendorId != null) { + json['vendor_id'] = vendorId; + } + + if (vendorName != null) { + json['vendor_name'] = vendorName; + } + + if (memorySize != null) { + json['memory_size'] = memorySize; + } + + if (apiType != null) { + json['api_type'] = apiType; + } + + if (multiThreadedRendering != null) { + json['multi_threaded_rendering'] = multiThreadedRendering; + } + + if (version != null) { + json['version'] = version; + } + + if (npotSupport != null) { + json['npot_support'] = npotSupport; + } + + return json; + } +} diff --git a/dart/lib/src/protocol/event.dart b/dart/lib/src/protocol/sentry_event.dart similarity index 79% rename from dart/lib/src/protocol/event.dart rename to dart/lib/src/protocol/sentry_event.dart index ee4b3403d7..142ce218d2 100644 --- a/dart/lib/src/protocol/event.dart +++ b/dart/lib/src/protocol/sentry_event.dart @@ -2,18 +2,23 @@ import 'package:meta/meta.dart'; import '../protocol.dart'; import '../stack_trace.dart'; +import '../utils.dart'; import '../version.dart'; /// An event to be reported to Sentry.io. @immutable -class Event { +class SentryEvent { /// Creates an event. - Event({ + SentryEvent({ SentryId eventId, - this.loggerName, + DateTime timestamp, + String platform, + this.logger, this.serverName, this.release, + this.dist, this.environment, + this.modules, this.message, this.transaction, this.exception, @@ -27,7 +32,9 @@ class Event { this.contexts, this.breadcrumbs, this.sdk, - }) : eventId = eventId ?? SentryId.newId(); + }) : eventId = eventId ?? SentryId.newId(), + platform = platform ?? sdkPlatform, + timestamp = timestamp ?? getUtcDateTime(); /// Refers to the default fingerprinting algorithm. /// @@ -38,8 +45,14 @@ class Event { /// The ID Sentry.io assigned to the submitted event for future reference. final SentryId eventId; + /// A timestamp representing when the breadcrumb occurred. + final DateTime timestamp; + + /// A string representing the platform the SDK is submitting from. This will be used by the Sentry interface to customize various components in the interface. + final String platform; + /// The logger that logged the event. - final String loggerName; + final String logger; /// Identifies the server that logged this event. final String serverName; @@ -47,9 +60,15 @@ class Event { /// The version of the application that logged the event. final String release; + /// The distribution of the application. + final String dist; + /// The environment that logged the event, e.g. "production", "staging". final String environment; + /// A list of relevant modules and their versions. + final Map modules; + /// Event message. /// /// Generally an event either contains a [message] or an [exception]. @@ -118,14 +137,22 @@ class Event { /// var supplemented = [Event.defaultFingerprint, 'foo']; final List fingerprint; + /// The SDK Interface describes the Sentry SDK and its configuration used to capture and transmit an event. final Sdk sdk; - Event copyWith({ + // TODO: Request and DebugMeta Interface + // TODO: do we need a Threads interface? + + SentryEvent copyWith({ SentryId eventId, - String loggerName, + DateTime timestamp, + String platform, + String logger, String serverName, String release, + String dist, String environment, + Map modules, Message message, String transaction, dynamic exception, @@ -140,12 +167,16 @@ class Event { List breadcrumbs, Sdk sdk, }) => - Event( + SentryEvent( eventId: eventId ?? this.eventId, - loggerName: loggerName ?? this.loggerName, + timestamp: timestamp ?? this.timestamp, + platform: platform ?? this.platform, + logger: logger ?? this.logger, serverName: serverName ?? this.serverName, release: release ?? this.release, + dist: dist ?? this.dist, environment: environment ?? this.environment, + modules: modules ?? this.modules, message: message ?? this.message, transaction: transaction ?? this.transaction, exception: exception ?? this.exception, @@ -164,16 +195,22 @@ class Event { /// Serializes this event to JSON. Map toJson( {StackFrameFilter stackFrameFilter, String origin}) { - final json = { - 'platform': sdkPlatform, - }; + final json = {}; if (eventId != null) { json['event_id'] = eventId.toString(); } - if (loggerName != null) { - json['logger'] = loggerName; + if (timestamp != null) { + json['timestamp'] = formatDateAsIso8601WithSecondPrecision(timestamp); + } + + if (platform != null) { + json['platform'] = platform; + } + + if (logger != null) { + json['logger'] = logger; } if (serverName != null) { @@ -184,10 +221,18 @@ class Event { json['release'] = release; } + if (dist != null) { + json['dist'] = dist; + } + if (environment != null) { json['environment'] = environment; } + if (modules != null && modules.isNotEmpty) { + json['modules'] = modules; + } + if (message != null) { json['message'] = message.toJson(); } @@ -197,6 +242,7 @@ class Event { } if (exception != null) { + // TODO: create Exception and Mechanism Interface class json['exception'] = [ { 'type': '${exception.runtimeType}', @@ -204,6 +250,7 @@ class Event { } ]; if (exception is Error && exception.stackTrace != null) { + // TODO: create Stack Trace and Frame Interface json['stacktrace'] = { 'frames': encodeStackTrace( exception.stackTrace, diff --git a/dart/lib/src/sentry.dart b/dart/lib/src/sentry.dart index 23a8ea6580..3778b56b3d 100644 --- a/dart/lib/src/sentry.dart +++ b/dart/lib/src/sentry.dart @@ -45,7 +45,7 @@ class Sentry { } /// Reports an [event] to Sentry.io. - static Future captureEvent(Event event) async { + static Future captureEvent(SentryEvent event) async { return currentHub.captureEvent(event); } diff --git a/dart/lib/src/sentry_options.dart b/dart/lib/src/sentry_options.dart index 154145b6a5..58a8ccb725 100644 --- a/dart/lib/src/sentry_options.dart +++ b/dart/lib/src/sentry_options.dart @@ -3,6 +3,7 @@ import 'package:sentry/sentry.dart'; import 'diagnostic_logger.dart'; import 'hub.dart'; import 'protocol.dart'; +import 'utils.dart'; /// Sentry SDK options class SentryOptions { @@ -20,7 +21,7 @@ class SentryOptions { /// event to event, such as local operating system version, the version of /// Dart/Flutter SDK, etc. These attributes have lower precedence than those /// supplied in the even passed to [capture]. - Event environmentAttributes; + SentryEvent environmentAttributes; /// If [compressPayload] is `true` the outgoing HTTP payloads are compressed /// using gzip. Otherwise, the payloads are sent in plain UTF8-encoded JSON @@ -33,12 +34,12 @@ class SentryOptions { /// If [clock] is provided, it is used to get time instead of the system /// clock. This is useful in tests. Should be an implementation of [ClockProvider]. - /// This parameter is dynamic to maintain backwards compatibility with - /// previous use of [Clock](https://pub.dartlang.org/documentation/quiver/latest/quiver.time/Clock-class.html) - /// from [`package:quiver`](https://pub.dartlang.org/packages/quiver). - dynamic clock; + ClockProvider _clock; - int maxBreadcrumbs; + ClockProvider get clock => _clock; + + /// This variable controls the total amount of breadcrumbs that should be captured Default is 100 + int maxBreadcrumbs = 100; /// Logger interface to log useful debugging information if debug is enabled Logger _logger = noOpLogger; @@ -138,8 +139,10 @@ class SentryOptions { this.environmentAttributes, this.compressPayload, this.httpClient, - this.clock, - }); + ClockProvider clock = getUtcDateTime, + }) { + _clock = clock; + } /// Adds an event processor void addEventProcessor(EventProcessor eventProcessor) { @@ -172,19 +175,23 @@ class SentryOptions { } } -typedef BeforeSendCallback = Event Function(Event event, dynamic hint); +typedef BeforeSendCallback = SentryEvent Function( + SentryEvent event, dynamic hint); typedef BeforeBreadcrumbCallback = Breadcrumb Function( Breadcrumb breadcrumb, dynamic hint, ); -typedef EventProcessor = Event Function(Event event, dynamic hint); +typedef EventProcessor = SentryEvent Function(SentryEvent event, dynamic hint); typedef Integration = Function(Hub hub, SentryOptions options); typedef Logger = Function(SentryLevel level, String message); +/// Used to provide timestamp for logging. +typedef ClockProvider = DateTime Function(); + void noOpLogger(SentryLevel level, String message) {} void dartLogger(SentryLevel level, String message) { diff --git a/dart/test/contexts_test.dart b/dart/test/contexts_test.dart index 042c2a8125..87ed57ed90 100644 --- a/dart/test/contexts_test.dart +++ b/dart/test/contexts_test.dart @@ -52,7 +52,7 @@ void main() { browser: testBrowser, ); - final event = Event(contexts: contexts); + final event = SentryEvent(contexts: contexts); expect( event.toJson()['contexts'], diff --git a/dart/test/event_test.dart b/dart/test/event_test.dart index a4a7447a57..b9ed7b73e1 100644 --- a/dart/test/event_test.dart +++ b/dart/test/event_test.dart @@ -7,7 +7,7 @@ import 'package:sentry/src/stack_trace.dart'; import 'package:test/test.dart'; void main() { - group(Event, () { + group(SentryEvent, () { test('$Breadcrumb serializes', () { expect( Breadcrumb( @@ -25,8 +25,9 @@ void main() { ); }); test('$Sdk serializes', () { - final event = Event( + final event = SentryEvent( eventId: SentryId.empty(), + timestamp: DateTime.utc(2019), sdk: Sdk( name: 'sentry.dart.flutter', version: '4.3.2', @@ -35,6 +36,7 @@ void main() { expect(event.toJson(), { 'platform': 'dart', 'event_id': '00000000000000000000000000000000', + 'timestamp': '2019-01-01T00:00:00', 'sdk': { 'name': 'sentry.dart.flutter', 'version': '4.3.2', @@ -46,6 +48,7 @@ void main() { }); }); test('serializes to JSON', () { + final timestamp = DateTime.utc(2019); const user = User( id: 'user_id', username: 'username', @@ -54,15 +57,16 @@ void main() { extras: {'foo': 'bar'}); final breadcrumbs = [ - Breadcrumb('test log', DateTime.utc(2019), + Breadcrumb('test log', timestamp, level: SentryLevel.debug, category: 'test'), ]; final error = StateError('test-error'); expect( - Event( + SentryEvent( eventId: SentryId.empty(), + timestamp: timestamp, message: Message( 'test-message 1 2', template: 'test-message %d %d', @@ -80,13 +84,14 @@ void main() { 'e': 'f', 'g': 2, }, - fingerprint: const [Event.defaultFingerprint, 'foo'], + fingerprint: const [SentryEvent.defaultFingerprint, 'foo'], userContext: user, breadcrumbs: breadcrumbs, ).toJson(), { 'platform': 'dart', 'event_id': '00000000000000000000000000000000', + 'timestamp': '2019-01-01T00:00:00', 'sdk': {'version': sdkVersion, 'name': 'sentry.dart'}, 'message': { 'formatted': 'test-message 1 2', diff --git a/dart/test/mocks.dart b/dart/test/mocks.dart index b5a4c44b5d..e50a8f0abf 100644 --- a/dart/test/mocks.dart +++ b/dart/test/mocks.dart @@ -12,8 +12,8 @@ final fakeMessage = Message('message 1', template: 'message %d', params: ['1']); final fakeUser = User(id: '1', email: 'test@test'); -final fakeEvent = Event( - loggerName: 'main', +final fakeEvent = SentryEvent( + logger: 'main', serverName: 'server.dart', release: '1.4.0-preview.1', environment: 'Test', diff --git a/dart/test/test_utils.dart b/dart/test/test_utils.dart index 50182c6e4b..1ffd29a6cc 100644 --- a/dart/test/test_utils.dart +++ b/dart/test/test_utils.dart @@ -76,7 +76,7 @@ Future testCaptureException( httpClient: httpMock, clock: fakeClockProvider, compressPayload: compressPayload, - environmentAttributes: Event( + environmentAttributes: SentryEvent( serverName: 'test.server.com', release: '1.2.3', environment: 'staging', @@ -238,7 +238,7 @@ void runTest({Codec, List> gzip, bool isWeb = false}) { httpClient: httpMock, clock: fakeClockProvider, compressPayload: false, - environmentAttributes: Event( + environmentAttributes: SentryEvent( serverName: 'test.server.com', release: '1.2.3', environment: 'staging', @@ -295,7 +295,7 @@ void runTest({Codec, List> gzip, bool isWeb = false}) { httpClient: httpMock, clock: fakeClockProvider, compressPayload: false, - environmentAttributes: Event( + environmentAttributes: SentryEvent( serverName: 'test.server.com', release: '1.2.3', environment: 'staging', @@ -314,7 +314,7 @@ void runTest({Codec, List> gzip, bool isWeb = false}) { await client.close(); }); - test('$Event userContext overrides client', () async { + test('$SentryEvent userContext overrides client', () async { final fakeClockProvider = () => DateTime.utc(2017, 1, 2); String loggedUserId; // used to find out what user context was sent @@ -350,7 +350,7 @@ void runTest({Codec, List> gzip, bool isWeb = false}) { httpClient: httpMock, clock: fakeClockProvider, compressPayload: false, - environmentAttributes: Event( + environmentAttributes: SentryEvent( serverName: 'test.server.com', release: '1.2.3', environment: 'staging', @@ -362,12 +362,12 @@ void runTest({Codec, List> gzip, bool isWeb = false}) { try { throw ArgumentError('Test error'); } catch (error, stackTrace) { - final eventWithoutContext = Event( + final eventWithoutContext = SentryEvent( eventId: SentryId.empty(), exception: error, stackTrace: stackTrace, ); - final eventWithContext = Event( + final eventWithContext = SentryEvent( eventId: SentryId.empty(), exception: error, stackTrace: stackTrace, diff --git a/flutter/example/lib/main.dart b/flutter/example/lib/main.dart index 94b288ce09..4b12dd8ca7 100644 --- a/flutter/example/lib/main.dart +++ b/flutter/example/lib/main.dart @@ -35,7 +35,7 @@ Future main() async { runApp(MyApp()); }, (error, stackTrace) async { print('Capture from runZonedGuarded $error'); - final event = Event( + final event = SentryEvent( exception: error, stackTrace: stackTrace, // release is required on Web to match the source maps