Monocle stores standard OpenTelemetry data: any span, log, or metric you send is kept and searchable. The dashboards, however, need to know what a span represents. Is it an HTTP request? A SQL query? A job? To answer, Monocle relies on attribute names.
Most of them are the official OpenTelemetry semantic conventions. Where OpenTelemetry has no convention yet, for example cache operations, emails, or CLI commands, Monocle defines its own. This page lists them all, dashboard by dashboard.
You only need this page to write your own instrumentation, an SDK for another language, or to debug a dashboard that stays empty. The Monocle SDKs and instrumentations already emit everything listed here.
How spans are classified
Each span gets a type from the first rule it matches:
| Order | Rule | Type | Dashboard |
|---|---|---|---|
| 1 | Span kind SERVER with http.request.method | HTTP request | Requests |
| 2 | Span kind CLIENT with db.system.name | Database query | Queries |
| 3 | Span kind CLIENT with http.request.method | External call | External Calls |
| 4 | Has cache.operation | Cache operation | Cache |
| 5 | Has mcp.method.name | MCP call | MCP Monitoring |
| 6 | Has messaging.system | Job | Jobs |
| 7 | entry_point.type is cli | Command | Commands |
| 8 | Has gen_ai.operation.name | AI operation | AI Agents |
The span kind matters: a database client span with the INTERNAL kind won't appear in Queries.
Service segments
A segment is the part of a trace that runs in one service. Its first span carries the context of the request, job, or command: the route, the user, the command name. Exceptions, queries, and AI calls take their context from the segment of their own service, not from the root of the trace.
A span starts a segment when it is the root of the trace, or when its parent ran in another process. Monocle reads the second case from the OTLP span flags. CLIENT and PRODUCER spans never start a segment. Without span flags, SERVER and CONSUMER spans start a segment. See Trace across services.
Legacy attribute names
Many instrumentations still emit older names. Monocle renames them on ingestion, so both work. When both are present, the new name wins.
| Legacy | Current |
|---|---|
http.method | http.request.method |
http.status_code | http.response.status_code |
http.target | url.path |
http.url | url.full |
net.peer.name | server.address |
net.peer.port | server.port |
db.system | db.system.name |
db.statement | db.query.text |
db.operation | db.operation.name |
db.sql.table | db.collection.name |
db.name | db.namespace |
Resource attributes
| Attribute | Used for |
|---|---|
service.name | The service. With a DSN, Monocle replaces it with the name of the DSN's service. |
service.version | The release. A new value on entry spans records a deployment. Also shown on each issue occurrence. |
vcs.ref.head.revision | The full commit SHA. Links a semver release to its commit, so a deployment declared with commitSha finds it. |
vcs.repository.url.full | The repository URL, such as https://github.com/acme/shop. Turns commits into links in the deployment panel. |
deployment.id | The deployment ID of your platform. Stored with the telemetry. |
service.instance.id | Required for an instance to appear in System Metrics |
host.name | Display |
Monocle ignores the placeholder versions 0.0.0, 0.0.1, 1.0.0, unknown, dev, and latest. Monocle agents set these attributes for you, and add monocle.service.version.source to say where the version came from.
The environment is not read from deployment.environment.name: it comes from the x-monocle-env header. See Any OpenTelemetry SDK.
HTTP requests
Spec: HTTP spans
| Attribute | Required | Used for |
|---|---|---|
Span kind SERVER | Yes | Telling incoming requests from outgoing calls |
http.request.method | Yes | Detecting a request |
http.route | Recommended | Grouping by endpoint (/users/:id). Without it, requests are grouped by path. |
url.path | No | Fallback when there is no route |
http.response.status_code | No | 2xx, 4xx, and 5xx breakdown, error rates |
http.connection_type | No | sse or websocket excludes long-lived connections from latency stats |
monocle.http.request.body, monocle.http.response.body | No | The HTTP Body tab of a span (body capture) |
Database queries
Spec: Database spans
| Attribute | Required | Used for |
|---|---|---|
Span kind CLIENT | Yes | Detecting a query |
db.system.name | Yes | Detecting a query, database selector |
db.query.text | No | Query pattern. Falls back to the span name. |
db.operation.name | No | Operation column (SELECT, INSERT…) |
db.collection.name | No | Table |
db.namespace | No | Database name |
Send parameterized SQL (WHERE id = $1) in db.query.text so that queries group well. Redis commands are not listed in Queries.
External calls
Spec: HTTP client spans
| Attribute | Required | Used for |
|---|---|---|
Span kind CLIENT | Yes | Detecting an outgoing call |
http.request.method | Yes | Detecting an outgoing call |
server.address | Recommended | Grouping by domain, and detecting calls to your own services |
url.template | No | URL pattern (/orders/{id}) |
url.full | No | URL pattern when there is no template, IDs replaced |
http.response.status_code | No | Errors, for statuses of 400 and above |
Exceptions and issues
Spec: Exceptions on spans
The simplest way is to record exceptions on spans with span.recordException(error). Monocle turns every span event named exception into an exception, and copies the span's user.* attributes onto it.
| Attribute | Required | Used for |
|---|---|---|
exception.type | Yes | Title and grouping |
exception.message | No | Message and grouping |
exception.stacktrace | No | Stack trace and grouping |
Monocle-specific attributes add more context:
| Attribute | Used for |
|---|---|
monocle.exception.frames | Source code around each frame, as JSON |
monocle.exception.cause_chain | The Error.cause chain |
monocle.exception.values | Structured exceptions, for AggregateError and causes |
monocle.exception.should_report | false drops the exception |
monocle.message.level | Level of captured messages (info, warning, error…) |
monocle.tag.*, monocle.extra.* | Tags and extra data shown on the exception |
You can also send exceptions as log records with the exception.* attributes and monocle.log.source=exception_reporter.
Logs
Spec: Logs data model
Any log record is accepted. Monocle reads the body, the trace and span IDs, and the severity text (INFO, WARN, ERROR…), which drives levels and counters. All attributes are searchable.
Users
Spec: User attributes
| Attribute | Required | Used for |
|---|---|---|
user.id | Yes | Identifying the user, on SERVER spans |
user.email | No | Display |
user.name | No | Display, takes priority over the email |
enduser.id is not read.
Jobs
Spec: Messaging spans
| Attribute | Required | Used for |
|---|---|---|
messaging.system | Yes | Detecting a job (bullmq, boringqueue…) |
messaging.operation.type | Yes | send or create for dispatches, process for executions |
messaging.job.name | Recommended | Grouping by job. Monocle-specific. |
messaging.destination.name | No | Queue name |
messaging.message.id | No | Job ID |
messaging.message.retry.count | No | Retries |
messaging.job.queue_time_ms | No | Time spent waiting in the queue. Monocle-specific. |
Link the execution span to the dispatch span with a span link to connect both traces. See Jobs.
Cache
OpenTelemetry has no cache conventions; these attributes are Monocle's.
| Attribute | Required | Used for |
|---|---|---|
cache.operation | Yes | Detecting a cache operation (get, set, getOrSet…) |
cache.key | No | Per-key table |
cache.hit | No | true or false, for hit rates on get and getOrSet |
cache.store | No | Store name |
Emails
OpenTelemetry has no email conventions; these attributes are Monocle's. Spans use the CLIENT kind.
| Attribute | Required | Used for |
|---|---|---|
email.system | Yes | Must be adonisjs-mail |
email.operation | Yes | Must be send |
email.transport | No | Transport column |
email.message.subject | No | Subject |
email.message.from | No | Sender |
email.message.to | No | Recipients, as a JSON array |
email.recipient_count | No | Number of recipients |
email.message.id | No | Message ID |
CLI commands
These attributes are Monocle's. They go on the root span of the command.
| Attribute | Required | Used for |
|---|---|---|
entry_point.type | Yes | Must be cli |
cli.command.name | Yes | Grouping by command |
cli.command.description | No | Display |
cli.args.*, cli.flags.* | No | Arguments of each execution |
AI
Spec: GenAI spans
| Attribute | Required | Used for |
|---|---|---|
gen_ai.operation.name | Yes | chat, execute_tool, invoke_agent… |
gen_ai.request.model, gen_ai.response.model | Recommended | Models table and cost |
gen_ai.usage.input_tokens, gen_ai.usage.output_tokens | Recommended | Token usage and cost |
gen_ai.usage.input_tokens.cached | No | Cached tokens |
gen_ai.tool.name | No | Tools table |
gen_ai.conversation.id | No | Conversations tab |
gen_ai.input.messages, gen_ai.response.text | No | Prompt and response previews |
Monocle computes the cost from the model and token counts. Evaluation scores are read from span events named gen_ai.evaluation.result, with gen_ai.evaluation.name and gen_ai.evaluation.score.value.
MCP
Spec: MCP
| Attribute | Required | Used for |
|---|---|---|
mcp.method.name | Yes | Detecting an MCP call |
mcp.tool.name | No | Tools table |
mcp.client.name, mcp.client.version | No | Clients table |
mcp.tool.result.is_error | No | Errors |
System metrics
Specs: Process metrics, Node.js runtime metrics
System Metrics reads process.cpu.utilization (with process.cpu.state), process.memory.usage, v8js.memory.heap.used, v8js.memory.heap.limit, nodejs.eventloop.utilization, and nodejs.eventloop.delay.p99. Every other metric appears in the Metrics explorer.
Reserved attributes
Monocle sets monocle.* attributes itself on ingestion, such as the organization, project, environment, and service IDs. Values sent by your application for these keys are overwritten. Apart from monocle.http.*, monocle.tag.*, and monocle.extra.*, monocle.* attributes are hidden in the dashboard.