Skip to main content
This guide covers everything you need to instrument your AdonisJS application with Monocle. You will learn how to:
  • Install and configure the agent
  • Track authenticated users across traces
  • Capture exceptions and custom messages
  • Use tracing helpers and decorators
  • Configure instrumentations (mail, cache, jobs, AI, MCP)
  • Fan out telemetry to multiple destinations

Overview

The agent includes Adonis instrumentation and the Node auto-instrumentation bundle. Add Mastra, Vercel AI, BullMQ, Bentocache, and MCP support explicitly so your application only installs the integrations it uses.
This guide uses @monocle.sh/adonisjs-agent 2.x. Upgrading from 1.x? Follow the migration guide.
Mail, Adonis queue, and Ace CLI tracing are built in. They activate automatically when their packages are available and keep their top-level mail, queue, and cli options. Optional mail and queue packages are resolved from your application; the agent does not install them.

Prerequisites

  • AdonisJS 6.2.0+ or AdonisJS 7.0.0+
  • A Monocle account with an API key

Installation

Install and configure the package using the Ace CLI.
  1. Creates config/monocle.ts configuration file
  2. Creates otel.ts initialization file at project root
  3. Adds the otel.ts import as the first import in bin/server.ts and bin/console.ts
  4. Registers the Monocle provider in adonisrc.ts
  5. Registers the Monocle middleware as the first router middleware
  6. Adds required environment variables to .env and start/env.ts
After running the command, add your API key to .env:
.env
You can find your API key in your application settings on the Monocle dashboard. That’s it. Your application now has automatic tracing for HTTP requests, database queries, Redis operations, and more.
The import order is critical.OpenTelemetry must initialize before any other code loads. The SDK needs to patch libraries like http, pg, and redis before they are imported. That is why otel.ts is imported as the very first line in bin/server.ts.If you move or remove the import '../otel.js' line, auto-instrumentation will not work.

Environment Variables

The agent requires these environment variables:
The APP_ENV variable determines which environment your telemetry data is associated with in Monocle. You can filter traces, logs, and metrics by environment using the environment selector in the dashboard.

Configuration

The configuration file is located at config/monocle.ts. Here is a minimal setup:
config/monocle.ts

Full configuration reference

All options are optional except apiKey, serviceName, serviceVersion, and environment.
config/monocle.ts

Customizing instrumentations

You can configure individual OpenTelemetry instrumentations by passing options keyed by their package name.
config/monocle.ts
Default ignored URLs include /health, /healthz, /ready, /readiness, /metrics, /favicon.ico and other common health check paths.

User Context

To associate telemetry data with authenticated users, call Monocle.setUser() in your authentication middleware. This lets you filter traces and exceptions by user in the dashboard.
app/middleware/silent_auth_middleware.ts
The name field takes priority in the Monocle UI, falling back to email, then id.
Do not include sensitive data (passwords, tokens, API keys) in user attributes. These values are sent to Monocle and will be visible in trace viewers.

Exception Tracking

Exceptions thrown during a request are automatically captured by the agent. It hooks into AdonisJS’s ExceptionHandler.report() method and respects your ignore rules (ignoreExceptions, ignoreStatuses, ignoreCodes).

Manual exception capture

You can manually capture exceptions anywhere in your code.
app/services/payment_service.ts

Capture messages

Use Monocle.captureMessage() to capture custom messages when you want to track something that is not an exception. Messages appear in the Exceptions dashboard alongside errors.
app/services/order_service.ts
Supported levels: debug, info, log, warning, error, fatal.

Tracing Helpers

Creating custom spans

Use record() to wrap a section of code in a span. This is useful when you want to measure the duration of a specific operation that is not automatically instrumented.
app/services/report_service.ts
record() handles both sync and async callbacks, automatically records exceptions, and closes the span when done.

Decorators

The @span() decorator wraps a single method in a span. The @spanAll() decorator wraps every public method in a class.
app/services/order_service.ts

Other helpers

Instrumentations

HTTP

HTTP tracing is configured with the top-level http option. Alongside the standard HTTP instrumentation options, Monocle adds few specific features:
  • sanitizeUrls to redact sensitive query parameters from URL span attributes
  • captureBodies to record request and response payloads on spans
Both features are disabled by default. Configure sanitizeUrls to enable URL sanitization. For body capture, set captureBodies.enabled: true, or opt in per side with incoming.request.enabled, incoming.response.enabled, and so on.
config/monocle.ts

URL sanitization

sanitizeUrls rewrites URL span attributes such as http.url, url.full, http.target, and url.query.
config/monocle.ts
For example, an OAuth callback like:
becomes:
For more control, you can provide a custom sanitize function that takes the full URL object and returns a sanitized string.
config/monocle.ts

Body capture scope

incoming captures traffic handled by your Adonis app:
  • incoming.request for the HTTP request body sent to your server
  • incoming.response for the HTTP response body returned by your server
outgoing captures traffic created by Node HTTP clients inside your app:
  • outgoing.request for the request body your app sends to another service
  • outgoing.response for the response body returned by that service
captureBodies.outgoing only applies to traffic instrumented by @opentelemetry/instrumentation-http, which means node:http and node:https. It does not cover fetch or undici.

Body capture defaults

captureBodies is opt-in because payload capture can expose sensitive data. When enabled, Monocle:
  • captures application/json and application/x-www-form-urlencoded by default
  • stores at most 10_000 bytes per request or response unless you increase maxBodySize
  • shows captured payloads in the HTTP Body tab of the trace details view
Body capture should be enabled deliberately and reviewed carefully. Payloads can contain credentials or sensitive information. Keep capture scoped to the endpoints you need, prefer the smallest possible maxBodySize, and use redact or transform to remove anything sensitive before it is exported.

Redaction order

captureBodies.redact applies declarative redaction rules first. captureBodies.transform runs after that and lets you mutate or replace the captured payload programmatically. The declarative redact rules extend Monocle’s built-in safe defaults. Common secrets such as password, token, code, access_token, refresh_token, authorization, and many others are redacted automatically even if you do not list them yourself.

Advanced overrides

If you need low-level OpenTelemetry overrides, you can still configure instrumentations["@opentelemetry/instrumentation-http"]. When both are present, the low-level instrumentation config takes priority over the top-level http option.

Mail

If @adonisjs/mail is installed, the agent automatically instruments all emails sent through the mail service. Every email appears as a span in your traces with subject, recipients, and transport info. You can monitor email activity in the dedicated Emails dashboard. To disable:
config/monocle.ts

Cache

Install the Bentocache integration explicitly to trace cache operations, including when using @adonisjs/cache. Keep bentocache as a direct application dependency so the integration uses the same instance as your cache service.
Terminal
config/monocle.ts
The defaults preserve the former cache configuration: keys are captured and sanitized, parent spans are not required, and internal Redis/L2 spans are suppressed. UUIDs, numeric IDs, and hex hashes in keys become *. Pass your previous cache options to bentocache(). Omit the integration or use bentocache({ enabled: false }) to disable it. See the Bentocache guide for customization.

Background Jobs

@adonisjs/queue

If @adonisjs/queue (boringqueue) is installed, the agent instruments job dispatch and execution. Jobs appear in the Jobs dashboard with execution count, error rate, and latency metrics.
config/monocle.ts

BullMQ

Install @monocle.sh/instrumentation-bullmq in your BullMQ application, then register bullmq() to trace job dispatch and processing.
Terminal
config/monocle.ts
Consumer spans link to producer spans by default. Set useProducerSpanAsConsumerParent: true to keep both in the same trace. See the BullMQ guide for all options. Omit bullmq() to disable the Monocle BullMQ integration. Use queue: false to disable the separate Adonis queue integration. The Node auto-instrumentation bundle can still trace underlying Redis operations independently.

Sampling noisy jobs

Use the sampling(ctx) hook to reduce trace volume for high-throughput jobs while keeping failed executions.
config/monocle.ts
See Job Sampling for all sampling rules and caveats.

AI SDK

Install the Vercel AI integration and register vercelAi() to trace AI SDK calls, token usage, and costs.
Terminal
config/monocle.ts
Omit vercelAi() to disable this integration. See the Vercel AI guide for supported operations and recording options.

Conversation tracking

Import withConversationId() directly from the integration package to group AI calls in the Conversations tab.
app/services/chat_service.ts

Mastra

Install the Mastra integration and register mastra() to normalize spans from your Mastra OpenTelemetry bridge. Configure the bridge using the Mastra guide.
Terminal
config/monocle.ts
Mastra recording options are independent of vercelAi() options. Set them on both integrations if you use both. Omit mastra() to disable normalization.

CLI Commands

Ace CLI command execution is traced by default. Scaffolding commands (make:*, generate:*) and long-running queue workers are excluded automatically. Command arguments and flags are captured as span attributes (cli.args.*, cli.flags.*).
config/monocle.ts
To disable entirely:
config/monocle.ts
CLI tracing requires otel.ts in bin/console.ts.Just like bin/server.ts, your bin/console.ts file must import otel.ts as its very first import for CLI instrumentation to work. The node ace configure command adds this automatically, but if you set up manually or upgraded from an older version, make sure it is there:
bin/console.ts

MCP Server

Install the MCP integration explicitly, then attach it to your server instance. MCP does not need an integrations entry.
Terminal
app/mcp/server.ts

Multi-Destination OTLP

You can send telemetry to additional OTLP backends alongside Monocle. The Monocle destination is always injected automatically.
config/monocle.ts
Each destination receives the full telemetry data (traces, metrics, logs).

Disabling Telemetry

If no API key is provided, telemetry is automatically disabled. This is useful for local development.
.env.development

Migrating from @adonisjs/otel

If you are already using @adonisjs/otel, switching to the Monocle agent is straightforward. The agent wraps @adonisjs/otel and provides the same API with additional capabilities.

1. Swap the package

2. Rename config file

Rename config/otel.ts to config/monocle.ts and replace defineConfig import:
config/monocle.ts

3. Update all imports

Replace all @adonisjs/otel imports with their Monocle equivalents:

Why use Monocle’s helpers

The Monocle agent re-exports most helpers from @adonisjs/otel unchanged (getCurrentSpan, setAttributes, recordEvent, etc.). However, record, handleError, @span, and @spanAll are enhanced versions that add source code context extraction. When an exception is caught by these helpers, the agent reads the actual source files from disk and attaches the surrounding lines of code to the span. This is what powers the source code preview in the Monocle exception viewer. You get the exact line that errored with surrounding context, without needing source maps. The agent also fully serializes the error cause chain (Error.cause), including AggregateError children, so nested errors are never lost. These enhancements only work when importing from @monocle.sh/adonisjs-agent. If you keep using @adonisjs/otel imports directly, you will get standard OpenTelemetry error recording without the extra context.