Skip to content
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

[v9] Remove max response body size #2709

Merged
merged 14 commits into from
Feb 18, 2025
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
- Remove `options.autoAppStart` and `setAppStartEnd` ([#2680](https://github.com/getsentry/sentry-dart/pull/2680))
- Add hint for transactions ([#2675](https://github.com/getsentry/sentry-dart/pull/2675))
- `BeforeSendTransactionCallback` now has a `Hint` parameter
- Remove max response body size ([#2709](https://github.com/getsentry/sentry-dart/pull/2709))
- Responses are now only attached if size is below ~15mb
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and also pls mention that this is currently only applicable for the dio integration, not our http integration

Copy link
Contributor

@buenaflor buenaflor Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our http integration doesn't support capturing the response data generally, we could add that feature later at some point

- Responses are attached to the `Hint` object, which can be read in `beforeSend`/`beforeSendTransaction` callbacks.

### Dependencies

Expand Down
10 changes: 9 additions & 1 deletion dart/lib/src/hint.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'protocol/sentry_response.dart';
import 'sentry_attachment/sentry_attachment.dart';
import 'sentry_options.dart';

/// Hints are used in [BeforeSendCallback], [BeforeBreadcrumbCallback] and
/// event processors.
Expand Down Expand Up @@ -49,6 +49,8 @@

SentryAttachment? viewHierarchy;

SentryResponse? response;

Hint();

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

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

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

View check run for this annotation

Codecov / codecov/patch

dart/lib/src/hint.dart#L86-L88

Added lines #L86 - L88 were not covered by tests
return hint;
}

// Key/Value Storage

void addAll(Map<String, dynamic> keysAndValues) {
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
80 changes: 14 additions & 66 deletions dio/lib/src/dio_event_processor.dart
Original file line number Diff line number Diff line change
@@ -1,6 +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 +33,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 +81,30 @@ 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;
}
if (contentLength > 157286) {
return null;
}
return data;
}
}
Loading
Loading