Skip to content
Maple Docs
Open app
Browse the docs
On this page

OpenTelemetry conventions

Maple's expected OpenTelemetry attributes, status codes, span kinds, and data model conventions.

Maple accepts telemetry over the OpenTelemetry Protocol (OTLP). This page describes the attributes and conventions Maple reads to build its dashboards, service map and analytics.

Maple stores every OTel attribute you send verbatim. A curated set gets special treatment: pre-extracted into indexed columns at ingest, exposed as short filter aliases, rendered as colored badges, used to draw the service map, or ranked higher in the log attribute chips. Most of these follow the OpenTelemetry semantic conventions. If your SDK emits standard attributes, you usually don’t need to do anything extra.

Audit with Claude Code: maple-audit reviews an existing setup against these conventions per service, with severities, and fixes the gaps. See the maple-audit skill.

Sending data

This page covers what to put on your telemetry. Endpoints, authentication headers, content types and the standard OTEL_* environment variables are in the Ingest API reference. To set up an SDK, start at Instrument your application.

Service identity

The bare minimum every span needs. service.name is the primary axis Maple groups by. Without it, spans go to a synthetic unknown_service bucket.

AttributeExampleWhat Maple does with it
service.nameapi, ingest, webRequired. Primary grouping for services list, service map, dashboards, alerts. Filter alias: service.
service.version1.4.2, c0b92f68Per-version slices on service overview. Hidden from log chips but always queryable.
service.namespacepaymentsLogical grouping above service.name. Hidden from log chips.
service.instance.idUUID per processDistinguishes replicas of the same service. Hidden from log chips.

Deployment and version tracking

Tag every span with these and you get per-environment and per-version slices across the services table, service map, and per-service overview.

AttributeExampleWhat Maple does with it
deployment.environment.nameproductionFilterable everywhere; per-env throughput / latency / error rate; environment chips in span detail.
deployment.environmentproductionLegacy alias, treated as the same value. Either spelling is accepted.
vcs.ref.head.revisionc0b92f68Git commit SHA. Enables release markers on charts and per-version metrics.
vcs.repository.url.fullhttps://github.com/acme/apiCanonical repo URL. Links telemetry to source.

vcs.repository.url.full and vcs.ref.head.revision are the OpenTelemetry semantic-convention keys. Use them exactly as named. Legacy spellings like deployment.commit_sha, git.repo, or app.repo_url are not read.

Set resource attributes via environment variable:

export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=production,vcs.repository.url.full=https://github.com/acme/api,vcs.ref.head.revision=abc123"

In the search bar, env, environment, and commit_sha are short aliases. See Filter aliases below.

Span status codes

Maple stores span status codes as title-case strings. Maple’s ingest converts the OTLP status enum on the way in:

OTLP valueStored asMeaning
0"Unset"Default. No explicit status set
1"Ok"Explicitly marked successful
2"Error"Span encountered an error

Set status through your SDK’s status API. You don’t need to convert anything yourself.

Title case matters when you filter or write queries. StatusCode = 'Error' matches. Uppercase (ERROR) or lowercase (error) variants match zero rows.

Only spans with status Error appear in error analytics.

Span kinds

KindDescriptionHow Maple Uses It
"Server"Incoming request handlerThroughput and error rate calculations. Callee side of a service map edge. Renders path-only HTTP routes.
"Client"Outgoing request to another serviceCaller side of a service map edge; database nodes; external dependencies. Renders host+path HTTP routes.
"Producer"Async message producerCaller side of a service map edge; messaging dependencies.
"Consumer"Async message consumerThroughput calculations. Callee side of a Producer edge.
"Internal"Default, synchronous in-process workTrace detail view.

Client spans get a small outgoing-arrow icon in HTTP labels and render their route as host+path so the destination is visible. Server spans render path-only. The service map and a service’s dependencies are built only from Client and Producer spans. A network call left on Internal does not appear on either.

HTTP attributes

The most heavily instrumented namespace. Maple extracts three fields into indexed columns at write time, then renders method, route, and status code in trace rows.

Fast columns

Filtering on these scans a small column instead of doing a per-row map lookup. The legacy and current OTel semconv names map to the same column. The first non-empty source wins, so you don’t need to migrate just for fast filtering.

Attribute(s)Indexed column
http.method, http.request.methodHttpMethod
http.route, url.path, http.targetHttpRoute
http.status_code, http.response.status_codeHttpStatusCode

Method color pills

http.method / http.request.method drives a colored pill on the span row:

MethodColor
GETBlue
POSTOrange
PUTGreen
PATCHGray
DELETERed
HEADGray
OPTIONSDark gray

Status badge tiers

http.status_code / http.response.status_code is rendered as a colored badge in the trace list:

Status rangeTone
5xxError (red)
4xxWarn (amber)
3xxBlue
1xx–2xxInfo (green)

In log chips, the same key scores 95, just below exception.*. See Attribute prominence scoring.

Route extraction and fallback chain

For full HTTP info, Maple tries each source in order until one matches:

  • Method: http.method → http.request.method → span name (e.g. http.server GET /path, or bare GET /path).
  • Route on server spans: http.route → http.target → url.path.
  • Route on client spans: http.route → parsed url.full / http.url (host+path) → server.address / net.peer.name combined with url.path / http.target.
  • Status: http.status_code → http.response.status_code.

If none of the route attributes are set, Maple falls back to the route in the span name.

So url.full (e.g. https://api.stripe.com/v1/charges) on a Client span is enough for route rendering. Emitting http.route is still preferred, because it’s a semantic path (/api/users/:id) instead of a high-cardinality URL.

Service map

The service map draws a node for each service and each database, and an edge for the calls between them. Calls to external HTTP hosts, message queues and RPC services are not drawn on the map. They are listed on the service’s Dependencies tab. Four rules make sure your spans show up correctly.

1. Service-to-service edges

Maple draws an edge when a Client or Producer span in one service has a child Server or Consumer span in another service, in the same trace. Two things make that work:

  • The callee is instrumented, so it records its own Server or Consumer span.
  • The caller propagates trace context (the traceparent header), so the callee’s span becomes a child of the client span.

Instrumented HTTP and RPC clients do both for you.

api:    GET /v1/users  (span.kind=Client, span_id=a1)
users:  GET /v1/users  (span.kind=Server, parent_span_id=a1)
                            └──> draws an edge api → users

peer.service does not draw edges. If the callee is not instrumented, or the caller drops traceparent, no edge is drawn. The call shows up at most as an external dependency on the caller’s Dependencies tab (see rule 3).

2. Database nodes

Set db.system.name and db.namespace on database Client spans. The legacy db.system spelling is also accepted. Maple keys each database node on the pair, so services that call the same database share one node.

SELECT * FROM users  (span.kind=Client, db.system.name=postgresql, db.namespace=users_db)
                            └──> draws an edge api → postgresql users_db

Without db.system.name, the call is treated as an external HTTP or other dependency, not a database. Without db.namespace, Maple falls back to the legacy db.name, then to the host (server.address). With none of these set, every database behind that driver collapses into one node.

3. External dependencies

Other outbound Client and Producer spans become external dependencies. They are listed on the calling service’s Dependencies tab, not drawn on the map. Maple names each one from these attributes:

Call typeAttributesDependency name
Messagingmessaging.system, messaging.destination.nameDestination name, or the system if missing
RPCrpc.system, rpc.servicerpc.service, or the system if missing
HTTP, otherserver.addressHost

HTTP client instrumentation sets server.address automatically.

4. Pick canonical names

Keep db.system.name, messaging.system, and rpc.system values spelled the same across services. If one service emits db.system.name=postgresql and another emits PostgreSQL, they become separate database nodes. Use the OpenTelemetry well-known values where one exists.

Database queries

Besides the service map, these drive the log chips and the AI error-debug prompt context.

AttributeWhat Maple does with it
db.system.name (legacy db.system)Scored 70 in log chips; with db.namespace, keys the service map database node; toned info in log chips.
db.namespaceNames the database node on the service map.
db.query.text (legacy db.statement)Scored 70; rendered in span detail; included as context in the error-debug prompt.
db.operation.name (legacy db.operation)Scored 70 (e.g. "SELECT", "INSERT").

Caching

Maple detects a cache span when cache.system or cache.result is present. When detected, the trace UI renders a hit/miss badge and an operation pill (GET / SET / DELETE) on the span row.

AttributeExampleWhat Maple does with it
cache.systemredis, memcachedIdentifies the cache backend; presence triggers cache-span detection.
cache.resulthit | missDrives the hit/miss badge color; presence also triggers cache-span detection.
cache.nameuser-sessionsLogical cache name shown in span detail.
cache.operationGET, SET, DELETEDrives the operation pill color.
cache.lookup_performedtrue | falseWhether a lookup was actually executed (string, not bool).

Errors and exceptions

Drives the error banner in the log detail panel and the highest-priority chip on every log row.

AttributeWhat Maple does with it
exception.messageBanner body. Falls back to error.message, then to the log body.
exception.typeMonospace badge beside the banner title. Falls back to error.type.
error.messageSame as exception.message (legacy fallback).
error.typeSame as exception.type (legacy fallback).

Any attribute matching exception.* scores 100 (top of the log chips) and is toned error (red).

If the message runs past 3 lines or 160 characters, the banner collapses by default and shows a “Show more” toggle.

RPC

For gRPC and other RPC frameworks.

AttributeWhat Maple does with it
rpc.systemNames RPC dependencies when rpc.service is missing.
rpc.serviceScored 68 in log chips; toned info. Names RPC dependencies.
rpc.methodScored 68; toned info.
rpc.grpc.status_codeScored 90 (just below HTTP status). Non-zero values are toned error (red).

User identity

Promotes user/customer context to the log chips so it’s visible at a glance on every log row.

AttributeWhat Maple does with it
user.id, enduser.id, customer.id, customer_idAll scored 66 in log chips (equal priority).

Logs

Severity levels

SeverityText drives the per-row text color in the log list and the trace detail timeline.

SeverityTextSeverityNumberColor theme
TRACE1-4severity-trace
DEBUG5-8severity-debug
INFO9-12severity-info
WARN13-16severity-warn
ERROR17-20severity-error
FATAL21-24severity-fatal

ERROR and FATAL severities also show the error banner at the top of the log detail panel.

Trace correlation

Logs are automatically correlated with traces when TraceId and SpanId fields are present. Most OTel SDKs inject these fields when a span is active.

Kubernetes and infrastructure

Kubernetes resource attributes power the service map’s pod-count badges and the Infrastructure pages. The maple-k8s-infra Helm chart sets most of these for you via the OTel operator and the k8sattributes processor.

Workload identity (joins to service.name)

AttributeWhat Maple does with it
k8s.deployment.namePrimary workload identity. With k8s.namespace.name, joins to service.name for infrastructure data.
k8s.statefulset.nameSame join, for stateful workloads.
k8s.daemonset.nameSame join, for DaemonSets.
k8s.job.nameJob filter and pod detail on the Infrastructure pages. Not part of the service join.
k8s.cluster.nameCluster shown on the Infrastructure pages. Not part of the service join.

Resource attributes normally stay out of log chips. These are the exceptions, along with deployment.environment.

AttributeWhat Maple does with it
k8s.pod.namePromoted to log attribute chips.
k8s.namespace.namePromoted to log attribute chips.
cloud.regionPromoted to log attribute chips.

Node detail metadata

AttributeWhat Maple does with it
k8s.node.nameRequired to match node metrics from kubelet; node-list and node-detail views.
k8s.node.uidDisplay in node metadata panel.
k8s.pod.uidUsed to count distinct pods per workload.
k8s.kubelet.versionDisplay in node metadata panel.
container.runtimeDisplay in K8s node metadata (containerd, cri-o, etc.).

Cloud and platform badges

These set the platform badge and runtime icon next to a service on the service map. SDKs running on common platforms detect most of them automatically. The keys are listed here so self-instrumenters can match.

AttributeExample valuesWhat Maple does with it
cloud.providercloudflarecloudflare sets the Cloudflare badge.
cloud.platformcloudflare.workers, aws_lambdacloudflare.workers sets the Cloudflare badge; aws_lambda sets the Lambda badge.
cloud.regionus-west-2, iad1Promoted to log chips (see Kubernetes section above).
process.runtime.namenodejs, bun, deno, workerd, rust, jvmRuntime mark on the service map.
faas.nameLambda function name, Worker script nameAny value sets the Lambda badge unless the service is on Cloudflare. Matches Cloudflare Worker scripts to their service.
faas.versionFunction version / revisionShown as the script version on Cloudflare Workers.

A service with k8s.pod.name or k8s.deployment.name gets the Kubernetes badge. Cloudflare takes precedence over Lambda, and Lambda over Kubernetes.

nodejs, bun, deno, workerd, rust, python (or cpython), ruby, and the JVM (jvm, java, or the OTel-canonical OpenJDK Runtime Environment) render as their logo next to the service name. go, dotnet, php, and anything unrecognized render as a short text chip, because their logos are wordmarks that are unreadable at icon size. A runtime the platform badge already implies (workerd on a Cloudflare service) is not shown a second time.

Common aliases are folded together (node/nodejs, go/golang). Keep the value consistent across services on the same runtime anyway. An unlisted variant falls through to the text chip, and one fleet ends up wearing two different marks.

Filter aliases

In Maple’s WHERE-clause search bar (trace list, log search, dashboard widgets), you can type a short alias and it resolves to the canonical attribute:

AliasResolves to
serviceservice.name
spanspan.name
environment, envdeployment.environment
commit_shavcs.ref.head.revision
root.onlyroot_only (synthetic boolean, root spans only)
errors_onlyhas_error (synthetic boolean, error spans only)

So env = "production" and deployment.environment = "production" mean the same thing. Pick whichever is shorter.

Reserved namespace

maple_* is reserved for Maple platform internals (org routing, ingest auth keys). Do not use this prefix for your own attributes. The UI hides anything starting with maple_ from log attribute chips.

Attributes Maple hides from log chips

These are stored on the row but skipped from the log attribute chips because they’re noisy or already shown elsewhere (service column, etc.):

  • service.name, service.namespace, service.instance.id, service.version
  • telemetry.sdk.*
  • process.runtime.*, process.executable.*
  • os.*
  • host.arch, host.name
  • maple_*

The data is still queryable. You can filter or group by these in the search bar. They just don’t appear in the row’s attribute chips.

Appendix: attribute prominence scoring

Each log row shows every attribute that isn’t hidden as a chip, ordered by score. Higher score comes first.

ScoreAttributes
100error, exception, exception.* (anything)
95http.status_code, http.response.status_code
90rpc.grpc.status_code
80http.method, http.request.method
70db.system.name, db.system, db.query.text, db.statement, db.operation.name, db.operation
68rpc.service, rpc.method
66user.id, enduser.id, customer.id, customer_id
60duration_ms, latency_ms, http.duration
55http.url, http.route, url.path
40Other http.*, url.*
38Other db.*
36Other rpc.*
34messaging.*
32Other user.*, enduser.*
25Anything with a dot (namespace.key)
20Bare keys (no namespace)

Resource attributes appear in chips only if they’re in the promoted set (deployment.environment, deployment.environment.name, k8s.pod.name, k8s.namespace.name, cloud.region). A promoted resource attribute scores 10 lower than the same key on the log itself.

Metrics

Maple accepts OTLP metrics at /v1/metrics: sums (counters), gauges, histograms, and exponential histograms. Summary data points are not supported and are dropped at ingest.

For exact RED (rate, error, duration) metrics alongside sampled traces, derive metrics from every span with the Collector’s SpanMetrics connector before sampling. See Exact counts with SpanMetrics.

Data retention

How long each signal is kept depends on your plan. See Retention.