Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
- Add hint for transactions ([#2675](https://github.com/getsentry/sentry-dart/pull/2675))
- `BeforeSendTransactionCallback` now has a `Hint` parameter
- Remove `dart:html` usage in favour of `package:web` ([#2710](https://github.com/getsentry/sentry-dart/pull/2710))

- Remove max response body size ([#2709](https://github.com/getsentry/sentry-dart/pull/2709))
- Responses are now only attached if size is below ~0.15mb
- Responses are attached to the `Hint` object, which can be read in `beforeSend`/`beforeSendTransaction` callbacks via `hint.response`.
- For now, only the `dio` integration is supported.

### Enhancements

- Replay: improve Android native interop performance by using JNI ([#2670](https://github.com/getsentry/sentry-dart/pull/2670))
Expand Down
15 changes: 14 additions & 1 deletion dart/lib/src/hint.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'protocol/sentry_response.dart';
import 'sentry_attachment/sentry_attachment.dart';
import 'sentry_options.dart';

import 'package:meta/meta.dart';

/// Hints are used in [BeforeSendCallback], [BeforeBreadcrumbCallback] and
/// event processors.
Expand Down Expand Up @@ -41,6 +43,9 @@
/// };
/// ```
class Hint {
@internal
static const maxResponseBodySize = 157286;

final Map<String, dynamic> _internalStorage = {};

final List<SentryAttachment> attachments = [];
Expand All @@ -49,6 +54,8 @@

SentryAttachment? viewHierarchy;

SentryResponse? response;

Hint();

factory Hint.withAttachment(SentryAttachment attachment) {
Expand Down Expand Up @@ -81,6 +88,12 @@
return hint;
}

factory Hint.withResponse(SentryResponse response) {
final hint = Hint();
hint.response = response;

Check warning on line 93 in dart/lib/src/hint.dart

View check run for this annotation

Codecov / codecov/patch

dart/lib/src/hint.dart#L91-L93

Added lines #L91 - L93 were not covered by tests
return hint;
}

// Key/Value Storage

void addAll(Map<String, dynamic> keysAndValues) {
Expand Down
3 changes: 2 additions & 1 deletion dart/lib/src/protocol/contexts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,10 @@ class Contexts extends MapView<String, dynamic> {

set trace(SentryTraceContext? trace) => this[SentryTraceContext.type] = trace;

/// Response context for a HTTP response.
/// Response context for a HTTP response. Not added automatically.
SentryResponse? get response => this[SentryResponse.type];

/// Use [Hint.response] in `beforeSend/beforeSendTransaction` to populate this value.
set response(SentryResponse? value) => this[SentryResponse.type] = value;

/// Feedback context for a feedback event.
Expand Down
4 changes: 0 additions & 4 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@ class SentryOptions {
/// This does not change whether an event is captured.
MaxRequestBodySize maxRequestBodySize = MaxRequestBodySize.never;

/// Configures up to which size response bodies should be included in events.
/// This does not change whether an event is captured.
MaxResponseBodySize maxResponseBodySize = MaxResponseBodySize.never;

SentryLogger _logger = noOpLogger;

/// Logger interface to log useful debugging information if debug is enabled
Expand Down
1 change: 0 additions & 1 deletion dio/example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ Future<void> main() async {
options.sendDefaultPii = true;

options.maxRequestBodySize = MaxRequestBodySize.small;
options.maxResponseBodySize = MaxResponseBodySize.small;
},
appRunner: runApp, // Init your App.
);
Expand Down
82 changes: 15 additions & 67 deletions dio/lib/src/dio_event_processor.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// ignore_for_file: deprecated_member_use

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:sentry/sentry.dart';

Expand Down Expand Up @@ -34,17 +32,13 @@ class DioEventProcessor implements EventProcessor {
return event;
}

final response = _responseFrom(dioError);
hint.response ??= _responseFrom(dioError);

var contexts = event.contexts;
if (event.contexts.response == null) {
contexts = contexts.copyWith(response: response);
}
// Don't override just parts of the original request.
// Keep the original one or if there's none create one.
event = event.copyWith(
request: event.request ?? _requestFrom(dioError),
contexts: contexts,
contexts: event.contexts,
);

return event;
Expand Down Expand Up @@ -86,77 +80,31 @@ class DioEventProcessor implements EventProcessor {
final headers = response?.headers.map.map(
(key, value) => MapEntry(key, value.join('; ')),
);
final contentLengthHeader = headers?['content-length'];
int? contentLength;
if (contentLengthHeader != null) {
contentLength = int.tryParse(contentLengthHeader);
}

return SentryResponse(
headers: _options.sendDefaultPii ? headers : null,
bodySize: _getBodySize(
dioError.response?.data,
dioError.requestOptions.responseType,
),
bodySize: contentLength,
statusCode: response?.statusCode,
data: _getResponseData(
dioError.response?.data,
dioError.requestOptions.responseType,
),
data: _getResponseData(dioError.response?.data, contentLength),
);
}

/// Returns the response data, if possible according to the users settings.
Object? _getResponseData(Object? data, ResponseType responseType) {
Object? _getResponseData(Object? data, int? contentLength) {
if (!_options.sendDefaultPii || data == null) {
return null;
}
switch (responseType) {
case ResponseType.json:
// ignore: invalid_use_of_internal_member
final jsData = utf8JsonEncoder.convert(data);
if (_options.maxResponseBodySize.shouldAddBody(jsData.length)) {
return data;
}
break;
case ResponseType.stream:
break; // No support for logging stream body.
case ResponseType.plain:
if (data is String &&
_options.maxResponseBodySize.shouldAddBody(data.codeUnits.length)) {
return data;
}
break;
case ResponseType.bytes:
if (data is List<int> &&
_options.maxResponseBodySize.shouldAddBody(data.length)) {
return data;
}
break;
}
return null;
}

int? _getBodySize(Object? data, ResponseType responseType) {
if (data == null) {
if (contentLength == null) {
return null;
}
switch (responseType) {
case ResponseType.json:
return json.encode(data).codeUnits.length;
case ResponseType.stream:
if (data is String) {
return data.length;
} else {
return null;
}
case ResponseType.plain:
if (data is String) {
return data.codeUnits.length;
} else {
return null;
}
case ResponseType.bytes:
if (data is List<int>) {
return data.length;
} else {
return null;
}
// ignore: invalid_use_of_internal_member
if (contentLength > Hint.maxResponseBodySize) {
return null;
}
return data;
}
}
Loading
Loading