Skip to content

Commit c75fe4f

Browse files
feat(flutter): Add failing request demos to the example
Two buttons request a 404 inside a span, through the http and Dio integrations, so the error-to-http.client-span link can be checked in Sentry. The dialog shows the trace id to search for. Co-Authored-By: Cursor <cursoragent@cursor.com>
1 parent 1b3c2c5 commit c75fe4f

1 file changed

Lines changed: 83 additions & 0 deletions

File tree

packages/flutter/example/lib/screens/performance_screen.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,23 @@ class PerformanceScreen extends StatelessWidget {
182182
'Demonstrates the new SpanV2 API with streaming trace lifecycle. Creates spans and sets attributes.',
183183
buttonTitle: 'Emit SpanV2',
184184
),
185+
if (Sentry.currentHub.options.traceLifecycle ==
186+
SentryTraceLifecycle.stream) ...[
187+
TooltipButton(
188+
onPressed: () => makeFailingWebRequest(context),
189+
key: const Key('http_failing_request'),
190+
text:
191+
'Requests a 404 inside a span. The captured error should be linked to the http.client span in Sentry.',
192+
buttonTitle: 'Dart: Failing web request',
193+
),
194+
TooltipButton(
195+
onPressed: () => makeFailingWebRequestWithDio(context),
196+
key: const Key('dio_failing_request'),
197+
text:
198+
'Requests a 404 through Dio inside a span. The captured error should be linked to the http.client span in Sentry.',
199+
buttonTitle: 'Dio: Failing web request',
200+
),
201+
],
185202
],
186203
),
187204
),
@@ -343,6 +360,72 @@ Future<void> makeWebRequest(BuildContext context) async {
343360
}
344361
}
345362

363+
/// A URL that reliably answers 404, to demo linking an error to its
364+
/// `http.client` span.
365+
final _failingUrl = Uri.parse('${exampleUrl}0');
366+
367+
final _failingStatusCodes = [SentryStatusCode(404)];
368+
369+
Future<void> makeFailingWebRequest(BuildContext context) async {
370+
final client = SentryHttpClient(
371+
failedRequestStatusCodes: _failingStatusCodes,
372+
);
373+
374+
late SentryId traceId;
375+
int? statusCode;
376+
await Sentry.startSpan('http-failing-request', (span) async {
377+
traceId = span.traceId;
378+
statusCode = (await client.get(_failingUrl)).statusCode;
379+
});
380+
381+
if (!context.mounted) return;
382+
await _showLinkedErrorDialog(context, traceId, statusCode);
383+
}
384+
385+
Future<void> makeFailingWebRequestWithDio(BuildContext context) async {
386+
final dio = Dio();
387+
dio.addSentry(failedRequestStatusCodes: _failingStatusCodes);
388+
389+
late SentryId traceId;
390+
int? statusCode;
391+
await Sentry.startSpan('dio-failing-request', (span) async {
392+
traceId = span.traceId;
393+
try {
394+
await dio.getUri<String>(_failingUrl);
395+
} on DioException catch (exception) {
396+
statusCode = exception.response?.statusCode;
397+
}
398+
});
399+
400+
if (!context.mounted) return;
401+
await _showLinkedErrorDialog(context, traceId, statusCode);
402+
}
403+
404+
Future<void> _showLinkedErrorDialog(
405+
BuildContext context,
406+
SentryId traceId,
407+
int? statusCode,
408+
) async {
409+
await showDialog<void>(
410+
context: context,
411+
builder: (context) {
412+
return AlertDialog(
413+
title: Text('Captured $statusCode'),
414+
content: SelectableText(
415+
'Search this trace in Sentry to see the error linked to the '
416+
'http.client span:\n\n$traceId',
417+
),
418+
actions: [
419+
MaterialButton(
420+
onPressed: () => Navigator.pop(context),
421+
child: const Text('Close'),
422+
),
423+
],
424+
);
425+
},
426+
);
427+
}
428+
346429
Future<void> _showWebResponseDialog(
347430
BuildContext context, int? statusCode, String body) async {
348431
await showDialog<void>(

0 commit comments

Comments
 (0)