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

feat: Change default tracing headers #501

Merged
merged 2 commits into from
Oct 26, 2023
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
1 change: 1 addition & 0 deletions packages/datadog_flutter_plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Release 2.0 introduces breaking changes. Follow the [Migration Guide](MIGRATING.

* Update to v2.0 of Datadog SDKs.
* Update UUID to ^4.0. See [#472]
* Change default tracing headers for first party hosts to use both Datadog headers and W3C tracecontext headers.

## 1.6.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,10 @@ class DatadogConfiguration {
set firstPartyHosts(List<String> hosts) {
firstPartyHostsWithTracingHeaders.clear();
for (var entry in hosts) {
firstPartyHostsWithTracingHeaders[entry] = {TracingHeaderType.datadog};
firstPartyHostsWithTracingHeaders[entry] = {
TracingHeaderType.datadog,
TracingHeaderType.tracecontext
};
}
}

Expand Down Expand Up @@ -216,10 +219,12 @@ class DatadogConfiguration {
final headerTypes = firstPartyHostsWithTracingHeaders[entry];
if (headerTypes == null) {
firstPartyHostsWithTracingHeaders[entry] = {
TracingHeaderType.datadog
TracingHeaderType.datadog,
TracingHeaderType.tracecontext,
};
} else {
headerTypes.add(TracingHeaderType.datadog);
headerTypes.add(TracingHeaderType.tracecontext);
}
}
}
Expand Down Expand Up @@ -309,7 +314,10 @@ class DatadogAttachConfiguration {
set firstPartyHosts(List<String> hosts) {
firstPartyHostsWithTracingHeaders.clear();
for (var entry in hosts) {
firstPartyHostsWithTracingHeaders[entry] = {TracingHeaderType.datadog};
firstPartyHostsWithTracingHeaders[entry] = {
TracingHeaderType.datadog,
TracingHeaderType.tracecontext
};
}
}

Expand Down Expand Up @@ -358,10 +366,12 @@ class DatadogAttachConfiguration {
final headerTypes = firstPartyHostsWithTracingHeaders[entry];
if (headerTypes == null) {
firstPartyHostsWithTracingHeaders[entry] = {
TracingHeaderType.datadog
TracingHeaderType.datadog,
TracingHeaderType.tracecontext
};
} else {
headerTypes.add(TracingHeaderType.datadog);
headerTypes.add(TracingHeaderType.tracecontext);
}
}
}
Expand Down
22 changes: 14 additions & 8 deletions packages/datadog_flutter_plugin/test/datadog_sdk_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,11 @@ void main() {

expect(datadogSdk.firstPartyHosts.length, 2);
expect(datadogSdk.firstPartyHosts[0].hostName, 'example.com');
expect(datadogSdk.firstPartyHosts[0].headerTypes,
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});

Choose a reason for hiding this comment

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

can you also assert the data in both headers (datadog and tracecontext) is same?

if this is covered somewhere else, I'm fine with that also.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 I actually thought I had it in the actual tracing library, but it appears not. I'll add it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added for the main library. Ready for re-review.

expect(datadogSdk.firstPartyHosts[1].hostName, 'datadoghq.com');
expect(datadogSdk.firstPartyHosts[1].headerTypes,
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
});

test('attachToExisting with loggingEnabled creates Logging bridge', () async {
Expand Down Expand Up @@ -303,11 +307,11 @@ void main() {

expect(datadogSdk.firstPartyHosts.length, 2);
expect(datadogSdk.firstPartyHosts[0].hostName, 'example.com');
expect(
datadogSdk.firstPartyHosts[0].headerTypes, {TracingHeaderType.datadog});
expect(datadogSdk.firstPartyHosts[0].headerTypes,
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
expect(datadogSdk.firstPartyHosts[1].hostName, 'datadoghq.com');
expect(
datadogSdk.firstPartyHosts[1].headerTypes, {TracingHeaderType.datadog});
expect(datadogSdk.firstPartyHosts[1].headerTypes,
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
});

test('first party hosts with tracing headers set to sdk', () async {
Expand Down Expand Up @@ -346,8 +350,8 @@ void main() {
expect(datadogSdk.firstPartyHosts[0].hostName, 'example.com');
expect(datadogSdk.firstPartyHosts[0].headerTypes, {TracingHeaderType.b3});
expect(datadogSdk.firstPartyHosts[1].hostName, 'datadoghq.com');
expect(
datadogSdk.firstPartyHosts[1].headerTypes, {TracingHeaderType.datadog});
expect(datadogSdk.firstPartyHosts[1].headerTypes,
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
});

test('headerTypesForHost with no hosts returns empty set', () async {
Expand Down Expand Up @@ -375,7 +379,8 @@ void main() {
await datadogSdk.initialize(configuration, TrackingConsent.pending);

var uri = Uri.parse('https://datadoghq.com/path');
expect(datadogSdk.headerTypesForHost(uri), {TracingHeaderType.datadog});
expect(datadogSdk.headerTypesForHost(uri),
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
});

test(
Expand All @@ -392,7 +397,8 @@ void main() {
await datadogSdk.initialize(configuration, TrackingConsent.pending);

var uri = Uri.parse('https://test.datadoghq.com/path');
expect(datadogSdk.headerTypesForHost(uri), {TracingHeaderType.datadog});
expect(datadogSdk.headerTypesForHost(uri),
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});
});

test('headerTypesForHost with matching subdomain does not match root',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,5 +519,52 @@ void main() {
expect(capturedB.url, testUriB);
verifyHeaders(capturedB.headers, TracingHeaderType.b3);
});

test('different tracing headers are same trace id', () async {
// Given
when(() => mockDatadog
.headerTypesForHost(any(that: HasHost(equals('test_url_a')))))
.thenReturn(
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});

// When
final client = DatadogClient(
datadogSdk: mockDatadog,
innerClient: mockClient,
);
final testUri = Uri.parse('https://test_url_a/test');
await client.get(testUri);

// Then
final callAttributes = verify(() => mockRum.startResource(
any(), RumHttpMethod.get, testUri.toString(), captureAny()))
.captured[0] as Map<String, Object?>;

final traceValue = callAttributes['_dd.trace_id'] as String?;
final traceInt = traceValue != null ? BigInt.tryParse(traceValue) : null;
expect(traceInt, isNotNull);
expect(traceInt?.bitLength, lessThanOrEqualTo(63));

final spanValue = callAttributes['_dd.span_id'] as String?;
final spanInt = spanValue != null ? BigInt.tryParse(spanValue) : null;
expect(spanInt, isNotNull);
expect(spanInt?.bitLength, lessThanOrEqualTo(63));

final captured = verify(() => mockClient.send(captureAny())).captured[0]
as http.BaseRequest;

final datadogTraceInt =
BigInt.tryParse(captured.headers['x-datadog-trace-id']!);
expect(traceInt, datadogTraceInt);
final datadogSpanInt =
BigInt.tryParse(captured.headers['x-datadog-parent-id']!);
expect(spanInt, datadogSpanInt);

final tracecontextParts = captured.headers['traceparent']!.split('-');
final contextTraceInt = BigInt.tryParse(tracecontextParts[1], radix: 16);
expect(traceInt, contextTraceInt);
final contextSpanInt = BigInt.tryParse(tracecontextParts[2], radix: 16);
expect(spanInt, contextSpanInt);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,67 @@ void main() {
await verifyCall(testUriB, TracingHeaderType.b3);
});

test('different tracing headers are same trace id', () async {
// Given
enableRum();
when(() => mockDatadog
.headerTypesForHost(any(that: HasHost(equals('test_url_a')))))
.thenReturn(
{TracingHeaderType.datadog, TracingHeaderType.tracecontext});

// When
final client = DatadogTrackingHttpClient(
mockDatadog,
DdHttpTrackingPluginConfiguration(),
mockClient,
);
final testUri = Uri.parse('https://test_url_a/test');
final completer = setupMockRequest(testUri);
var mockResponse = setupMockClientResponse(200);
var request = await client.openUrl('get', testUri);
completer.complete(mockResponse);

var response = await request.done;
response.listen((event) {});
await mockResponse.streamController.close();

// Then
final callAttributes = verify(() =>
mockRum.stopResource(any(), any(), any(), any(), captureAny()))
.captured[0] as Map<String, Object?>;

final traceValue = callAttributes['_dd.trace_id'] as String?;
final traceInt = traceValue != null ? BigInt.tryParse(traceValue) : null;
expect(traceInt, isNotNull);
expect(traceInt?.bitLength, lessThanOrEqualTo(63));

final spanValue = callAttributes['_dd.span_id'] as String?;
final spanInt = spanValue != null ? BigInt.tryParse(spanValue) : null;
expect(spanInt, isNotNull);
expect(spanInt?.bitLength, lessThanOrEqualTo(63));

final headers = request.headers;
final datadogTraceString =
verify(() => headers.add('x-datadog-trace-id', captureAny()))
.captured[0];
final datadogTraceInt = BigInt.tryParse(datadogTraceString);
expect(traceInt, datadogTraceInt);
final datadogSpanString =
verify(() => headers.add('x-datadog-parent-id', captureAny()))
.captured[0];
final datadogSpanInt = BigInt.tryParse(datadogSpanString);
expect(spanInt, datadogSpanInt);

final traceContextString =
verify(() => headers.add('traceparent', captureAny())).captured[0]
as String;
final tracecontextParts = traceContextString.split('-');
final contextTraceInt = BigInt.tryParse(tracecontextParts[1], radix: 16);
expect(traceInt, contextTraceInt);
final contextSpanInt = BigInt.tryParse(tracecontextParts[2], radix: 16);
expect(spanInt, contextSpanInt);
});

group('when rum is enabled with datadog tracing headers', () {
late DatadogTrackingHttpClient client;

Expand Down