Skip to content
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- Fix: Integrations are executed on Hub creation
- Fix: NoOp encode for Web
- Fix: Breadcrumb data should accept serializable types and not only String values
- Ref: added Scope.applyToEvent

# `package:sentry` changelog

Expand Down
70 changes: 16 additions & 54 deletions dart/lib/src/client.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:math';

import 'package:meta/meta.dart';
import 'package:sentry/sentry.dart';
import 'package:sentry/src/transport/noop_transport.dart';

Expand Down Expand Up @@ -44,20 +43,18 @@ abstract class SentryClient {
return emptyFuture;
}

event = _applyScope(event: event, scope: scope);
if (scope != null) {
event = scope.applyToEvent(event, hint);
} else {
_options.logger(SentryLevel.debug, 'No scope is defined');
}

// dropped by scope event processors
if (event == null) {
return emptyFuture;
}

// TODO create eventProcessors ?
event = event.copyWith(
serverName: _options.serverName,
environment: _options.environment,
release: _options.release,
platform: event.platform ?? sdkPlatform,
);
event = _prepareEvent(event);

if (_options.beforeSendCallback != null) {
try {
Expand All @@ -77,6 +74,16 @@ abstract class SentryClient {
return _options.transport.send(event);
}

SentryEvent _prepareEvent(SentryEvent event) => event.copyWith(
serverName: event.serverName ?? _options.serverName,
dist: event.dist ?? _options.dist,
environment:
event.environment ?? _options.environment ?? defaultEnvironment,
release: event.release ?? _options.release,
sdk: event.sdk ?? _options.sdk,
platform: event.platform ?? sdkPlatform,
);

/// Reports the [throwable] and optionally its [stackTrace] to Sentry.io.
Future<SentryId> captureException(
dynamic throwable, {
Expand Down Expand Up @@ -142,51 +149,6 @@ abstract class SentryClient {
return event;
}

SentryEvent _applyScope({
@required SentryEvent event,
@required Scope scope,
}) {
if (scope != null) {
// Merge the scope transaction.
if (event.transaction == null) {
event = event.copyWith(transaction: scope.transaction);
}

// Merge the user context.
if (event.userContext == null) {
event = event.copyWith(userContext: scope.user);
}

// Merge the scope fingerprint.
if (event.fingerprint == null) {
event = event.copyWith(fingerprint: scope.fingerprint);
}

// Merge the scope breadcrumbs.
if (event.breadcrumbs == null) {
event = event.copyWith(breadcrumbs: scope.breadcrumbs);
}

// Merge the scope tags.
event = event.copyWith(
tags: scope.tags.map((key, value) => MapEntry(key, value))
..addAll(event.tags ?? {}));

// Merge the scope extra.
event = event.copyWith(
extra: scope.extra.map((key, value) => MapEntry(key, value))
..addAll(event.extra ?? {}));

// Merge the scope level.
if (scope.level != null) {
event = event.copyWith(level: scope.level);
}

// TODO: execute scope event processors
}
return event;
}

bool _sampleRate() {
if (_options.sampleRate != null && _random != null) {
return (_options.sampleRate < _random.nextDouble());
Expand Down
5 changes: 2 additions & 3 deletions dart/lib/src/protocol/sentry_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SentryEvent {
SentryEvent({
SentryId eventId,
DateTime timestamp,
Sdk sdk,
this.sdk,
this.platform,
this.logger,
this.serverName,
Expand All @@ -33,8 +33,7 @@ class SentryEvent {
this.contexts,
this.breadcrumbs,
}) : eventId = eventId ?? SentryId.newId(),
timestamp = timestamp ?? getUtcDateTime(),
sdk = sdk ?? Sdk(name: sdkName, version: sdkVersion);
timestamp = timestamp ?? getUtcDateTime();

/// Refers to the default fingerprinting algorithm.
///
Expand Down
40 changes: 40 additions & 0 deletions dart/lib/src/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,46 @@ class Scope {
/// Removes an extra from the Scope
void removeExtra(String key) => _extra.remove(key);

SentryEvent applyToEvent(SentryEvent event, dynamic hint) {
event = event.copyWith(
transaction: event.transaction ?? transaction,
userContext: event.userContext ?? user,
fingerprint: event.fingerprint ?? fingerprint,
breadcrumbs: event.breadcrumbs ?? breadcrumbs,
tags: tags.isNotEmpty ? _mergeEventTags(event) : event.tags,
extra: extra.isNotEmpty ? _mergeEventExtra(event) : event.extra,
level: level ?? event.level,
);

for (final processor in _eventProcessors) {
try {
event = processor(event, hint);
} catch (err) {
_options.logger(
SentryLevel.error,
'An exception occurred while processing event by a processor : $err',
);
}
if (event == null) {
_options.logger(SentryLevel.debug, 'Event was dropped by a processor');
break;
}
}

return event;
}

/// the event tags will be kept
/// if the scope and the event have tag entries with the same key,
Map<String, String> _mergeEventTags(SentryEvent event) =>
tags.map((key, value) => MapEntry(key, value))..addAll(event.tags ?? {});

/// if the scope and the event have extra entries with the same key,
/// the event extra will be kept
Map<String, dynamic> _mergeEventExtra(SentryEvent event) =>
extra.map((key, value) => MapEntry(key, value))
..addAll(event.extra ?? {});

/// Clones the current Scope
Scope clone() {
final clone = Scope(_options)
Expand Down
11 changes: 9 additions & 2 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import 'hub.dart';
import 'protocol.dart';
import 'utils.dart';

const defaultEnvironment = 'production';

/// Sentry SDK options
class SentryOptions {
/// Default Log level if not specified Default is DEBUG
Expand Down Expand Up @@ -98,7 +100,6 @@ class SentryOptions {
/// Sets the release. SDK will try to automatically configure a release out of the box
String release;

// TODO: probably its part of environmentAttributes
/// Sets the environment. This string is freeform and not set by default. A release can be
/// associated with more than one environment to separate them in the UI Think staging vs prod or
/// similar.
Expand Down Expand Up @@ -137,8 +138,14 @@ class SentryOptions {
/// The server name used in the Sentry messages.
String serverName;

Sdk _sdk = Sdk(name: sdkName, version: sdkVersion);

/// Sdk object that contains the Sentry Client Name and its version
Sdk sdk;
Sdk get sdk => _sdk;

set sdk(Sdk sdk) {
_sdk = sdk ?? _sdk;
}

// TODO: Scope observers, enableScopeSync

Expand Down