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

Make response body accessible via hint in beforeSendTransaction callback for SentryHttpClient #2293

Open
wants to merge 33 commits into
base: v9
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2308122
capture response body for failed requests and if tracing is enabled.
martinhaintz Sep 16, 2024
da865b2
unified event capturing for request and response
martinhaintz Sep 17, 2024
bc3d263
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 4, 2024
710ab1a
make response body accessible via hint
martinhaintz Nov 5, 2024
f9abe16
fix warning
martinhaintz Nov 5, 2024
a309f16
add changelog entry
martinhaintz Nov 5, 2024
715ab7d
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 11, 2024
52ecb5e
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 13, 2024
0282579
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 18, 2024
4190467
add response body as hint for beforeTransactionSend
martinhaintz Nov 18, 2024
ac2c668
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 19, 2024
24b8ca9
update hive mocks
martinhaintz Nov 19, 2024
7042c14
update drift mocks
martinhaintz Nov 19, 2024
b9fbb3a
update dio mocks
martinhaintz Nov 19, 2024
557958f
update file mocks
martinhaintz Nov 19, 2024
5959137
update mocks for isar
martinhaintz Nov 19, 2024
b417e98
update sqflite mocks
martinhaintz Nov 19, 2024
1ead661
add script to run builder for all packages
martinhaintz Nov 19, 2024
fdadb89
fix streamed response copier
martinhaintz Nov 19, 2024
f773568
fix dart analyze
martinhaintz Nov 19, 2024
b0bca7d
fix analyzer and format
martinhaintz Nov 19, 2024
9e2ff12
update flutter mocks and fix tests
martinhaintz Nov 19, 2024
8896a1e
fix mocks
martinhaintz Nov 19, 2024
9b4000b
fix analyze options
martinhaintz Nov 19, 2024
86ffb80
cleanup and code reformating
martinhaintz Nov 19, 2024
b325b09
revert changes
martinhaintz Nov 19, 2024
b38f597
remove unused import
martinhaintz Nov 19, 2024
47f50aa
removed hint from tracer
martinhaintz Nov 20, 2024
a188061
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 20, 2024
4d43edd
Merge branch 'main' into feat/capture-http-response-body-for-sentry-h…
martinhaintz Nov 25, 2024
537230b
fix changelog example
martinhaintz Nov 25, 2024
d9c2674
fix changelog example
martinhaintz Dec 2, 2024
a5c5b8e
Merge branch 'v9' into feat/capture-http-response-body-for-sentry-htt…
martinhaintz Dec 4, 2024
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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@

### Features

- Make response body accessible via hint in `beforSend` callback for failed web requests or if tracing is enabled in `SentryHttpClient` ([#2293](https://github.com/getsentry/sentry-dart/pull/2293))
```dart
options.beforeSendTransaction = (transaction, hint) {
final firstHint = transaction.spans[0].hint;
final firstResponseBody = firstHint?.get(TypeCheckHint.httpResponse);
final secondHint = transaction.spans[1].hint;
final secondResponseBody = secondHint?.get(TypeCheckHint.httpResponse);
// user can now use it
return transaction;
};
```
- Support for screenshot PII content masking ([#2361](https://github.com/getsentry/sentry-dart/pull/2361))
By default, masking is enabled for SessionReplay. To also enable it for screenshots captured with events, you can specify `options.experimental.privacy`:
```dart
Expand Down
1 change: 1 addition & 0 deletions dart/lib/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export 'src/throwable_mechanism.dart';
export 'src/transport/transport.dart';
export 'src/integration.dart';
export 'src/event_processor.dart';
// ignore: invalid_export_of_internal_element
export 'src/http_client/sentry_http_client.dart';
export 'src/http_client/sentry_http_client_error.dart';
export 'src/sentry_attachment/sentry_attachment.dart';
Expand Down
15 changes: 10 additions & 5 deletions dart/lib/src/http_client/failed_request_client.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:http/http.dart';
import '../hint.dart';
import '../type_check_hint.dart';
import '../utils/streamed_response_copier.dart';
import '../utils/tracing_utils.dart';
import 'sentry_http_client_error.dart';
import '../protocol.dart';
Expand Down Expand Up @@ -99,15 +100,19 @@ class FailedRequestClient extends BaseClient {
int? statusCode;
Object? exception;
StackTrace? stackTrace;
StreamedResponse? response;
StreamedResponse? originalResponse;
StreamedResponse? copiedResponse;

final stopwatch = Stopwatch();
stopwatch.start();

try {
response = await _client.send(request);
statusCode = response.statusCode;
return response;
originalResponse = await _client.send(request);
final copier = StreamedResponseCopier(originalResponse);
originalResponse = copier.copy();
copiedResponse = copier.copy();
statusCode = originalResponse.statusCode;
return originalResponse;
} catch (e, st) {
exception = e;
stackTrace = st;
Expand All @@ -119,7 +124,7 @@ class FailedRequestClient extends BaseClient {
statusCode,
exception,
stackTrace,
response,
copiedResponse,
stopwatch.elapsed,
);
}
Expand Down
3 changes: 1 addition & 2 deletions dart/lib/src/http_client/sentry_http_client.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:http/http.dart';
import '../../sentry.dart';
import 'tracing_client.dart';
import '../hub.dart';
import '../hub_adapter.dart';
import 'breadcrumb_client.dart';
import 'failed_request_client.dart';

Expand Down
31 changes: 17 additions & 14 deletions dart/lib/src/http_client/tracing_client.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import 'package:http/http.dart';
import '../hub.dart';
import '../hub_adapter.dart';
import '../protocol.dart';
import '../sentry_trace_origins.dart';
import '../tracing.dart';
import '../utils/tracing_utils.dart';
import '../utils/http_sanitizer.dart';
import '../../sentry.dart';
import '../utils/streamed_response_copier.dart';

/// A [http](https://pub.dev/packages/http)-package compatible HTTP client
/// which adds support to Sentry Performance feature.
Expand Down Expand Up @@ -44,7 +39,8 @@ class TracingClient extends BaseClient {
span?.setData('http.request.method', request.method);
urlDetails?.applyToSpan(span);

StreamedResponse? response;
StreamedResponse? originalResponse;
final hint = Hint();
try {
if (containsTargetOrMatchesRegExp(
_hub.options.tracePropagationTargets, request.url.toString())) {
Expand All @@ -71,19 +67,26 @@ class TracingClient extends BaseClient {
}
}

response = await _client.send(request);
span?.setData('http.response.status_code', response.statusCode);
span?.setData('http.response_content_length', response.contentLength);
span?.status = SpanStatus.fromHttpStatusCode(response.statusCode);
originalResponse = await _client.send(request);
final copier = StreamedResponseCopier(originalResponse);
originalResponse = copier.copy();
final copiedResponse = copier.copy();

span?.setData('http.response.status_code', originalResponse.statusCode);
span?.setData(
'http.response_content_length', originalResponse.contentLength);
span?.status = SpanStatus.fromHttpStatusCode(originalResponse.statusCode);

hint.set(TypeCheckHint.httpResponse, copiedResponse);
} catch (exception) {
span?.throwable = exception;
span?.status = SpanStatus.internalError();

rethrow;
} finally {
await span?.finish();
await span?.finish(hint: hint);
}
return response;
return originalResponse;
}

@override
Expand Down
2 changes: 2 additions & 0 deletions dart/lib/src/hub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ class Hub {
Future<SentryId> captureTransaction(
SentryTransaction transaction, {
SentryTraceContextHeader? traceContext,
Hint? hint,
}) async {
var sentryId = SentryId.empty();

Expand Down Expand Up @@ -617,6 +618,7 @@ class Hub {
transaction,
scope: item.scope,
traceContext: traceContext,
hint: hint,
);
} catch (exception, stackTrace) {
_options.logger(
Expand Down
2 changes: 2 additions & 0 deletions dart/lib/src/hub_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@ class HubAdapter implements Hub {
Future<SentryId> captureTransaction(
SentryTransaction transaction, {
SentryTraceContextHeader? traceContext,
Hint? hint,
}) =>
Sentry.currentHub.captureTransaction(
transaction,
traceContext: traceContext,
hint: hint,
);

@override
Expand Down
1 change: 1 addition & 0 deletions dart/lib/src/noop_hub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class NoOpHub implements Hub {
Future<SentryId> captureTransaction(
SentryTransaction transaction, {
SentryTraceContextHeader? traceContext,
Hint? hint,
}) async =>
SentryId.empty();

Expand Down
1 change: 1 addition & 0 deletions dart/lib/src/noop_sentry_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class NoOpSentryClient implements SentryClient {
SentryTransaction transaction, {
Scope? scope,
SentryTraceContextHeader? traceContext,
Hint? hint,
}) async =>
SentryId.empty();

Expand Down
10 changes: 6 additions & 4 deletions dart/lib/src/noop_sentry_span.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import '../sentry.dart';
import 'metrics/local_metrics_aggregator.dart';
import 'protocol.dart';
import 'tracing.dart';
import 'utils.dart';

class NoOpSentrySpan extends ISentrySpan {
NoOpSentrySpan._();
Expand All @@ -27,7 +25,11 @@ class NoOpSentrySpan extends ISentrySpan {
}

@override
Future<void> finish({SpanStatus? status, DateTime? endTimestamp}) async {}
Future<void> finish({
SpanStatus? status,
DateTime? endTimestamp,
Hint? hint,
}) async {}

@override
void removeData(String key) {}
Expand Down
14 changes: 12 additions & 2 deletions dart/lib/src/protocol/sentry_span.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import '../metrics/local_metrics_aggregator.dart';

import '../sentry_tracer.dart';

typedef OnFinishedCallback = Future<void> Function({DateTime? endTimestamp});
typedef OnFinishedCallback = Future<void> Function({
DateTime? endTimestamp,
Hint? hint,
});

class SentrySpan extends ISentrySpan {
final SentrySpanContext _context;
Expand Down Expand Up @@ -36,6 +39,8 @@ class SentrySpan extends ISentrySpan {
@override
final SentryTracesSamplingDecision? samplingDecision;

late final Hint? hint;

SentrySpan(
this._tracer,
this._context,
Expand All @@ -55,10 +60,15 @@ class SentrySpan extends ISentrySpan {
}

@override
Future<void> finish({SpanStatus? status, DateTime? endTimestamp}) async {
Future<void> finish({
SpanStatus? status,
DateTime? endTimestamp,
Hint? hint,
}) async {
if (finished) {
return;
}
this.hint = hint;

if (status != null) {
_status = status;
Expand Down
11 changes: 7 additions & 4 deletions dart/lib/src/sentry_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,9 @@ class SentryClient {
SentryTransaction transaction, {
Scope? scope,
SentryTraceContextHeader? traceContext,
Hint? hint,
}) async {
final hint = Hint();
hint ??= Hint();

SentryTransaction? preparedTransaction =
_prepareEvent(transaction, hint) as SentryTransaction;
Expand Down Expand Up @@ -409,8 +410,10 @@ class SentryClient {
preparedTransaction = _createUserOrSetDefaultIpAddress(preparedTransaction)
as SentryTransaction;

preparedTransaction =
await _runBeforeSend(preparedTransaction, hint) as SentryTransaction?;
preparedTransaction = await _runBeforeSend(
preparedTransaction,
hint,
) as SentryTransaction?;

// dropped by beforeSendTransaction
if (preparedTransaction == null) {
Expand Down Expand Up @@ -515,7 +518,7 @@ class SentryClient {
try {
if (event is SentryTransaction && beforeSendTransaction != null) {
beforeSendName = 'beforeSendTransaction';
final callbackResult = beforeSendTransaction(event);
final callbackResult = beforeSendTransaction(event, hint);
if (callbackResult is Future<SentryTransaction?>) {
processedEvent = await callbackResult;
} else {
Expand Down
1 change: 1 addition & 0 deletions dart/lib/src/sentry_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ typedef BeforeSendCallback = FutureOr<SentryEvent?> Function(
/// object or nothing to skip reporting the transaction
typedef BeforeSendTransactionCallback = FutureOr<SentryTransaction?> Function(
SentryTransaction transaction,
Hint hint,
);

/// This function is called with an SDK specific breadcrumb object before the breadcrumb is added
Expand Down
9 changes: 6 additions & 3 deletions dart/lib/src/sentry_span_interface.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'package:meta/meta.dart';

import '../sentry.dart';
import 'metrics/local_metrics_aggregator.dart';
import 'protocol.dart';
import 'tracing.dart';

/// Represents performance monitoring Span.
abstract class ISentrySpan {
Expand All @@ -26,7 +25,11 @@ abstract class ISentrySpan {
void removeData(String key);

/// Sets span timestamp marking this span as finished.
Future<void> finish({SpanStatus? status, DateTime? endTimestamp}) async {}
Future<void> finish({
SpanStatus? status,
DateTime? endTimestamp,
Hint? hint,
}) async {}

/// Gets span status.
SpanStatus? get status;
Expand Down
17 changes: 12 additions & 5 deletions dart/lib/src/sentry_tracer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ class SentryTracer extends ISentrySpan {
}

@override
Future<void> finish({SpanStatus? status, DateTime? endTimestamp}) async {
Future<void> finish({
SpanStatus? status,
DateTime? endTimestamp,
Hint? hint,
}) async {
final commonEndTimestamp = endTimestamp ?? _hub.options.clock();
_autoFinishAfterTimer?.cancel();
_finishStatus = SentryTracerFinishStatus.finishing(status);
Expand Down Expand Up @@ -160,6 +164,7 @@ class SentryTracer extends ISentrySpan {
await _hub.captureTransaction(
transaction,
traceContext: traceContext(),
hint: hint,
);
} finally {
profiler?.dispose();
Expand Down Expand Up @@ -274,12 +279,14 @@ class SentryTracer extends ISentrySpan {
return child;
}

Future<void> _finishedCallback({
DateTime? endTimestamp,
}) async {
Future<void> _finishedCallback({DateTime? endTimestamp, Hint? hint}) async {
final finishStatus = _finishStatus;
if (finishStatus.finishing) {
await finish(status: finishStatus.status, endTimestamp: endTimestamp);
await finish(
status: finishStatus.status,
endTimestamp: endTimestamp,
hint: hint,
);
}
}

Expand Down
Loading
Loading