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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send trace origin #1534

Merged
merged 29 commits into from Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5edb1b2
add origin to trace context
denrase Jun 19, 2023
5fe8c6e
add to span context
denrase Jun 20, 2023
98192ae
add origin to span interface and implementing classes
denrase Jun 20, 2023
ff6de30
set trace origin when starting transacrions from hub
denrase Jun 20, 2023
f6f2559
set origin for transactions started through hub
denrase Jun 20, 2023
8d011af
set origin for http tracing client and dio tracing client adapter
denrase Jun 20, 2023
20d5532
set in file package
denrase Jun 20, 2023
f2d527a
set origin in span asset bundle
denrase Jun 26, 2023
cf9ff62
add origin to SentryTransformer
denrase Jun 26, 2023
10f74e8
Merge branch 'main' into feat/trace-origin
denrase Jun 26, 2023
bfcaae9
add missing origin
denrase Jun 26, 2023
b78d02c
add origin to batch
denrase Jun 26, 2023
5370936
set origin to executor spans
denrase Jun 26, 2023
9b84879
add origin to sqflite span
denrase Jun 26, 2023
0addffe
format
denrase Jun 26, 2023
6256ab8
add changelog entry and comments
denrase Jun 26, 2023
7796896
clone origin
denrase Jun 26, 2023
ec81fa0
add invalid_use_of_internal_member
denrase Jun 26, 2023
77f6137
introduce seperate 'auto.file.sqflite.sentry_database' origin
denrase Jun 26, 2023
58eec90
fix analyze issue
denrase Jun 26, 2023
2efb2d4
no need for extra param in hub
denrase Jun 27, 2023
8d41c70
set origin to manual
denrase Jun 27, 2023
1988ebe
simplify databse names
denrase Jul 4, 2023
c8e7289
Merge branch 'main' into feat/trace-origin
denrase Jul 10, 2023
af45407
rename trace origins for sqflite
denrase Jul 10, 2023
13dd3fe
Merge branch 'main' into feat/trace-origin
denrase Jul 11, 2023
7319f1f
Merge branch 'main' into feat/trace-origin
marandaneto Jul 14, 2023
1ff48ca
Merge branch 'main' into feat/trace-origin
marandaneto Jul 17, 2023
bb4030d
Merge branch 'main' into feat/trace-origin
marandaneto Jul 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

### Features

- Send trace origin ([#1534](https://github.com/getsentry/sentry-dart/pull/1534))

[Trace origin](https://develop.sentry.dev/sdk/performance/trace-origin/) indicates what created a trace or a span. Not all transactions and spans contain enough information to tell whether the user or what precisely in the SDK created it. Origin solves this problem. The SDK now sends origin for transactions and spans.

## 7.8.0

### Enhancements
Expand Down
2 changes: 2 additions & 0 deletions dart/lib/sentry.dart
Expand Up @@ -44,3 +44,5 @@ export 'src/utils/http_sanitizer.dart';
export 'src/utils/url_details.dart';
// ignore: invalid_export_of_internal_element
export 'src/utils/http_header_utils.dart';
// ignore: invalid_export_of_internal_element
export 'src/sentry_trace_origins.dart';
2 changes: 2 additions & 0 deletions dart/lib/src/http_client/tracing_client.dart
Expand Up @@ -2,6 +2,7 @@ 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';
Expand Down Expand Up @@ -33,6 +34,7 @@ class TracingClient extends BaseClient {
'http.client',
description: description,
);
span?.origin = SentryTraceOrigins.autoHttpHttp;

// if the span is NoOp, we don't want to attach headers
if (span is NoOpSentrySpan) {
Expand Down
7 changes: 7 additions & 0 deletions dart/lib/src/hub.dart
Expand Up @@ -398,6 +398,7 @@ class Hub {
name,
operation,
description: description,
origin: SentryTraceOrigins.manual,
),
startTimestamp: startTimestamp,
bindToScope: bindToScope,
Expand Down Expand Up @@ -442,6 +443,12 @@ class Hub {
transactionContext.copyWith(samplingDecision: samplingDecision);
}

if (transactionContext.origin == null) {
transactionContext = transactionContext.copyWith(
origin: SentryTraceOrigins.manual,
);
}

final tracer = SentryTracer(
transactionContext,
this,
Expand Down
6 changes: 6 additions & 0 deletions dart/lib/src/noop_sentry_span.dart
Expand Up @@ -51,6 +51,12 @@ class NoOpSentrySpan extends ISentrySpan {
@override
SentrySpanContext get context => _spanContext;

@override
String? get origin => null;

@override
set origin(String? origin) {}

@override
SpanStatus? get status => null;

Expand Down
12 changes: 12 additions & 0 deletions dart/lib/src/protocol/sentry_span.dart
Expand Up @@ -36,6 +36,7 @@ class SentrySpan extends ISentrySpan {
}) {
_startTimestamp = startTimestamp?.toUtc() ?? _hub.options.clock();
_finishedCallback = finishedCallback;
_origin = _context.origin;
}

@override
Expand Down Expand Up @@ -145,6 +146,14 @@ class SentrySpan extends ISentrySpan {
@override
SentrySpanContext get context => _context;

String? _origin;

@override
String? get origin => _origin;

@override
set origin(String? origin) => _origin = origin;

Map<String, dynamic> toJson() {
final json = _context.toJson();
json['start_timestamp'] =
Expand All @@ -162,6 +171,9 @@ class SentrySpan extends ISentrySpan {
if (_tags.isNotEmpty) {
json['tags'] = _tags;
}
if (_origin != null) {
json['origin'] = _origin;
}
return json;
}

Expand Down
11 changes: 11 additions & 0 deletions dart/lib/src/protocol/sentry_trace_context.dart
Expand Up @@ -28,6 +28,13 @@ class SentryTraceContext {
/// The Span status
final SpanStatus? status;

/// The origin of the span indicates what created the span.
///
/// @note Gets set by the SDK. It is not expected to be set manually by users.
///
/// @see <https://develop.sentry.dev/sdk/performance/trace-origin>
final String? origin;

factory SentryTraceContext.fromJson(Map<String, dynamic> json) {
return SentryTraceContext(
operation: json['op'] as String,
Expand All @@ -41,6 +48,7 @@ class SentryTraceContext {
? null
: SpanStatus.fromString(json['status'] as String),
sampled: true,
origin: json['origin'] == null ? null : json['origin'] as String?,
);
}

Expand All @@ -53,6 +61,7 @@ class SentryTraceContext {
if (parentSpanId != null) 'parent_span_id': parentSpanId!.toString(),
if (description != null) 'description': description,
if (status != null) 'status': status!.toString(),
if (origin != null) 'origin': origin,
};
}

Expand All @@ -64,6 +73,7 @@ class SentryTraceContext {
status: status,
parentSpanId: parentSpanId,
sampled: sampled,
origin: origin,
);

SentryTraceContext({
Expand All @@ -74,6 +84,7 @@ class SentryTraceContext {
required this.operation,
this.description,
this.status,
this.origin,
}) : traceId = traceId ?? SentryId.newId(),
spanId = spanId ?? SpanId.newId();
}
10 changes: 10 additions & 0 deletions dart/lib/src/sentry_span_context.dart
Expand Up @@ -20,6 +20,13 @@ class SentrySpanContext {
/// consistent across instances of the span.
final String? description;

/// The origin of the span indicates what created the span.
///
/// Gets set by the SDK. It is not expected to be set manually by users.
///
/// See https://develop.sentry.dev/sdk/performance/trace-origin
final String? origin;

/// Item encoded as JSON
Map<String, dynamic> toJson() {
return {
Expand All @@ -28,6 +35,7 @@ class SentrySpanContext {
'op': operation,
if (parentSpanId != null) 'parent_span_id': parentSpanId.toString(),
if (description != null) 'description': description,
if (origin != null) 'origin': origin,
};
}

Expand All @@ -37,6 +45,7 @@ class SentrySpanContext {
this.parentSpanId,
required this.operation,
this.description,
this.origin,
}) : traceId = traceId ?? SentryId.newId(),
spanId = spanId ?? SpanId.newId();

Expand All @@ -53,6 +62,7 @@ class SentrySpanContext {
parentSpanId: parentSpanId,
sampled: sampled,
status: status,
origin: origin,
);
}
}
10 changes: 10 additions & 0 deletions dart/lib/src/sentry_span_interface.dart
Expand Up @@ -36,6 +36,16 @@ abstract class ISentrySpan {
/// Gets the span context.
SentrySpanContext get context;

/// Gets the span origin
String? get origin;

/// Sets span origin.
///
/// Gets set by the SDK. It is not expected to be set manually by users.
///
/// See https://develop.sentry.dev/sdk/performance/trace-origin
set origin(String? origin);

/// Returns the end timestamp if finished
DateTime? get endTimestamp;

Expand Down
21 changes: 21 additions & 0 deletions dart/lib/src/sentry_trace_origins.dart
@@ -0,0 +1,21 @@
import 'package:meta/meta.dart';

@internal
class SentryTraceOrigins {
static const manual = 'manual';

static const autoNavigationRouteObserver = 'auto.navigation.route_observer';
static const autoHttpHttp = 'auto.http.http';
static const autoHttpDioHttpClientAdapter =
'auto.http.dio.http_client_adapter';
static const autoHttpDioTransformer = 'auto.http.dio.transformer';
static const autoFile = 'auto.file';
static const autoFileAssetBundle = 'auto.file.asset_bundle';
static const autoDbSqfliteOpenDatabase = 'auto.db.sqflite.open_database';
static const autoDbSqfliteBatch = 'auto.db.sqflite.batch';
static const autoDbSqfliteDatabase = 'auto.db.sqflite.database';
static const autoDbSqfliteDatabaseExecutor =
'auto.db.sqflite.database_executor';
static const autoDbSqfliteDatabaseFactory =
'auto.db.sqflite.database_factory';
}
6 changes: 6 additions & 0 deletions dart/lib/src/sentry_tracer.dart
Expand Up @@ -255,6 +255,12 @@ class SentryTracer extends ISentrySpan {
@override
SentrySpanContext get context => _rootSpan.context;

@override
String? get origin => _rootSpan.origin;

@override
set origin(String? origin) => _rootSpan.origin = origin;

@override
DateTime get startTimestamp => _rootSpan.startTimestamp;

Expand Down
6 changes: 6 additions & 0 deletions dart/lib/src/sentry_transaction_context.dart
@@ -1,4 +1,5 @@
import 'package:meta/meta.dart';
import 'sentry_trace_origins.dart';

import 'protocol.dart';
import 'sentry_baggage.dart';
Expand All @@ -21,12 +22,14 @@ class SentryTransactionContext extends SentrySpanContext {
SpanId? parentSpanId,
this.transactionNameSource,
this.samplingDecision,
String? origin,
}) : super(
operation: operation,
description: description,
traceId: traceId,
spanId: spanId,
parentSpanId: parentSpanId,
origin: origin,
denrase marked this conversation as resolved.
Show resolved Hide resolved
);

factory SentryTransactionContext.fromSentryTrace(
Expand All @@ -50,6 +53,7 @@ class SentryTransactionContext extends SentrySpanContext {
: null,
transactionNameSource:
transactionNameSource ?? SentryTransactionNameSource.custom,
origin: SentryTraceOrigins.manual,
);
}

Expand All @@ -63,6 +67,7 @@ class SentryTransactionContext extends SentrySpanContext {
SpanId? parentSpanId,
SentryTransactionNameSource? transactionNameSource,
SentryTracesSamplingDecision? samplingDecision,
String? origin,
}) =>
SentryTransactionContext(
name ?? this.name,
Expand All @@ -76,5 +81,6 @@ class SentryTransactionContext extends SentrySpanContext {
transactionNameSource:
transactionNameSource ?? this.transactionNameSource,
samplingDecision: samplingDecision ?? this.samplingDecision,
origin: origin ?? this.origin,
);
}
1 change: 1 addition & 0 deletions dart/test/http_client/tracing_client_test.dart
Expand Up @@ -44,6 +44,7 @@ void main() {
expect(span.data['http.fragment'], 'baz');
expect(span.data['http.response.status_code'], 200);
expect(span.data['http.response_content_length'], 2);
expect(span.origin, SentryTraceOrigins.autoHttpHttp);
});

test('finish span if errored request', () async {
Expand Down
17 changes: 17 additions & 0 deletions dart/test/hub_test.dart
Expand Up @@ -176,6 +176,7 @@ void main() {
expect(tr.context.description, 'desc');
expect(tr.startTimestamp.isAtSameMomentAs(startTime), true);
expect((tr as SentryTracer).name, 'name');
expect(tr.origin, SentryTraceOrigins.manual);
});

test('start transaction binds span to the scope', () async {
Expand Down Expand Up @@ -265,6 +266,22 @@ void main() {
expect(tr.samplingDecision?.sampled, false);
});

test('start transaction with context sets trace origin fallback', () async {
final hub = fixture.getSut();
final tr = hub.startTransactionWithContext(
SentryTransactionContext('name', 'op'),
);
expect(tr.origin, SentryTraceOrigins.manual);
});

test('start transaction with context keeps origin', () async {
final hub = fixture.getSut();
final tr = hub.startTransactionWithContext(
SentryTransactionContext('name', 'op', origin: 'auto.navigation.test'),
);
expect(tr.origin, 'auto.navigation.test');
});

test('start transaction return NoOp if performance is disabled', () async {
final hub = fixture.getSut(tracesSampleRate: null);

Expand Down
12 changes: 7 additions & 5 deletions dart/test/sentry_span_context_test.dart
Expand Up @@ -14,9 +14,10 @@ void main() {
expect(map['op'], 'op');
expect(map['parent_span_id'], isNotNull);
expect(map['description'], 'desc');
expect(map['origin'], 'manual');
});

test('toTraceContext gets sampled and status', () {
test('toTraceContext gets sampled, status, and origin', () {
final sut = fixture.getSut();
final aborted = SpanStatus.aborted();
final traceContext = sut.toTraceContext(
Expand All @@ -31,15 +32,16 @@ void main() {
expect(traceContext.parentSpanId, isNotNull);
expect(traceContext.description, 'desc');
expect(traceContext.status, aborted);
expect(traceContext.origin, 'manual');
});
}

class Fixture {
SentrySpanContext getSut() {
return SentrySpanContext(
operation: 'op',
parentSpanId: SpanId.newId(),
description: 'desc',
);
operation: 'op',
parentSpanId: SpanId.newId(),
description: 'desc',
origin: 'manual');
}
}