Usage

Exception Reporting

Capture, enrich, and filter exceptions with HTTP context, user details, and smart fingerprinting.

Exception reporting in @eienjs/adonisjs-sentry is powered by the reportException function. It captures unhandled exceptions while automatically extracting contextual information from the current AdonisJS HttpContext.

Global Exception Handler

The standard way to report errors in AdonisJS is within app/exceptions/handler.ts:

app/exceptions/handler.ts
import type { HttpContext } from '@adonisjs/core/http';
import { ExceptionHandler } from '@adonisjs/core/http';
import { reportException } from '@eienjs/adonisjs-sentry';

export default class HttpExceptionHandler extends ExceptionHandler {
  async report(error: unknown, ctx: HttpContext) {
    reportException(error, ctx);

    await super.report(error, ctx);
  }
}
reportException returns the generated Sentry event ID string, or undefined if Sentry is disabled or the error was ignored.

Manual Exception Reporting

You can also call reportException manually in services, background queues, or scheduled jobs without an HttpContext:

app/services/billing_service.ts
import { reportException } from '@eienjs/adonisjs-sentry';

export class BillingService {
  async processPayment(orderId: string) {
    try {
      await this.chargeGateway(orderId);
    } catch (error) {
      // Captures the exception without HTTP context
      const eventId = reportException(error);
      // ... handle fallback
    }
  }

  private async chargeGateway(orderId: string): Promise<void> {
    // Process payment gateway charge
  }
}

How Errors Are Filtered

Before delivering any event to Sentry, reportException runs filtering checks against your rules defined in config/sentry.ts:

  1. Initialization check: If Sentry.isInitialized() is false, reporting is immediately skipped.
  2. HTTP Status filtering: If error.status exists (or is treated as 500 if absent) and matches ignoreStatuses, the error is discarded.
  3. Error Code filtering: If error.code matches any string in ignoreCodes, it is ignored.
  4. Exception Class filtering: If error instanceof exception matches any constructor in ignoreExceptions, it is ignored.
config/sentry.ts
export default defineConfig({
  // ...
  report: {
    ignoreStatuses: [401, 403, 404, 422],
    ignoreCodes: ['E_UNAUTHORIZED_ACCESS', 'E_VALIDATION_ERROR'],
    ignoreExceptions: [],
  },
});

Context and Tags Attached

When an HttpContext is supplied, reportException sets up an isolated Sentry scope with comprehensive diagnostic data:

Tags

  • error.code: The error code (e.g. E_ROW_NOT_FOUND).
  • http.status_code: The HTTP response code (e.g. 500, 400).
  • route: The matched route pattern (e.g. /api/v1/users/:id), falling back to ctx.routeKey or 'unknown'.
  • http.method: HTTP method in uppercase (e.g. GET, POST).
  • request_id: The unique request identifier from ctx.request.id().

Request Context

A structured context block named request is added to the event:

{
  "url": "https://api.example.com/users/42?include=profile",
  "method": "GET",
  "route": "/users/:id",
  "params": {
    "id": "42"
  }
}

Smart Fingerprinting by Error Code

In AdonisJS, built-in and custom exceptions typically define a unique code string such as E_ROW_NOT_FOUND or E_INVALID_CREDENTIALS.

By default (fingerprintByCode: true), reportException groups issues in Sentry using:

scope.setFingerprint(['{{ default }}', code]);

This prevents issues with dynamic error messages (such as "Cannot find user with ID 42" and "Cannot find user with ID 99") from creating hundreds of separate issues in your Sentry dashboard.

To disable this behavior and use Sentry's default grouping algorithms, set:

config/sentry.ts
export default defineConfig({
  // ...
  report: {
    fingerprintByCode: false,
  },
});

User Context and PII Protection

When @adonisjs/auth is installed and a user is authenticated, reportException automatically extracts ctx.auth.user and attaches it to the Sentry scope.

Privacy Default: User ID Only

By default, dataCollection.userInfo is set to false in config/sentry.ts. In this mode, only the user's id is transmitted:

{
  "user": {
    "id": "123"
  }
}

Enabling Full User Information

If your privacy policy and compliance requirements allow transmitting user emails and IP addresses, set dataCollection.userInfo: true:

config/sentry.ts
export default defineConfig({
  // ...
  dataCollection: {
    userInfo: true,
  },
});

With userInfo: true, the scope includes:

  • id: String(ctx.auth.user.id)
  • email: ctx.auth.user.email (if string)
  • ip_address: ctx.request.ip()

To completely disable user capturing, set captureUser: false inside report:

config/sentry.ts
export default defineConfig({
  // ...
  report: {
    captureUser: false,
  },
});