Skip to main content
A resource is whatever is producing telemetry — a service, a host, a pod. Its attributes are attached to every log, span and metric it emits, so they are what you filter, group and correlate by. Getting two of them right is worth more than everything else on this page.

The two that matter most

service.name is unset by default, and the default is unknown_service.Every service that does not set it collapses into a single entry that appears to be enormous and is not anything. The service map is meaningless, per-service dashboards are meaningless, and alerts scoped to a service cannot be written.This is the single most common instrumentation mistake, and it is one environment variable.
deployment.environment is the second. Without it, staging traffic and production traffic are the same service, and every chart is the sum of the two.
Get Started in the dashboard shows the exact base endpoint for your deployment next to a license key you create there, with copy buttons, and then watches for your first records. Where these pages write $OIQ_ENDPOINT, that page has the real value.

The attributes aiAxonIQ builds on

Set these and the product works as designed. Omit them and specific features degrade in specific ways. On Kubernetes, pod, namespace, node and workload attributes are added by the Collector or the zero-code agent — you do not set those by hand. See Kubernetes.

Naming services

Names are what everyone will read at 3am, so it is worth spending five minutes on a convention:
1

Use the name the team uses

checkout-api, not svc-prod-ckt-01. If nobody says it out loud, it is the wrong name.
2

Keep it stable across environments

The same service in staging and production should carry the same service.name and differ by deployment.environment. Naming them checkout-api-staging and checkout-api-prod makes them two services forever, and no comparison between them is possible.
3

Do not encode the instance

A pod name or host in service.name produces one service per replica. Instances belong in host.name and the Kubernetes attributes.

Resource attributes versus span attributes

Two levels, and the distinction decides both what you can query and what you pay.
  • Resource attributes describe the emitter and are attached to every record it produces. Set them once, at startup.
  • Span and log attributes describe one event — http.method, http.status_code, order.id. Set them per operation.
Put per-request values on the span, never on the resource. A resource attribute is repeated on every record the process emits, so a request id there is both useless and expensive. The rule is: does this value change between two requests? If yes, it is a span attribute.

Cardinality: the cost you cannot see

For metrics, every distinct combination of label values is a separate stored series. This, not the number of samples, is what drives cost.
Never put these in a metric label or a resource attribute: user id, request id, session id, trace id, full URL path, raw error message, timestamp, or anything else unbounded.The classic case is an un-templated URL — /orders/8817 and /orders/8818 are two series, and a busy endpoint becomes millions. Report the route pattern, /orders/{id}, and put the actual id on a span attribute where per-event data belongs and costs what one event costs.
High cardinality on logs and spans is fine and expected. It is specifically a metrics problem.

Setting them

The portable way. Every OpenTelemetry SDK reads these without any code.
Comma-separated key=value pairs. OTEL_SERVICE_NAME takes precedence over a service.name inside OTEL_RESOURCE_ATTRIBUTES.
Useful when a source you do not control emits nothing useful, or when you want to guarantee a value regardless of what an application sets.
upsert overwrites what arrived; insert only fills in a missing value. Prefer insert unless you specifically intend to override applications.
Set the variables from the downward API so they follow the workload rather than being pasted per deployment.

Conventions worth following

OpenTelemetry publishes semantic conventions — agreed names for common attributes. Following them is what makes tooling work without configuration.
Custom attributes are fine — prefix them with something of your own, like acme.tenant_tier, so they never collide with a convention added later. Attribute keys are case-sensitive throughout.

Verify what actually arrived

Instrumentation intent and reality diverge. Confirm:
1

Open Services

Your service should be there under the name you chose. An unknown_service entry means service.name did not reach us from something.
2

Open a log record or a span and read its attributes

Resource attributes are shown alongside record attributes. This is the fastest way to catch a typo in an attribute name.
3

Filter on one

Zero results usually means a misspelled key rather than missing data — an unrecognised field name is an attribute lookup that matches nothing, not an error. See Searching logs.

Next

Sampling

Keep the traces that matter and drop the rest.

Collector configuration

Where to add, rename and redact attributes in flight.

Signals and the data model

How attributes connect logs, metrics and traces.