Sentry Link (GraphQL)

pub package likes popularity pub points

Compatibility list

This integration is compatible with the following packages. It's also compatible with other packages which are build on gql suite of packages.

packagestats
gql_linklikes popularity pub points
graphqllikes popularity pub points
ferrylikes popularity pub points
artemislikes popularity pub points

Usage

Just add SentryLink.link() and/or SentryTracingLink to your links. It will add error reporting and performance monitoring to your GraphQL operations.

final link = Link.from([
    AuthLink(getToken: () async => 'Bearer $personalAccessToken'),
    // SentryLink records exceptions
    SentryLink.link(),
    // SentryTracingLink adds performance tracing with Sentry
    SentryTracingLink(shouldStartTransaction: true),
    HttpLink('https://api.github.com/graphql'),
]);

In addition to that, you can add GqlEventProcessor to Sentry's event processor, to improve support for nested LinkExceptions and its subclasses.

A GraphQL error will be reported like the following screenshot:

SentryBreadcrumbLink

The SentryBreadcrumbLink adds breadcrumbs for every succesful GraphQL operation. Failed operations can be added as breadcrumbs via SentryLink.link().

SentryResponseParser and SentryRequestSerializer

The SentryResponseParser and SentryRequestSerializer classes can be used to trace the serialization process. Both classes work with HttpLink and DioLink. When using the HttpLink, you can additionally use the sentryResponseDecoder function.

HttpLink example

import 'package:sentry_link/sentry_link.dart';

final link = Link.from([
    SentryLink.link(),
    AuthLink(getToken: () async => 'Bearer $personalAccessToken'),
    SentryTracingLink(shouldStartTransaction: true),
    HttpLink(
      'https://api.github.com/graphql',
      httpClient: SentryHttpClient(networkTracing: true),
      serializer: SentryRequestSerializer(),
      parser: SentryResponseParser(),
    ),
  ]);

DioLink example

This example also uses the sentry_dio integration.

import 'package:sentry_link/sentry_link.dart';
import 'package:sentry_dio/sentry_dio.dart';

final link = Link.from([
    SentryLink.link(),
    AuthLink(getToken: () async => 'Bearer $personalAccessToken'),
    SentryTracingLink(shouldStartTransaction: true),
    DioLink(
      'https://api.github.com/graphql',
      client: Dio()..addSentry(networkTracing: true),
      serializer: SentryRequestSerializer(),
      parser: SentryResponseParser(),
    ),
  ]);
HttpLink

Bonus HttpLink tracing

import 'dart:async';
import 'dart:convert';

import 'package:sentry/sentry.dart';
import 'package:http/http.dart' as http;

import 'package:sentry_link/sentry_link.dart';

final link = Link.from([
  SentryLink.link(),
  SentryTracingLink(shouldStartTransaction: true),
  AuthLink(getToken: () async => 'Bearer $personalAccessToken'),
  HttpLink(
    'https://api.github.com/graphql',
    httpClient: SentryHttpClient(networkTracing: true),
    serializer: SentryRequestSerializer(),
    parser: SentryResponseParser(),
    httpResponseDecoder: sentryResponseDecoder,
  ),
]);

Map<String, dynamic>? sentryResponseDecoder(
  http.Response response, {
  Hub? hub,
}) {
  final currentHub = hub ?? HubAdapter();
  final span = currentHub.getSpan()?.startChild(
        'serialize.http.client',
        description: 'http response deserialization',
      );
  Map<String, dynamic>? result;
  try {
    result = _defaultHttpResponseDecoder(response);
    span?.status = const SpanStatus.ok();
  } catch (e) {
    span?.status = const SpanStatus.unknownError();
    span?.throwable = e;
    rethrow;
  } finally {
    unawaited(span?.finish());
  }
  return result;
}

Map<String, dynamic>? _defaultHttpResponseDecoder(http.Response httpResponse) {
  return json.decode(utf8.decode(httpResponse.bodyBytes))
      as Map<String, dynamic>?;
}

📣 About the author

  • Twitter Follow
  • GitHub followers

Libraries