captureEvent method

Future<SentryId> captureEvent(
  1. SentryEvent event, {
  2. Scope? scope,
  3. dynamic stackTrace,
  4. Hint? hint,
})

Reports an event to Sentry.io.

Implementation

Future<SentryId> captureEvent(
  SentryEvent event, {
  Scope? scope,
  dynamic stackTrace,
  Hint? hint,
}) async {
  if (_isIgnoredError(event)) {
    internalLogger.debug(
      'Error was ignored as specified in the ignoredErrors options.',
    );
    _options.recorder.recordLostEvent(
      DiscardReason.ignored,
      _getCategory(event),
    );
    return _emptySentryId;
  }

  if (_options.containsIgnoredExceptionForType(event.throwable)) {
    internalLogger.debug(
      () =>
          'Event was dropped as the exception ${event.throwable.runtimeType.toString()} is ignored.',
    );
    _options.recorder.recordLostEvent(
      DiscardReason.eventProcessor,
      _getCategory(event),
    );
    return _emptySentryId;
  }

  hint ??= Hint();

  SentryEvent? preparedEvent = _prepareEvent(
    event,
    hint,
    stackTrace: stackTrace,
  );

  if (scope != null) {
    preparedEvent = await scope.applyToEvent(preparedEvent, hint);
  } else {
    internalLogger.debug('No scope to apply on event was provided');
  }

  // dropped by scope event processors
  if (preparedEvent == null) {
    return _emptySentryId;
  }

  preparedEvent = await runEventProcessors(
    preparedEvent,
    hint,
    _options.eventProcessors,
    _options,
  );

  // dropped by event processors
  if (preparedEvent == null) {
    return _emptySentryId;
  }

  preparedEvent = _createUserOrSetDefaultIpAddress(preparedEvent);

  preparedEvent = await _runBeforeSend(preparedEvent, hint);

  // dropped by beforeSend
  if (preparedEvent == null) {
    return _emptySentryId;
  }

  // Sampling runs last so that the filters above, which the developer
  // controls, always get the final say on whether an event is dropped.
  if (preparedEvent.type != 'feedback' && _sampleRate()) {
    final sampledOutEvent = preparedEvent;
    _options.recorder.recordLostEvent(
      DiscardReason.sampleRate,
      _getCategory(sampledOutEvent),
    );
    internalLogger.debug(
      () =>
          'Event ${sampledOutEvent.eventId} was dropped due to sampling decision.',
    );
    await _options.lifecycleRegistry.dispatchCallback(
      OnEventSampledOut(sampledOutEvent, hint),
    );
    return _emptySentryId;
  }

  // Event is fully processed and ready to be sent
  await _options.lifecycleRegistry.dispatchCallback(
    OnBeforeSendEvent(preparedEvent, hint),
  );

  var attachments = List<SentryAttachment>.from(scope?.attachments ?? []);
  attachments.addAll(hint.attachments);
  var screenshot = hint.screenshot;
  if (screenshot != null) {
    attachments.add(screenshot);
  }

  var viewHierarchy = hint.viewHierarchy;
  if (viewHierarchy != null && event.type != 'feedback') {
    attachments.add(viewHierarchy);
  }

  var traceContext = scope?.span?.traceContext();
  final activeSpan = scope?.getActiveSpan();
  if (activeSpan != null) {
    traceContext = activeSpan.resolveDsc();
  } else if (traceContext == null) {
    if (scope != null) {
      scope.propagationContext.baggage ??= SentryBaggage({})
        ..setValuesFromScope(scope, _options);
      traceContext = SentryTraceContextHeader.fromBaggage(
        scope.propagationContext.baggage!,
      );
    }
  } else {
    traceContext.replayId = scope?.replayId;
  }

  final envelope = SentryEnvelope.fromEvent(
    preparedEvent,
    _options.sdk,
    dsn: _options.dsn,
    traceContext: traceContext,
    attachments: attachments.isNotEmpty ? attachments : null,
  );

  final id = await captureEnvelope(envelope);
  return id ?? SentryId.empty();
}