> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aiaxoniq.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Resource attributes

> The attributes that describe your service, which ones aiAxonIQ builds features on, and the ones that quietly multiply your bill.

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

<Warning>
  **`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.
</Warning>

```bash theme={null}
OTEL_SERVICE_NAME=checkout-api
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,service.version=2.4.1
```

`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.

<Info>
  **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.
</Info>

## The attributes aiAxonIQ builds on

Set these and the product works as designed. Omit them and specific features
degrade in specific ways.

| Attribute                | What depends on it                                                  | If it is missing                             |
| :----------------------- | :------------------------------------------------------------------ | :------------------------------------------- |
| `service.name`           | Service inventory, service map, per-service views, most alert rules | Everything collapses into `unknown_service`  |
| `deployment.environment` | Separating environments in one organization                         | Staging and production are indistinguishable |
| `service.version`        | Version inventory, correlating a regression with a release          | You cannot tell which release started it     |
| `host.name`              | Infrastructure views, per-host filtering                            | Host-level correlation is unavailable        |
| `service.namespace`      | Grouping services owned by one team or system                       | Flat list only                               |

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](/send-data/platforms/kubernetes).

## Naming services

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

<Steps>
  <Step title="Use the name the team uses">
    `checkout-api`, not `svc-prod-ckt-01`. If nobody says it out loud, it is
    the wrong name.
  </Step>

  <Step title="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.
  </Step>

  <Step title="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.
  </Step>
</Steps>

## 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.

<Note>
  **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.
</Note>

## 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.

```text theme={null}
http.server.duration{service, route, status}          → a few hundred series
http.server.duration{service, route, status, user_id} → one series per user
```

<Warning>
  **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.
</Warning>

High cardinality on **logs and spans** is fine and expected. It is specifically
a metrics problem.

## Setting them

<AccordionGroup>
  <Accordion title="Environment variables — works with every SDK" icon="terminal">
    The portable way. Every OpenTelemetry SDK reads these without any code.

    ```bash theme={null}
    OTEL_SERVICE_NAME=checkout-api
    OTEL_RESOURCE_ATTRIBUTES=deployment.environment=production,service.version=2.4.1,service.namespace=commerce
    ```

    Comma-separated `key=value` pairs. `OTEL_SERVICE_NAME` takes precedence
    over a `service.name` inside `OTEL_RESOURCE_ATTRIBUTES`.
  </Accordion>

  <Accordion title="In the Collector — for telemetry that arrives without them" icon="server">
    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.

    ```yaml theme={null}
    processors:
      resource:
        attributes:
          - key: deployment.environment
            value: production
            action: upsert
    ```

    `upsert` overwrites what arrived; `insert` only fills in a missing value.
    Prefer `insert` unless you specifically intend to override applications.
  </Accordion>

  <Accordion title="In Kubernetes — from the pod spec" icon="dharmachakra">
    Set the variables from the downward API so they follow the workload rather
    than being pasted per deployment.

    ```yaml theme={null}
    env:
      - name: OTEL_SERVICE_NAME
        value: checkout-api
      - name: OTEL_RESOURCE_ATTRIBUTES
        value: deployment.environment=production
    ```
  </Accordion>
</AccordionGroup>

## Conventions worth following

OpenTelemetry publishes semantic conventions — agreed names for common
attributes. Following them is what makes tooling work without configuration.

| Instead of                    | Use                                            |
| :---------------------------- | :--------------------------------------------- |
| `env`, `environment`, `stage` | `deployment.environment`                       |
| `svc`, `app`, `application`   | `service.name`                                 |
| `version`, `build`            | `service.version`                              |
| `status`, `code`              | `http.status_code`                             |
| `endpoint`, `path`            | `http.route` *(the pattern, not the raw path)* |

<Info>
  **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.
</Info>

## Verify what actually arrived

Instrumentation intent and reality diverge. Confirm:

<Steps>
  <Step title="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.
  </Step>

  <Step title="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.
  </Step>

  <Step title="Filter on one">
    ```text theme={null}
    deployment.environment:"production"
    ```

    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](/guides/logs/search).
  </Step>
</Steps>

## Next

<CardGroup cols={3}>
  <Card title="Sampling" icon="percent" href="/send-data/otel/sampling">
    Keep the traces that matter and drop the rest.
  </Card>

  <Card title="Collector configuration" icon="server" href="/send-data/otel/collector-config">
    Where to add, rename and redact attributes in flight.
  </Card>

  <Card title="Signals and the data model" icon="diagram-project" href="/concepts/data-model">
    How attributes connect logs, metrics and traces.
  </Card>
</CardGroup>
