Skip to content

Commit 5d2b46d

Browse files
denrasemarandaneto
andauthored
Add http fields to span.data (#1497)
Co-authored-by: Manoel Aranda Neto <[email protected]>
1 parent 8932ece commit 5d2b46d

File tree

9 files changed

+75
-14
lines changed

9 files changed

+75
-14
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
## Unreleased
44

5-
### Features
5+
### Enhancements
66

7+
- Add http fields to `span.data` ([#1497](https://github.com/getsentry/sentry-dart/pull/1497))
8+
- Set `http.response.status_code`
9+
- Set `http.response_content_length`
710
- Improve `SentryException#value`, remove stringified stack trace ([##1470](https://github.com/getsentry/sentry-dart/pull/#1470))
811

912
## 7.6.3

dart/lib/sentry.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,5 @@ export 'src/exception_stacktrace_extractor.dart';
4242
export 'src/utils/http_sanitizer.dart';
4343
// ignore: invalid_export_of_internal_element
4444
export 'src/utils/url_details.dart';
45+
// ignore: invalid_export_of_internal_element
46+
export 'src/utils/http_header_utils.dart';

dart/lib/src/http_client/tracing_client.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class TracingClient extends BaseClient {
5757
}
5858

5959
response = await _client.send(request);
60+
span?.setData('http.response.status_code', response.statusCode);
61+
span?.setData('http.response_content_length', response.contentLength);
6062
span?.status = SpanStatus.fromHttpStatusCode(response.statusCode);
6163
} catch (exception) {
6264
span?.throwable = exception;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import 'package:meta/meta.dart';
2+
3+
/// Helper to extract header data
4+
@internal
5+
class HttpHeaderUtils {
6+
/// Get `Content-Length` header
7+
static int? getContentLength(Map<String, List<String>> headers) {
8+
final contentLengthHeader =
9+
headers['content-length'] ?? headers['Content-Length'];
10+
if (contentLengthHeader != null && contentLengthHeader.isNotEmpty) {
11+
final headerValue = contentLengthHeader.first;
12+
return int.tryParse(headerValue);
13+
}
14+
return null;
15+
}
16+
}

dart/test/http_client/tracing_client_test.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ void main() {
4242
expect(span.data['url'], 'https://example.com');
4343
expect(span.data['http.query'], 'foo=bar');
4444
expect(span.data['http.fragment'], 'baz');
45+
expect(span.data['http.response.status_code'], 200);
46+
expect(span.data['http.response_content_length'], 2);
4547
});
4648

4749
test('finish span if errored request', () async {
@@ -225,7 +227,7 @@ class Fixture {
225227
MockClient getClient({int statusCode = 200, String? reason}) {
226228
return MockClient((request) async {
227229
expect(request.url, requestUri);
228-
return Response('', statusCode, reasonPhrase: reason, request: request);
230+
return Response('{}', statusCode, reasonPhrase: reason, request: request);
229231
});
230232
}
231233
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import 'package:sentry/sentry.dart';
2+
import 'package:test/test.dart';
3+
4+
void main() {
5+
test('get content length lower case', () {
6+
final headers = {
7+
'content-length': ['12']
8+
};
9+
expect(HttpHeaderUtils.getContentLength(headers), 12);
10+
});
11+
12+
test('get content length camel case', () {
13+
final headers = {
14+
'Content-Length': ['12']
15+
};
16+
expect(HttpHeaderUtils.getContentLength(headers), 12);
17+
});
18+
}

dio/lib/src/breadcrumb_client_adapter.dart

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,8 @@ class BreadcrumbClientAdapter implements HttpClientAdapter {
4242

4343
statusCode = response.statusCode;
4444
reason = response.statusMessage;
45-
final contentLengthHeader = response.headers['content-length'];
46-
if (contentLengthHeader != null && contentLengthHeader.isNotEmpty) {
47-
final headerValue = contentLengthHeader.first;
48-
responseBodySize = int.tryParse(headerValue);
49-
}
45+
// ignore: invalid_use_of_internal_member
46+
responseBodySize = HttpHeaderUtils.getContentLength(response.headers);
5047

5148
return response;
5249
} catch (_) {

dio/lib/src/tracing_client_adapter.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ class TracingClientAdapter implements HttpClientAdapter {
6666

6767
response = await _client.fetch(options, requestStream, cancelFuture);
6868
span?.status = SpanStatus.fromHttpStatusCode(response.statusCode);
69+
span?.setData('http.response.status_code', response.statusCode);
70+
final contentLengthHeader =
71+
// ignore: invalid_use_of_internal_member
72+
HttpHeaderUtils.getContentLength(response.headers);
73+
if (contentLengthHeader != null) {
74+
span?.setData('http.response_content_length', contentLengthHeader);
75+
}
6976
} catch (exception) {
7077
span?.throwable = exception;
7178
span?.status = const SpanStatus.internalError();

dio/test/tracing_client_adapter_test.dart

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ void main() {
2424

2525
test('captured span if successful request', () async {
2626
final sut = fixture.getSut(
27-
client: fixture.getClient(statusCode: 200, reason: 'OK'),
27+
client:
28+
fixture.getClient(statusCode: 200, reason: 'OK', contentLength: 2),
2829
);
2930
final tr = fixture._hub.startTransaction(
3031
'name',
@@ -46,6 +47,8 @@ void main() {
4647
expect(span.data['url'], 'https://example.com');
4748
expect(span.data['http.query'], 'foo=bar');
4849
expect(span.data['http.fragment'], 'baz');
50+
expect(span.data['http.response.status_code'], 200);
51+
expect(span.data['http.response_content_length'], 2);
4952
});
5053

5154
test('finish span if errored request', () async {
@@ -175,16 +178,27 @@ class Fixture {
175178
return dio;
176179
}
177180

178-
MockHttpClientAdapter getClient({int statusCode = 200, String? reason}) {
181+
MockHttpClientAdapter getClient({
182+
int statusCode = 200,
183+
String? reason,
184+
int? contentLength,
185+
}) {
179186
return MockHttpClientAdapter((options, requestStream, cancelFuture) async {
180187
expect(options.uri, requestUri);
188+
189+
final headers = options.headers.map(
190+
(key, dynamic value) =>
191+
MapEntry(key, <String>[value?.toString() ?? '']),
192+
);
193+
194+
if (contentLength != null) {
195+
headers['Content-Length'] = [contentLength.toString()];
196+
}
197+
181198
return ResponseBody.fromString(
182-
'',
199+
'{}',
183200
statusCode,
184-
headers: options.headers.map(
185-
(key, dynamic value) =>
186-
MapEntry(key, <String>[value?.toString() ?? '']),
187-
),
201+
headers: headers,
188202
);
189203
});
190204
}

0 commit comments

Comments
 (0)