Custom Instrumentation
To capture transactions customized to your organization's needs, you must first set up performance monitoring.
To instrument certain regions of your code, you can create transactions to capture them.
The following example creates a transaction that contains an expensive operation (for example, processOrderBatch
), and sends the result to Sentry:
import 'package:sentry/sentry.dart';
final transaction = Sentry.startTransaction('processOrderBatch()', 'task');
try {
processOrderBatch();
} catch (exception) {
transaction.throwable = exception;
transaction.status = SpanStatus.internalError();
} finally {
await transaction.finish();
}
Add More Spans to the Transaction
By default, transactions are not bound to the scope. Transaction has to be passed manually as a method parameter to enable attaching nested spans. When creating nested span, you can choose the value of operation
and description
.
import 'package:sentry/sentry.dart';
final transaction = Sentry.startTransaction('processOrderBatch()', 'task');
try {
await processOrderBatch(transaction);
} catch (exception) {
transaction.throwable = exception;
transaction.status = SpanStatus.internalError();
} finally {
await transaction.finish();
}
Future<void> processOrderBatch(ISentrySpan span) async {
// span operation: task, span description: operation
final innerSpan = span.startChild('task', description: 'operation');
try {
// omitted code
} catch (exception) {
innerSpan.throwable = exception;
innerSpan.status = SpanStatus.notFound();
} finally {
await innerSpan.finish();
}
}
Keep in mind that each individual span also needs to be manually finished;
Spans are sent together with their parent transaction when the transaction is finished. Make sure to call finish()
on transaction once all the child spans have finished.
Retrieve a Transaction
In cases where you want to attach Spans to an already ongoing Transaction you can use Sentry#getSpan
. This method will return a SentryTransaction
in case there is a running Transaction, otherwise it returns null
.
import 'package:sentry/sentry.dart';
final span = Sentry.getSpan()?.startChild('task') ??
Sentry.startTransaction('processOrderBatch()', 'task');
try {
processOrderBatch();
} catch (exception) {
span.throwable = exception;
span.status = SpanStatus.internalError();
} finally {
await span.finish();
}
Connect Errors with Spans
Sentry errors can be linked with transactions and spans.
Errors reported to Sentry while transaction or span bound to the scope is running are linked automatically:
import 'package:sentry/sentry.dart';
final transaction = Sentry.startTransaction(
'processOrderBatch()',
'task',
bindToScope: true,
);
try {
processOrderBatch();
} catch (exception) {
Sentry.captureException(exception);
} finally {
await transaction.finish();
}
Exceptions may be thrown within spans that can finish before exception gets reported to Sentry. To attach span information to this exception, you must link it by calling the throwable
setter method:
import 'package:sentry/sentry.dart';
final transaction = Sentry.startTransaction('processOrderBatch()', 'task');
try {
processOrderBatch();
} catch (exception) {
transaction.throwable = exception;
rethrow;
} finally {
await transaction.finish();
}
Distributed Tracing
Traces can bridge across multiple software services. Each span in a trace can be represented as a sentry-trace
header, containing the trace id, span id, and sampling details. This sentry-trace
header can be passed to downstream services so that they can create spans that are a continuation of the trace started in the originating service.
To obtain a trace header from the span, use ISentrySpan#toSentryTrace()
method. Then pass it to the downstream service. If the communication happens over HTTP, it is recommended that you set the value to the sentry-trace
HTTP header.
To create a span as a continuation of the trace retrieved from the upstream service, pass the sentry-trace
header value to the transaction context:
final header = request.headers['sentry-trace'];
final sentryTraceHeader = SentryTraceHeader.fromTraceHeader(header);
try {
final transaction = Sentry.startTransactionWithContext(SentryTransactionContext.fromSentryTrace('name', 'operation', sentryTraceHeader));
} catch (error) {
// handle [InvalidSentryTraceHeaderException] if invalid `sentry-trace` header.
}
The SentryHttpClient
instrumentation handles trace continuations automatically when enabling the networkTracing
feature.
- Package:
- pub:sentry_flutter
- Version:
- 8.6.0
- Repository:
- https://github.com/getsentry/sentry-dart