-
-
Notifications
You must be signed in to change notification settings - Fork 257
Logs: Integrate in Sentry Client #2920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f4f785
20506d4
c5f5d6e
1a2c038
16c4b42
f4ec20b
9bf5514
9cb7821
f50a6ce
3dee73c
6c74691
2b9b62e
ea79978
39f4130
302d22a
9163b43
58bbb6a
bd95978
5050c90
a58b17d
874a4ce
8ed3a83
de3a856
3ad3ff0
345d4f6
74e69d9
87d52e6
b58cd37
969dd3c
1a206f4
58535ae
b7f74b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import 'dart:async'; | ||
|
||
import 'sentry_log_batcher.dart'; | ||
import 'protocol/sentry_log.dart'; | ||
|
||
class NoopLogBatcher implements SentryLogBatcher { | ||
@override | ||
FutureOr<void> addLog(SentryLog log) {} | ||
|
||
@override | ||
Future<void> flush() async {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ import 'type_check_hint.dart'; | |
import 'utils/isolate_utils.dart'; | ||
import 'utils/regex_utils.dart'; | ||
import 'utils/stacktrace_utils.dart'; | ||
import 'sentry_log_batcher.dart'; | ||
import 'version.dart'; | ||
|
||
/// Default value for [SentryUser.ipAddress]. It gets set when an event does not have | ||
|
@@ -75,6 +76,9 @@ class SentryClient { | |
if (enableFlutterSpotlight) { | ||
options.transport = SpotlightHttpTransport(options, options.transport); | ||
} | ||
if (options.enableLogs) { | ||
options.logBatcher = SentryLogBatcher(options); | ||
} | ||
return SentryClient._(options); | ||
} | ||
|
||
|
@@ -485,6 +489,73 @@ class SentryClient { | |
); | ||
} | ||
|
||
@internal | ||
Future<void> captureLog( | ||
buenaflor marked this conversation as resolved.
Show resolved
Hide resolved
|
||
SentryLog log, { | ||
Scope? scope, | ||
}) async { | ||
denrase marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!_options.enableLogs) { | ||
return; | ||
} | ||
|
||
log.attributes['sentry.sdk.name'] = SentryLogAttribute.string( | ||
_options.sdk.name, | ||
); | ||
log.attributes['sentry.sdk.version'] = SentryLogAttribute.string( | ||
_options.sdk.version, | ||
); | ||
buenaflor marked this conversation as resolved.
Show resolved
Hide resolved
|
||
final environment = _options.environment; | ||
if (environment != null) { | ||
log.attributes['sentry.environment'] = SentryLogAttribute.string( | ||
environment, | ||
); | ||
} | ||
final release = _options.release; | ||
if (release != null) { | ||
log.attributes['sentry.release'] = SentryLogAttribute.string( | ||
release, | ||
); | ||
} | ||
|
||
final propagationContext = scope?.propagationContext; | ||
if (propagationContext != null) { | ||
log.traceId = propagationContext.traceId; | ||
} | ||
final span = scope?.span; | ||
if (span != null) { | ||
log.attributes['sentry.trace.parent_span_id'] = SentryLogAttribute.string( | ||
span.context.spanId.toString(), | ||
); | ||
} | ||
|
||
final beforeSendLog = _options.beforeSendLog; | ||
SentryLog? processedLog = log; | ||
if (beforeSendLog != null) { | ||
try { | ||
final callbackResult = beforeSendLog(log); | ||
|
||
if (callbackResult is Future<SentryLog?>) { | ||
processedLog = await callbackResult; | ||
} else { | ||
processedLog = callbackResult; | ||
} | ||
} catch (exception, stackTrace) { | ||
_options.logger( | ||
SentryLevel.error, | ||
'The beforeSendLog callback threw an exception', | ||
exception: exception, | ||
stackTrace: stackTrace, | ||
); | ||
if (_options.automatedTestMode) { | ||
rethrow; | ||
} | ||
} | ||
} | ||
if (processedLog != null) { | ||
_options.logBatcher.addLog(processedLog); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we report a dropped log if null after the |
||
} | ||
|
||
void close() { | ||
_options.httpClient.close(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import 'dart:async'; | ||
import 'sentry_envelope.dart'; | ||
import 'sentry_options.dart'; | ||
import 'protocol/sentry_log.dart'; | ||
import 'package:meta/meta.dart'; | ||
|
||
@internal | ||
class SentryLogBatcher { | ||
SentryLogBatcher(this._options, {Duration? flushTimeout, int? maxBufferSize}) | ||
: _flushTimeout = flushTimeout ?? Duration(seconds: 5), | ||
_maxBufferSize = maxBufferSize ?? 100; | ||
|
||
final SentryOptions _options; | ||
final Duration _flushTimeout; | ||
final int _maxBufferSize; | ||
|
||
final _logBuffer = <SentryLog>[]; | ||
|
||
Timer? _flushTimer; | ||
|
||
void addLog(SentryLog log) { | ||
_logBuffer.add(log); | ||
|
||
_flushTimer?.cancel(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. canceling the timer here means that, in theory, if a log is added every 4 seconds, we will not flush them for several minutes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i guess it's fine as per docs, just ensuring it's wanted |
||
|
||
if (_logBuffer.length >= _maxBufferSize) { | ||
return flush(); | ||
} else { | ||
_flushTimer = Timer(_flushTimeout, flush); | ||
} | ||
} | ||
|
||
void flush() { | ||
_flushTimer?.cancel(); | ||
_flushTimer = null; | ||
|
||
final logs = List<SentryLog>.from(_logBuffer); | ||
_logBuffer.clear(); | ||
|
||
if (logs.isEmpty) { | ||
return; | ||
} | ||
|
||
final envelope = SentryEnvelope.fromLogs( | ||
logs, | ||
_options.sdk, | ||
); | ||
|
||
// TODO: Make sure the Android SDK understands the log envelope type. | ||
_options.transport.send(envelope); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:sentry/src/protocol/sentry_log.dart'; | ||
import 'package:sentry/src/sentry_log_batcher.dart'; | ||
|
||
class MockLogBatcher implements SentryLogBatcher { | ||
final addLogCalls = <SentryLog>[]; | ||
final flushCalls = <void>[]; | ||
|
||
@override | ||
FutureOr<void> addLog(SentryLog log) { | ||
addLogCalls.add(log); | ||
} | ||
|
||
@override | ||
Future<void> flush() async { | ||
flushCalls.add(null); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.