Skip to content

Commit bbdbcb9

Browse files
authored
feat: add setAttributes and removeAttribute (#3352)
* Add setAttributeS * Update * Update * Add removeAttribute * Add scope test * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Update * Merge scope * Update * Fix analyzer * Fix analyzer
1 parent 3ddf010 commit bbdbcb9

34 files changed

+478
-161
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- Add `Sentry.setAttributes` and `Sentry.removeAttribute` ([#3352](https://github.com/getsentry/sentry-dart/pull/3352))
8+
- These attributes are set at the scope level and apply to all logs (and later to metrics and spans).
9+
- When a scope attribute conflicts with a log-level attribute, the log-level attribute always takes precedence.
10+
511
### Fixes
612

713
- Android app crashing on hot-restart in debug mode ([#3358](https://github.com/getsentry/sentry-dart/pull/3358))

packages/dart/lib/src/hub.dart

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ class Hub {
289289
if (!_isEnabled) {
290290
_options.log(
291291
SentryLevel.warning,
292-
"Instance is disabled and this 'captureFeedback' call is a no-op.",
292+
"Instance is disabled and this 'captureLog' call is a no-op.",
293293
);
294294
} else {
295295
final item = _peek();
@@ -341,7 +341,31 @@ class Hub {
341341
return scope;
342342
}
343343

344-
/// Adds a breacrumb to the current Scope
344+
void setAttributes(Map<String, SentryAttribute> attributes) {
345+
if (!_isEnabled) {
346+
_options.log(
347+
SentryLevel.warning,
348+
"Instance is disabled and this 'setAttributes' call is a no-op.",
349+
);
350+
} else {
351+
final item = _peek();
352+
item.scope.setAttributes(attributes);
353+
}
354+
}
355+
356+
void removeAttribute(String key) {
357+
if (!_isEnabled) {
358+
_options.log(
359+
SentryLevel.warning,
360+
"Instance is disabled and this 'removeAttribute' call is a no-op.",
361+
);
362+
} else {
363+
final item = _peek();
364+
item.scope.removeAttribute(key);
365+
}
366+
}
367+
368+
/// Adds a breadcrumb to the current Scope
345369
Future<void> addBreadcrumb(Breadcrumb crumb, {Hint? hint}) async {
346370
if (!_isEnabled) {
347371
_options.log(

packages/dart/lib/src/hub_adapter.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,11 @@ class HubAdapter implements Hub {
199199

200200
@override
201201
FutureOr<void> captureLog(SentryLog log) => Sentry.currentHub.captureLog(log);
202+
203+
@override
204+
void setAttributes(Map<String, SentryAttribute> attributes) =>
205+
Sentry.currentHub.setAttributes(attributes);
206+
207+
@override
208+
void removeAttribute(String key) => Sentry.currentHub.removeAttribute(key);
202209
}

packages/dart/lib/src/logs_enricher_integration.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'sdk_lifecycle_hooks.dart';
55
import 'utils/os_utils.dart';
66
import 'integration.dart';
77
import 'hub.dart';
8-
import 'protocol/sentry_log_attribute.dart';
8+
import 'protocol/sentry_attribute.dart';
99
import 'sentry_options.dart';
1010

1111
@internal
@@ -20,12 +20,12 @@ class LogsEnricherIntegration extends Integration<SentryOptions> {
2020
final os = getSentryOperatingSystem();
2121

2222
if (os.name != null) {
23-
event.log.attributes['os.name'] = SentryLogAttribute.string(
23+
event.log.attributes['os.name'] = SentryAttribute.string(
2424
os.name ?? '',
2525
);
2626
}
2727
if (os.version != null) {
28-
event.log.attributes['os.version'] = SentryLogAttribute.string(
28+
event.log.attributes['os.version'] = SentryAttribute.string(
2929
os.version ?? '',
3030
);
3131
}

packages/dart/lib/src/noop_hub.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,10 @@ class NoOpHub implements Hub {
144144

145145
@override
146146
Scope get scope => Scope(_options);
147+
148+
@override
149+
void setAttributes(Map<String, SentryAttribute> attributes) {}
150+
151+
@override
152+
void removeAttribute(String key) {}
147153
}

packages/dart/lib/src/protocol.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@ export 'protocol/sentry_feature_flag.dart';
4343
export 'protocol/sentry_feature_flags.dart';
4444
export 'protocol/sentry_log.dart';
4545
export 'protocol/sentry_log_level.dart';
46-
export 'protocol/sentry_log_attribute.dart';
46+
export 'protocol/sentry_attribute.dart';
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import 'package:meta/meta.dart';
2+
3+
@Deprecated('Use SentryAttribute instead')
4+
class SentryLogAttribute extends SentryAttribute {
5+
SentryLogAttribute._(super.value, super.type);
6+
7+
factory SentryLogAttribute.string(String value) {
8+
return SentryLogAttribute._(value, 'string');
9+
}
10+
11+
factory SentryLogAttribute.bool(bool value) {
12+
return SentryLogAttribute._(value, 'boolean');
13+
}
14+
15+
factory SentryLogAttribute.int(int value) {
16+
return SentryLogAttribute._(value, 'integer');
17+
}
18+
19+
factory SentryLogAttribute.double(double value) {
20+
return SentryLogAttribute._(value, 'double');
21+
}
22+
}
23+
24+
class SentryAttribute {
25+
@internal
26+
final String type;
27+
final dynamic value;
28+
29+
@internal
30+
SentryAttribute(this.value, this.type);
31+
32+
factory SentryAttribute.string(String value) {
33+
return SentryAttribute(value, 'string');
34+
}
35+
36+
factory SentryAttribute.bool(bool value) {
37+
return SentryAttribute(value, 'boolean');
38+
}
39+
40+
factory SentryAttribute.int(int value) {
41+
return SentryAttribute(value, 'integer');
42+
}
43+
44+
factory SentryAttribute.double(double value) {
45+
return SentryAttribute(value, 'double');
46+
}
47+
48+
Map<String, dynamic> toJson() {
49+
return {
50+
'value': value,
51+
'type': type,
52+
};
53+
}
54+
}

packages/dart/lib/src/protocol/sentry_log.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1+
import 'sentry_attribute.dart';
12
import 'sentry_id.dart';
23
import 'sentry_log_level.dart';
3-
import 'sentry_log_attribute.dart';
44

55
class SentryLog {
66
DateTime timestamp;
77
SentryId traceId;
88
SentryLogLevel level;
99
String body;
10-
Map<String, SentryLogAttribute> attributes;
10+
Map<String, SentryAttribute> attributes;
1111
int? severityNumber;
1212

1313
/// The traceId is initially an empty default value and is populated during event processing;

packages/dart/lib/src/protocol/sentry_log_attribute.dart

Lines changed: 0 additions & 30 deletions
This file was deleted.

packages/dart/lib/src/scope.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ class Scope {
167167

168168
List<SentryAttachment> get attachments => List.unmodifiable(_attachments);
169169

170+
final Map<String, SentryAttribute> _attributes = {};
171+
172+
Map<String, SentryAttribute> get attributes => Map.unmodifiable(_attributes);
173+
170174
Scope(this._options);
171175

172176
Breadcrumb? _addBreadCrumbSync(Breadcrumb breadcrumb, Hint hint) {
@@ -222,6 +226,16 @@ class Scope {
222226
}
223227
}
224228

229+
void setAttributes(Map<String, SentryAttribute> attributes) {
230+
attributes.forEach((key, value) {
231+
_attributes[key] = value;
232+
});
233+
}
234+
235+
void removeAttribute(String key) {
236+
_attributes.remove(key);
237+
}
238+
225239
void addAttachment(SentryAttachment attachment) {
226240
_attachments.add(attachment);
227241
}
@@ -258,6 +272,7 @@ class Scope {
258272
_eventProcessors.clear();
259273
_replayId = null;
260274
propagationContext = PropagationContext();
275+
_attributes.clear();
261276

262277
_clearBreadcrumbsSync();
263278
_setUserSync(null);
@@ -461,6 +476,10 @@ class Scope {
461476
clone.addAttachment(attachment);
462477
}
463478

479+
if (_attributes.isNotEmpty) {
480+
clone.setAttributes(Map.from(_attributes));
481+
}
482+
464483
return clone;
465484
}
466485

0 commit comments

Comments
 (0)