@@ -11,24 +11,48 @@ import 'version.dart';
11
11
class LoggingIntegration implements Integration <SentryOptions > {
12
12
/// Creates the [LoggingIntegration] .
13
13
///
14
- /// All log events equal or higher than [minBreadcrumbLevel] are recorded as a
14
+ /// - All log events equal or higher than [minBreadcrumbLevel] are recorded as a
15
15
/// [Breadcrumb] .
16
- /// All log events equal or higher than [minEventLevel] are recorded as a
16
+ /// - All log events equal or higher than [minEventLevel] are recorded as a
17
17
/// [SentryEvent] .
18
+ /// - All log events equal or higher than [minSentryLogLevel] are logged to
19
+ /// Sentry, if [SentryOptions.enableLogs] is true.
20
+ ///
21
+ /// Log levels are mapped to the following Sentry log levels methods:
22
+ ///
23
+ /// | Dart Log Level | Sentry Log Level |
24
+ /// |-----------------------|------------------|
25
+ /// | SHOUT, SEVERE | error |
26
+ /// | WARNING | warn |
27
+ /// | INFO | info |
28
+ /// | CONFIG, FINE, ALL | debug |
29
+ /// | FINER, FINEST | trace |
30
+ ///
31
+ /// Custom log levels are mapped based on their numeric values:
32
+ /// - >= 1000 → error
33
+ /// - >= 900 → warn
34
+ /// - >= 800 → info
35
+ /// - >= 700 || 500 || 0 → debug
36
+ /// - < 700 → trace
18
37
LoggingIntegration ({
19
38
Level minBreadcrumbLevel = Level .INFO ,
20
39
Level minEventLevel = Level .SEVERE ,
40
+ Level minSentryLogLevel = Level .INFO ,
21
41
}) : _minBreadcrumbLevel = minBreadcrumbLevel,
22
- _minEventLevel = minEventLevel;
42
+ _minEventLevel = minEventLevel,
43
+ _minSentryLogLevel = minSentryLogLevel;
23
44
24
45
final Level _minBreadcrumbLevel;
25
46
final Level _minEventLevel;
47
+ final Level _minSentryLogLevel;
26
48
late StreamSubscription <LogRecord > _subscription;
27
49
late Hub _hub;
50
+ late SentryOptions _options;
28
51
29
52
@override
30
53
void call (Hub hub, SentryOptions options) {
31
54
_hub = hub;
55
+ _options = options;
32
56
_subscription = Logger .root.onRecord.listen (
33
57
_onLog,
34
58
onError: (Object error, StackTrace stackTrace) async {
@@ -68,5 +92,34 @@ class LoggingIntegration implements Integration<SentryOptions> {
68
92
hint: Hint .withMap ({TypeCheckHint .record: record}),
69
93
);
70
94
}
95
+
96
+ if (_options.enableLogs && _isLoggable (record.level, _minSentryLogLevel)) {
97
+ final attributes = {
98
+ 'loggerName' : SentryLogAttribute .string (record.loggerName),
99
+ 'sequenceNumber' : SentryLogAttribute .int (record.sequenceNumber),
100
+ 'time' : SentryLogAttribute .int (record.time.millisecondsSinceEpoch),
101
+ };
102
+
103
+ // Map log levels based on value ranges
104
+ final levelValue = record.level.value;
105
+ if (levelValue >= Level .SEVERE .value) {
106
+ // >= 1000 → error
107
+ await _options.logger.error (record.message, attributes: attributes);
108
+ } else if (levelValue >= Level .WARNING .value) {
109
+ // >= 900 → warn
110
+ await _options.logger.warn (record.message, attributes: attributes);
111
+ } else if (levelValue >= Level .INFO .value) {
112
+ // >= 800 → info
113
+ await _options.logger.info (record.message, attributes: attributes);
114
+ } else if (levelValue >= Level .CONFIG .value ||
115
+ levelValue == Level .FINE .value ||
116
+ levelValue == Level .ALL .value) {
117
+ // >= 700 || 500 || 0 → debug
118
+ await _options.logger.debug (record.message, attributes: attributes);
119
+ } else {
120
+ // < 700 → trace
121
+ await _options.logger.trace (record.message, attributes: attributes);
122
+ }
123
+ }
71
124
}
72
125
}
0 commit comments