What Are Resource Detectors in OpenTelemetry?

What Are Resource Detectors in OpenTelemetry?

A friendly, ground-up guide to the small helpers that discover where your software is running, what it is called and who it belongs to, and stamp that identity on every trace, metric and log, without you typing it all by hand.

Imagine you find a lost suitcase at an airport. You open it and look for a luggage tag. If there is a tag with a name, a flight number and a phone number, you can return the suitcase in minutes. If there is no tag, the suitcase might sit in a storage room for months, and nobody will know whose it is, where it came from or where it was going.

Telemetry, which is the information that software sends out about itself, has exactly this problem. A single span that says “this call took 900 milliseconds” is not very helpful if you cannot tell which service made it, which machine it ran on, which version of the code was running, or which cloud region it came from. In OpenTelemetry, the luggage tag is called a resource. And the helpers that fill in the luggage tag automatically, by looking around at the environment, are called resource detectors. In this guide, we will learn what they are, how they work, and how to use them wisely, using simple words and everyday examples.

1
Resource per application process, created once when it starts
3
Signals that carry the same resource: traces, metrics and logs
Startup
The moment when detection normally runs

1The Problem: Whose Data Is This?

Before learning the tool, let us feel the problem it solves.

A busy company with many services

Picture an online food delivery company. It runs a hundred different services: one for the menu, one for orders, one for payments, one for finding drivers, and many more. Each service runs in many copies, called instances, spread over many machines and several cloud regions. When the telemetry from all these copies arrives in one place, millions of spans, numbers and log lines arrive together.

Now an engineer asks a simple question: “Why is the payment service slow in the Mumbai region since this morning’s release?” To answer, the data must carry certain facts. It must say which service produced it, which version of that service, which region, and ideally which machine or pod. Without these facts, the engineer sees a giant pile of anonymous numbers.

The pain of typing it all by hand

One answer is to ask every developer to add these facts by hand in every service. But that has serious problems.

  • People forget. One team forgets the region, another spells the version differently, and the data becomes inconsistent.
  • Facts change. The same code may run on a laptop today and in a container tomorrow, and the machine name changes every time it is deployed.
  • Some facts are hard to know. Does your code know the ID of the cloud virtual machine it is running on? The name of the Kubernetes pod? The ID of the container? These facts live in the environment around the program, not in the program itself.
  • It is repetitive. Two hundred services would each need the same code to look up the same facts.
Everyday Analogy

Think of a hotel check-in desk. Each guest gets a wristband with their name, room number and stay dates. The hotel does not ask every guest to write their own wristband. A staff member looks up the booking and prints it. Resource detectors are the staff member who prints the wristband for your software, using facts they can look up around them.

flowchart LR
    subgraph NO["Without resource information"]
        A1["Span: slow call, 900 ms"] --> A2["Which service? Unknown"]
        A2 --> A3["Which region? Unknown"]
        A3 --> A4["Which version? Unknown"]
    end
    subgraph YES["With resource information"]
        B1["Span: slow call, 900 ms"] --> B2["Service: payments"]
        B2 --> B3["Region: ap-south-1"]
        B3 --> B4["Version: 2.4.1"]
    end
    
Figure 1: The same span is far more useful when it carries the identity of its sender

2First, What Is a Resource?

We must understand the luggage tag before we can understand the person who fills it in.

In OpenTelemetry, a resource is a set of facts that describes the thing that produces telemetry. That thing might be a service, a process, a container, a machine, or a function running in the cloud. The facts are stored as attributes, which are simple pairs of a name and a value, like “service.name equals payments” or “cloud.region equals ap-south-1”.

Three important properties

Property 1

Describes the Producer

A resource says who is sending the data, not what the data is about. It describes the sender, not the single event.

Property 2

Attached to Everything

The same resource is attached to every span, every metric and every log record that the application sends, so you do not repeat it for each item.

Property 3

Immutable

Once the resource is created, it does not change for the life of that SDK. It is a stable identity, not a changing status.

Resource versus span attributes

Beginners often confuse these two, so let us separate them with a table.

QuestionResource AttributeSpan Attribute
What does it describe?The sender: the service, host, cloud or containerOne single operation, such as one request
How often does it change?Rarely, usually fixed for the process lifetimeDifferent for every span
How is it stored?Once per batch of telemetryOn each span individually
Exampleservice.name, cloud.regionhttp.request.method, a customer tier
Everyday pictureThe luggage tagA note about what is inside this one bag
Everyday Analogy

A letter has two kinds of information. The return address on the envelope says who sent it and does not change from page to page. The contents of each page say something specific. The resource is the return address on the envelope. The span attributes are the words on the pages.

3So, What Are Resource Detectors?

The short answer first, and then the details.

A resource detector is a small component that automatically discovers facts about the environment where your software is running, and turns those facts into resource attributes. It looks at the machine, the operating system, the process, the container, the cloud provider and the orchestration system such as Kubernetes. Then it hands back a bundle of attributes, ready to be added to the resource.

A detector asks the environment, “Where am I, and who am I?” so that you do not have to type the answer.

What detectors can discover

Machine

Host and Operating System

The host name, the operating system type and version, and the processor type.

Program

Process

The process ID, the program’s executable name, the runtime such as the language version, and who started it.

Box

Container

The container ID and, in some cases, the container runtime and image name.

Cloud

Cloud Provider

Which cloud, which account, which region and zone, and the ID of the virtual machine, task or function.

Orchestrator

Kubernetes

The cluster, the namespace, the pod name, the node name and the deployment.

Settings

Environment Variables

Facts that you or your platform wrote down in standard settings, such as the service name.

What detectors are not

  • They are not instrumentation. They do not create spans or metrics. They only describe the sender.
  • They are not magic. They can only discover what the environment makes available. If the environment hides a fact, the detector cannot find it.
  • They do not describe individual requests. For per-request facts, you use span attributes.
  • They are not the same as the Kubernetes enrichment tool in the Collector. We will explain this difference carefully in a later chapter, because it is a common source of confusion.
i
Tip

You will meet resource detectors in two places: inside the SDK of your application, and inside the Collector as a processor called the resource detection processor. They share the same idea but work in different places. This guide covers both.

4Core Concepts: The Families of Resource Attributes

OpenTelemetry has agreed names for common facts, grouped into families. Knowing the families helps you read any trace.

The agreed names come from the semantic conventions, which are shared naming rules for telemetry. Using the same names everywhere means that dashboards, alerts and tools from different vendors understand your data without extra work. Here are the main families.

FamilyExample Attribute NamesWhat They Tell You
Serviceservice.name, service.version, service.namespace, service.instance.idWhich logical service, which release, which team group and which individual copy
Telemetry SDKtelemetry.sdk.name, telemetry.sdk.language, telemetry.sdk.versionWhich OpenTelemetry library produced the data
Hosthost.name, host.id, host.archThe machine, physical or virtual
Operating Systemos.type, os.descriptionThe operating system family and version
Processprocess.pid, process.executable.name, process.runtime.nameThe running program and its language runtime
Containercontainer.id, container.name, container.image.nameThe container the program runs in
Cloudcloud.provider, cloud.account.id, cloud.region, cloud.availability_zoneWhich cloud, account, region and zone
Kubernetesk8s.cluster.name, k8s.namespace.name, k8s.pod.name, k8s.node.nameWhere the workload sits in the cluster
Deploymentdeployment.environmentWhether this is production, staging or testing

The most important attribute of all

If you remember only one resource attribute, remember service.name. It is the logical name of your service, such as “checkout” or “payments”. Almost every tracing and monitoring tool uses it as the main way to group data. If you do not set it, the SDK uses a placeholder that begins with the words “unknown service” followed by the name of the running program. Seeing “unknown service” in your tools is the classic sign that nobody set the service name.

Everyday Analogy

Think of a school ID card. The student’s name is the most important line, and the class, the house and the year are extra lines that help sort the students. If the name were missing, the card would almost be useless, however many other lines it had. service.name is the name line of your telemetry.

Which ones can a detector find, and which must you provide?

This is a very practical question. Some facts are knowable from the environment, and some are choices that only your team can make.

Usually Detectable

  • Host name, host ID and operating system
  • Process ID, executable name and runtime
  • Container ID
  • Cloud provider, region, zone and instance ID
  • Kubernetes pod, namespace and node, if passed into the container
  • SDK name, language and version

Usually Must Be Provided

  • The logical service name
  • The service version, unless taken from the build
  • The environment, such as production or staging
  • The service namespace or team
  • Any company-specific labels, such as cost centre

5Internal Working: How Detection Happens in the SDK

Let us follow the story from the moment your program starts.

When your application starts and the OpenTelemetry SDK is set up, one of the first things it does is build the resource. It does this by running a list of detectors, one by one, collecting the facts each one finds, and then merging all the facts into one final resource. This resource is then handed to the providers for traces, metrics and logs, so every signal carries it.

sequenceDiagram
    participant App as Application starts
    participant SDK as OpenTelemetry SDK
    participant D1 as Default detector
    participant D2 as Environment detector
    participant D3 as Host and process detectors
    participant D4 as Cloud detector
    participant TP as Tracer, Meter and Logger providers
    App->>SDK: Initialise SDK
    SDK->>D1: Ask for SDK facts and default service name
    D1-->>SDK: telemetry.sdk and unknown service placeholder
    SDK->>D2: Ask for facts from environment variables
    D2-->>SDK: service.name and custom attributes
    SDK->>D3: Ask for host, OS and process facts
    D3-->>SDK: host.name, os.type, process.pid
    SDK->>D4: Ask for cloud facts
    D4-->>SDK: cloud.provider, cloud.region, host.id
    SDK->>SDK: Merge all facts into one resource
    SDK->>TP: Give the final resource to every provider
    
Figure 2: Detectors run one after another at startup, and their results are merged
1

Start With a Default

The SDK begins with a basic resource that contains facts about the SDK itself and a placeholder service name that starts with the words “unknown service”.

2

Run Each Configured Detector

Each detector in the list looks at its own part of the environment and returns a small set of attributes. If a detector finds nothing, it returns an empty set, which is fine.

3

Merge the Results

The SDK combines the sets into one. When two detectors report the same attribute name, one of them wins, according to merge rules we will see shortly.

4

Freeze the Resource

The final resource is created and fixed. It will not change for the rest of this process’s life.

5

Attach to Every Signal

The tracer, meter and logger providers all use this same resource. Each batch of exported data carries it once, rather than repeating it for each span or data point.

Automatic and manual detection

In many setups, detection happens without you doing anything. A few detectors are always on, such as the one that records the SDK’s own facts. Others are enabled by settings. In auto-instrumentation setups, such as agents, a sensible group of detectors is often turned on for you. In manual setups, you pick the ones you want when you build the SDK.

!
Watch Out

Defaults differ between languages and versions. A detector that is on by default in one language may be off by default in another, especially cloud-specific ones. Always check what your own SDK or agent enables, and then look at a real piece of exported data to confirm what was actually detected.

6Merging and Precedence: Who Wins When Facts Disagree?

When several sources give an answer to the same question, there must be clear rules.

Imagine that the environment detector says the service is called “checkout”, while a cloud detector says nothing about the service name, and the default detector says “unknown service”. All three provide a value, or a placeholder, for the same attribute. The SDK needs a rule for which one to keep.

The general rule is simple: when two resources are merged, the values from the later or more specific one override the earlier one on conflicts. The default placeholders sit at the bottom, and explicit choices made by you sit at the top. In most SDKs, values you set through the standard environment variables take priority over automatically detected ones.

flowchart TD
    A["Lowest priority: SDK defaults and placeholders"] --> B["Automatic detectors: host, OS, process, container, cloud"]
    B --> C["Environment variable detector: OTEL_RESOURCE_ATTRIBUTES"]
    C --> D["Highest priority: OTEL_SERVICE_NAME and values set in code"]
    D --> E["Final resource"]
    
Figure 3: A typical order of priority when facts conflict, from lowest to highest
SituationWhat HappensWhy
No service name set anywhereThe service is labelled “unknown service” followed by the program nameThe default placeholder is used because nothing better was given
Service name in OTEL_RESOURCE_ATTRIBUTES onlyThat value is usedThe environment detector provides it
Service name in both OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTESOTEL_SERVICE_NAME winsThe dedicated variable takes precedence over the general one
Two detectors report different host namesThe one that runs later usually winsLater results override earlier ones in a merge
Detector fails to find anythingNothing is added, and earlier values stayAn empty result changes nothing

The order of detectors matters

Because later detectors can override earlier ones, the order in which you list detectors is part of your configuration. If two detectors can disagree, such as one that reads a host name from the operating system and another that reads a more precise host ID from the cloud, put the more trusted source later.

Everyday Analogy

Think of a form with several corrections. The first draft says the meeting is at 3 pm. A later note says it has moved to 4 pm, and the final note from the organiser says 4:30 pm. Everyone follows the last, most authoritative note. Merging resources works in the same spirit: the later and more explicit statement wins.

7The Environment Variable Detector

The simplest and most important detector. Almost everyone uses it.

An environment variable is a named setting that is handed to a program when it starts, a bit like a note stuck on the door before the program enters the room. OpenTelemetry defines standard names for the notes that describe your resource.

SettingWhat It HoldsNotes
OTEL_SERVICE_NAMEThe logical name of the serviceThe easiest way to avoid “unknown service”. Wins over the same value inside the general setting.
OTEL_RESOURCE_ATTRIBUTESA list of name and value pairs, separated by commasUsed for the version, environment, team, and anything else you want to add. Special characters need encoding.

Why this approach is so popular

  • No code changes. You set the values in your deployment, not in your program.
  • Works in every language. The names are the same everywhere.
  • Easy to automate. Deployment tools can fill in the version, the environment and the team for you, so every service is labelled the same way.
  • Easy to change. You can fix a label by redeploying with a new setting, without rebuilding the application.

Production Example: A Standard Deployment Template

A platform team writes one deployment template used by every service in the company. The template fills in the service name from the project name, the version from the release tag, the environment from the target cluster, and the team from the repository owner. Every one of the two hundred services now reports the same set of labels, written the same way, with zero effort from application developers.

!
Watch Out

Values in OTEL_RESOURCE_ATTRIBUTES are split on commas, so a value that itself contains a comma, an equals sign or spaces must be encoded correctly, or the list may be read wrongly and attributes silently lost. Keep values simple, and check the exported data to confirm.

8Built-In Detectors Across Languages

Each language ships its own set of detectors, with similar ideas but different names and defaults.

Common

Environment Detector

Reads the standard settings. Present in virtually every language and nearly always on.

Common

Host Detector

Finds the host name and, in some languages, an ID and architecture.

Common

Operating System Detector

Finds the operating system type and description.

Common

Process Detector

Finds the process ID, executable name, the runtime, and in some cases the command used to start the program.

Common

Container Detector

Reads the container ID, often from system files that the container runtime exposes, and is usually offered as an add-on package.

Add-On

Cloud Detectors

Separate packages for Amazon, Google and Microsoft clouds, and others. They ask a metadata service about the instance, task or function.

How the languages differ in style

  • Java: Detectors are packaged as modules, and the Java agent turns on a sensible set automatically. Cloud ones are often switched on with a setting. Some detectors can be listed or hidden using provider settings.
  • Python: The core package has the environment and process detectors, and cloud and container detectors come as separate packages. A setting can list which detectors to use at startup.
  • JavaScript and Node.js: The core resources package offers environment, host, operating system, process and service instance detectors, and cloud detectors are separate packages. Some detectors work asynchronously, since they may need to wait for a reply.
  • Go: The resource package offers options you choose when building the resource, such as ones for the host, operating system, process, container, and from the environment, and cloud detectors live in a separate contrib area.
  • .NET: Packages for host, operating system, process, container and cloud environments are available as add-ons, and the environment settings are read by default.
i
Tip

Because package names and defaults keep changing, a good habit is to run your application once in a test environment with a console exporter, print the resource, and read it. That one look tells you exactly what your detectors found and what is missing.

9Cloud Detectors and Metadata Services

How can a program learn which cloud region it is in? It asks a very friendly neighbour.

Cloud providers give every virtual machine, container task or serverless function a special local address, called a metadata service, that answers questions about itself. The address is only reachable from inside that machine. A cloud detector simply makes a small web request to this address and reads the reply, which includes facts such as the instance ID, region, zone and account.

sequenceDiagram
    participant App as Application with SDK
    participant CD as Cloud detector
    participant MS as Cloud metadata service
    App->>CD: Start detection at startup
    CD->>MS: Request token if the provider requires one
    MS-->>CD: Short lived token
    CD->>MS: Ask for instance ID, region and zone
    MS-->>CD: Answers
    CD->>CD: Turn answers into cloud.* and host.* attributes
    CD-->>App: Return attributes within the allowed time
    
Figure 4: A cloud detector asks the local metadata service about its own environment

The cloud families

Where You RunWhat a Detector Can LearnPoints to Know
Virtual machines on a major cloudInstance ID, type, image, region, zone, accountThe metadata service must be reachable and not blocked by network rules
Managed container platformsCluster, task or service name, launch type, regionOften reads a metadata address that the platform places in an environment variable
Managed Kubernetes servicesCluster name and cloud details, along with the node’s informationThe cluster name is sometimes only available from the cloud provider
Serverless functionsFunction name, version, region, memory size, request ID detailsFacts are mostly found in environment variables, with no network call needed
Application platforms as a serviceSite or app name, region, resource groupFacts come from platform-provided environment variables

Costs and cautions of asking the network

  • Startup delay. A web request takes time. If the metadata service is slow or does not answer, startup may be delayed until a timeout. Good detectors use short timeouts.
  • Failure must be harmless. If the program is running on a laptop and there is no metadata service, the detector must quietly return nothing. It must never stop the application from starting.
  • Security tokens. Some clouds require a token, to protect the metadata service from abuse. Detectors handle this, but your network and permission settings must allow it.
  • Containers and hops. In some container setups, the metadata service is only reachable if network settings allow an extra hop. If detection mysteriously finds nothing in a container, check this.
  • Short-lived functions. In serverless functions that start often, every extra millisecond of startup is paid again and again. Prefer detectors that read environment variables over those that make network calls.
Everyday Analogy

Think of arriving at a big airport and not knowing which terminal you are in. You can look at a map on the wall, which is quick, or ask a staff member at the information desk, which takes longer and might have a queue. A cloud detector that reads an environment variable is like looking at the wall map. One that calls the metadata service is like going to the desk.

10Kubernetes: A Special Case

Inside a container, the program does not automatically know which pod or node it is in.

Kubernetes is a popular system for running many containers across many machines. Inside a container, a program sees its own small world. It does not directly know the name of its pod, the namespace, or the node. These facts are held by Kubernetes, not by the program, so a simple detector cannot discover them by looking around. We need a way to hand these facts in.

Three ways to get Kubernetes facts into the resource

Way 1

The Downward API

Kubernetes can pass facts about a pod into its containers as environment variables, such as the pod name and namespace. You then copy these into the resource attributes setting.

Way 2

The OpenTelemetry Operator

When it injects auto-instrumentation, the Operator can automatically set resource attributes from the pod’s own information, so you do nothing.

Way 3

The Collector’s Kubernetes Enrichment

A Collector processor looks up the pod in the Kubernetes API, using the network address of the sender, and adds pod and namespace details to the data in transit.

flowchart TD
    K["Kubernetes pod definition"] --> D["Downward API passes pod name and namespace as environment variables"]
    K --> O["Operator injects settings when instrumenting"]
    D --> E["OTEL_RESOURCE_ATTRIBUTES includes k8s facts"]
    O --> E
    E --> S["SDK environment detector builds the resource"]
    S --> X["Telemetry carries k8s attributes"]
    K --> A["Kubernetes API"]
    A --> P["Collector Kubernetes attributes processor looks up the sender"]
    X --> P
    P --> Y["Telemetry enriched in the Collector"]
    
Figure 5: Three routes that bring Kubernetes facts into your telemetry

A very important difference: detecting versus looking up

This is a favourite source of confusion, so let us be careful. The two Collector tools sound similar but do different jobs.

QuestionResource Detection ProcessorKubernetes Attributes Processor
What does it describe?The environment where the Collector itself runsThe environment of each sender whose data passes through
How does it learn?By looking around, for example at the host and cloud metadataBy asking the Kubernetes API about the sender’s pod
Good whenThe Collector runs on the same machine, in the same pod or the same node as the apps, as an agentThe Collector receives data from many pods and must tell them apart
Wrong whenThe Collector is a central gateway, since all data would be stamped with the gateway’s own detailsUsed without permission to read the Kubernetes API
Everyday Analogy

Imagine a post office clerk stamping every parcel. If the clerk uses the post office’s own address stamp, the stamp describes the post office, not the sender. That is the detection processor on a central gateway. If the clerk instead looks up each sender in a directory and writes the correct address on each parcel, that is the Kubernetes attributes processor.

!
Watch Out

A very common mistake is to add the resource detection processor to a central gateway Collector and then wonder why every service in the company appears to be running on the gateway’s host. Detect the sender’s environment in the SDK, in an agent Collector beside the sender, or with the Kubernetes lookup, not in a distant gateway.

11The Resource Detection Processor in the Collector

The same idea, working inside the Collector pipeline.

In the Collector, the resource detection processor runs detectors and adds the facts it finds to the resource of the data that passes through. It is configured, not coded. You list the detectors you want, in order, and set a few options. It can add the same details to traces, metrics and logs.

The kinds of detectors it offers

Basic

Environment and System

Reads standard settings, and the host’s name, operating system and similar details.

Containers

Docker

Finds container host details from the container runtime.

Amazon

EC2, ECS, EKS and Others

Reads facts for virtual machines, container tasks, managed Kubernetes, serverless and related platforms.

Google

Compute, GKE and Cloud Run

Finds project, region, zone and platform details on Google’s cloud.

Microsoft

Azure and AKS

Reads subscription, resource group, region and platform details.

Others

Other Platforms

Detectors exist for several other platforms and tools, depending on the Collector distribution you use.

The important settings

SettingWhat It DoesWhy It Matters
Detectors listNames the detectors to run, in orderOrder decides who wins when two detectors disagree
TimeoutHow long to wait for a detector to finishStops a slow metadata service from delaying startup for long
OverrideWhether detected values replace attributes already on the dataControls whether the Collector can overwrite what the SDK already set. Many teams set it so that existing values are kept.
Per-detector attribute choicesWhich attributes each detector should or should not addLets you leave out sensitive or high-churn facts
flowchart LR
    R["Receiver"] --> M["Memory Limiter"]
    M --> RD["Resource Detection"]
    RD --> F["Filter and Redaction"]
    F --> S["Sampling"]
    S --> B["Batch"]
    B --> X["Exporter"]
    
Figure 6: Resource detection sits early in the pipeline, so later steps can use the labels it adds

Resource detection normally sits early in the pipeline, right after the memory limiter. The reason is that later processors, such as filters and samplers, may want to use the labels it adds, for example “drop data from the test environment”. Adding labels first means the rules that come after can see them.

Production Example: Labels for Free on Every Node

A company runs one Collector agent on every machine in its cluster. The agent uses the resource detection processor with the system and cloud detectors. Every span, metric and log leaving any machine now carries the host name, cloud region and zone, even from old applications that were never taught to report these facts. Engineers can filter dashboards by zone on day one.

12Where Should You Detect: SDK or Collector?

The same facts can often be found in either place. Let us choose wisely.

FactBetter in the SDKBetter in the Collector
Service name and versionYes. Only the application and its deployment know them.No. The Collector cannot guess them reliably.
Process and runtime detailsYes. The SDK sits inside the process.No. The Collector sees a different process.
Host and cloud factsPossible, with add-on detectorsYes, if the Collector runs beside the app as an agent
Kubernetes pod and namespaceVia the Downward API or the OperatorVia the Kubernetes attributes processor, which works for any sender
Company-wide labels such as team or cost centreVia standard environment settings from a templateVia the resource processor, which can add fixed labels to everything
Old applications that cannot be changedNot possibleYes, the main reason to detect in the Collector
flowchart TD
    Q["Which fact do you need?"] --> A{"Does only the application know it?"}
    A -->|Yes| B["Set it in the SDK with environment settings"]
    A -->|No| C{"Can you change or restart the application?"}
    C -->|Yes| D["Detect in the SDK, or pass it in with the Downward API or Operator"]
    C -->|No| E{"Does the Collector run beside the application?"}
    E -->|Yes| F["Use the resource detection processor in the agent Collector"]
    E -->|No| G["Use a lookup, such as the Kubernetes attributes processor, or add fixed labels in the Collector"]
    
Figure 7: A simple guide for choosing where to detect or add resource facts

A sensible split of duties

  • The application and its deployment own the identity: service name, version, environment and team.
  • The agent Collector owns the local environment: host, cloud and node facts.
  • The gateway Collector owns company-wide policies: adding or fixing labels, and removing sensitive ones.

Giving each layer one clear job avoids two layers fighting over the same attribute.

13Data Flow and Lifecycle of a Resource

Follow one resource from the moment your program starts to the moment you read it on a dashboard.

1

Deployment Sets the Stage

Your deployment tool passes settings such as the service name, the version and the environment, plus pod facts, to the container.

2

The Program Starts and the SDK Initialises

The SDK builds its default resource and then runs the configured detectors.

3

The Final Resource Is Frozen

All the facts are merged, and the resource is attached to the tracer, meter and logger providers.

4

Telemetry Is Exported With It

Each batch of spans, metrics or logs sent to the Collector includes the resource once at the top of the batch.

5

The Collector May Add or Change

An agent Collector may add host and cloud facts, and the Kubernetes lookup may add pod facts. A gateway may enforce company labels or remove sensitive ones.

6

The Backend Stores and Groups

The storage system keeps the resource facts and uses them to group data: for example, by service name, region and version.

7

Engineers Filter and Compare

On dashboards, people filter by service, compare versions, split by region and drill into one pod, all because the resource facts are present.

How the resource looks in different backends

Different tools treat resource facts in different ways. Some show them as a panel of properties on each trace. Some use the service name as the main grouping key. Some store them in a separate table that you can join with other data. For example, when metrics are sent to a Prometheus-style system, the service name and instance become the standard “job” and “instance” labels, and the rest of the resource usually goes into a special information metric, which you can join in a query. Choose which facts to turn into direct labels with care, because each extra label can multiply the number of stored series.

i
Tip

A resource is attached once per batch, not once per span. That means adding many resource attributes costs very little on the wire. The real cost shows up later, when a backend turns some of them into labels or indexes them, so be selective at that stage, not at the detection stage.

14Resource Rules: Immutability and What Not to Put There

A resource is a luggage tag, not a diary. Keep it stable.

Because a resource is created once and does not change, it is the wrong place for anything that changes while the program runs. Putting changing facts there leads to confusing data or forces you to restart programs just to update labels.

Good Resource Attributes

  • Service name, version and namespace
  • Deployment environment
  • Cloud provider, account, region and zone
  • Host, container and pod identity
  • Fixed company labels, such as team

Bad Resource Attributes

  • The current user, request or session
  • Current memory or CPU use
  • Feature flag values that can change while the program runs
  • Anything that has a different value for each request
  • Secrets, tokens or passwords

The churn problem

Some resource attributes change every time a program restarts, such as the process ID, the pod name and the container ID. That is correct, since a new pod really is a new sender. But in a metrics system, every new combination of labels creates a brand new series. A cluster that restarts pods often can produce a flood of short-lived series if these attributes are turned into labels. Keep these in the resource, but be cautious about promoting them to metric labels.

Everyday Analogy

Think of a football match programme. It lists the team names, the stadium and the date. It does not list the current score, since that changes every minute. The programme is the resource. The live scoreboard is the span attributes and metrics.

15Instance Identity: Telling Copies Apart

When twenty copies of a service run at once, each needs its own identity.

The service instance ID, written service.instance.id, is meant to be unique for each running copy of a service. It lets you answer questions such as “is only one of the twenty copies slow?” The guidance is that it should be unique within the same service name and namespace, and it should be stable for the life of that copy.

Where does it come from?

  • You can set it through the standard environment settings, for example using the pod name.
  • A detector may create it, often as a random unique value generated at startup, in languages that offer such a detector.
  • A platform may provide it, such as a cloud instance ID or a container ID that you reuse.

Why this small field matters

In metrics systems, the instance ID is used to keep the numbers from different copies apart. If two copies share the same instance identity, their numbers can collide, overwrite each other or double count. If there is no instance identity at all, the backend cannot tell which copy produced a number.

Production Example: The Overlapping Counters

A team ran several copies of a worker service, all without an instance ID. Their metrics system treated the numbers from all copies as one stream, so a counter seemed to jump up and down as copies reported in turn. Adding a unique instance ID to each copy through the deployment template instantly produced clean, separate lines for each copy.

16Semantic Conventions, Schema URLs and Name Changes

Names are agreed standards. Standards evolve, and that has consequences.

The names of resource attributes come from the semantic conventions. These are carefully designed, but they are still maturing, and a few names have been renamed over time as the community improved them. For example, the attribute that records the deployment environment has been moving to a more specific name in newer versions. This is healthy for the project but can surprise teams whose dashboards depend on the old names.

Schema URLs

To help with this, a resource can carry a schema URL, a web address that names the version of the conventions used. A tool can use this to understand which version of the names a piece of data follows, and translate between versions. When two resources with different schema URLs are merged, the rules get more careful, and in some cases the merge is refused to avoid mixing incompatible names.

flowchart LR
    A["Old SDK sends deployment.environment"] --> C["Collector or backend"]
    B["New SDK sends the newer environment name"] --> C
    C --> D{"Are both names handled?"}
    D -->|Yes| E["Dashboards show all services together"]
    D -->|No| F["Some services vanish from filters and dashboards"]
    
Figure 8: Mixed naming versions can silently split your data if dashboards only know one name

How to stay safe

  • Read the release notes before upgrading SDKs or agents, looking for renamed attributes.
  • Test dashboards after an upgrade in a staging environment.
  • Normalise in the Collector by adding a rule that copies old names to new names or the other way around, during migration.
  • Pin versions across services, so that the whole company moves together instead of living with mixed names for months.

17Advantages, Disadvantages and Trade-offs

Every approach has a price. Let us count both sides honestly.

Advantages

  • Less manual work: facts are found automatically
  • Consistency: every service reports the same kinds of facts in the same way
  • Accuracy: facts come from the real environment, not from memory or copy and paste
  • Cheap to carry: attached once per batch, not once per item
  • Great for filtering: region, zone, version and pod become instant filters
  • Works for old applications: the Collector can add facts without code changes

Disadvantages

  • Startup cost: network-based detectors can add delay
  • Environment dependent: a detector finds nothing if the platform hides the facts
  • Different defaults: languages and agents enable different detectors
  • Privacy risk: some facts reveal more than you want to share
  • Name churn: standards evolve and names change
  • Confusing overlap: the SDK and Collector can both add the same facts and conflict

Key trade-offs

DecisionOption AOption B
Where to detectIn the SDK, accurate for the process and fully under developer controlIn the Collector, central and works for old applications
How many detectorsMany, for rich context but longer startup and more privacy riskFew, for lean startup and less exposure but less context
Cloud detection methodMetadata service calls, richest facts but slowerEnvironment variables only, faster but fewer facts
Override setting in the CollectorOverwrite existing values, so detected facts are consistentKeep existing values, so application choices are respected
Promote to metric labelsPromote many, for easy queries but high series countsPromote few and join the rest when needed

18Security and Privacy Considerations

A luggage tag that says too much can be a problem. Be deliberate about what you reveal.

Secrets

Command Lines Can Hold Passwords

A process detector may record the full command that started the program. If a password or token was passed as part of that command, it could end up in every piece of telemetry. Turn off or scrub such attributes.

Settings

Do Not Put Secrets in Resource Settings

The resource settings are visible in telemetry, in configuration files and in process listings. Never place keys, tokens or passwords there.

Identity

Account and Host Identifiers

Cloud account IDs, host names and addresses can reveal how your infrastructure is laid out. Share them only with backends you trust.

Access

Metadata Services Need Care

Metadata services can also give out credentials in some clouds. Detectors should read only the harmless facts, and your network rules should limit which programs can reach the service.

Permissions

Least Privilege for Lookups

A Kubernetes lookup needs permission to read pod information. Grant only the narrow rights needed, not wide access to the whole cluster.

Pipeline

Remove Before Export

A Collector can delete or mask sensitive resource attributes before data leaves your network. Treat this as a second line of defence.

!
Watch Out

Resource attributes ride along with every batch, so a sensitive value in the resource is repeated in all of your data, forever. Review a sample of real exported resources from a test environment before turning on a new detector in production, and check it against your privacy rules, such as GDPR.

19Monitoring, Logging and Troubleshooting

When labels go missing or look wrong, here is how to find out why.

Signals that something is wrong

  • “Unknown service” in your tools: nobody set the service name for that program.
  • Missing cloud or Kubernetes fields: a detector is not enabled, cannot reach its metadata source, or the platform hides the facts.
  • All services showing the same host: detection is running in a central gateway instead of beside the sender.
  • Services split in two on dashboards: two spellings or two naming versions are in use for the same service.
  • Slow application start: a detector is waiting on a metadata service that never answers.
  • Metric series exploding: restart-prone attributes such as pod name or process ID are being turned into labels.
  • Values that look wrong or old: an attribute set by hand, or an old setting, is overriding the detected value.

A simple troubleshooting routine

1

Print the Resource

Run the application in a test environment with a console exporter, or look at the data arriving in the Collector, and read the exact resource.

2

Compare With What You Expected

List the attributes you expected, and tick off which are present, missing or surprising.

3

Check Which Detectors Are Enabled

Look at the SDK or agent settings, and at the Collector’s detector list and order.

4

Check the Environment

Confirm that the settings are actually present inside the running container, and that the metadata service is reachable from there.

5

Look at Precedence

See whether another source is overriding the value, whether in the SDK, or because the Collector’s override option is replacing it.

6

Read the Logs

Turn on debug logging briefly. Detectors often log what they tried and why they gave up.

Common symptoms and likely causes

SymptomLikely CauseWhat to Try
Service appears as “unknown service”No service name configuredSet the service name setting in the deployment
No cloud facts at allCloud detector not enabled, or metadata service unreachableEnable the detector, check network rules and token requirements
All data shows the Collector’s hostResource detection on a gateway CollectorDetect in the SDK or an agent Collector, or use a sender lookup
Pod name missingDownward API not wired up, or Operator not usedPass pod facts as environment variables, or enable the Kubernetes lookup
Attributes silently missing from the settings listEncoding problem with special charactersSimplify values and encode special characters correctly
Version label differs between SDK and CollectorBoth layers set it, and override is replacing oneDecide which layer owns it, and configure override accordingly
Application starts slowly in the cloudA detector is waiting for a slow or blocked metadata callShorten the timeout, remove the detector, or use environment-based detection

20Performance and Startup Considerations

Detection happens once, but when it happens matters.

Since detection normally runs once at startup, its cost is usually small and does not affect the speed of your requests. But there are cases where it matters, and they are worth understanding.

Cold Starts

Serverless Functions

A function that starts many times per hour pays the detection cost on each start. Use detectors that read environment variables, and avoid ones that make network calls, if you can.

Timeouts

Metadata Service Delays

When a metadata service does not answer, the detector waits until its timeout. Keep timeouts short so a missing service does not hold up your start.

Blocking

Synchronous versus Asynchronous

Some SDKs detect in the background, so the program starts quickly and the facts are added when ready. Others wait. Know which you have, and whether early telemetry might leave without the full resource.

Scale

Many Instances at Once

When hundreds of copies start together, they all query the same metadata service at once. This can cause rate limits, so avoid repeated retries.

i
Tip

For maximum predictability, a very common approach is to pass the important facts to your application through environment settings in the deployment, and keep network-based detection in the Collector agent. That way, the application starts instantly and still carries rich context.

21Design Patterns and Anti-Patterns

Habits worth copying and traps worth avoiding.

Good design patterns

Pattern

Identity by Template

Generate service name, version, environment and team from your deployment template, so every service is labelled consistently.

Pattern

Layered Ownership

The app owns identity, the agent Collector owns local environment facts, and the gateway owns company policy.

Pattern

Downward API Wiring

Pass pod name, namespace and node name into containers and copy them into resource settings.

Pattern

Detect Early in the Pipeline

Put resource detection right after the memory limiter, so later rules can use the labels.

Pattern

Allow List of Attributes

Choose exactly which detected attributes you want to keep, and drop the rest.

Pattern

Golden Resource Test

Add a simple automated check that every service’s exported resource contains the required attributes.

Anti-patterns

ANTI-PATTERN 01Avoid
The Mistake

Leaving the service name unset and trusting the default.

Why It Hurts

Data from many services is grouped under placeholder names, and dashboards, alerts and service maps become meaningless.

Better Approach

Set the service name explicitly for every service, and add an automatic check that rejects “unknown service” in your pipeline.

ANTI-PATTERN 02Avoid
The Mistake

Running the resource detection processor on a central gateway and expecting it to describe the senders.

Why It Hurts

Every service appears to be on the gateway’s host and region, hiding the real picture.

Better Approach

Detect in the SDK or in an agent Collector beside the sender, and use a lookup tool for Kubernetes facts.

ANTI-PATTERN 03Avoid
The Mistake

Putting per-request or fast-changing data in resource attributes.

Why It Hurts

The resource is fixed at startup, so values go stale or force restarts, and metrics systems may be flooded with series.

Better Approach

Use span attributes or metric attributes for changing values, and keep the resource for stable identity.

ANTI-PATTERN 04Avoid
The Mistake

Enabling every available detector everywhere “just in case”.

Why It Hurts

Startup gets slower, privacy risks increase, and noisy or churning attributes pollute your data.

Better Approach

Enable only the detectors that answer questions you actually ask, and review what they add.

ANTI-PATTERN 05Avoid
The Mistake

Letting the SDK and the Collector both set the same attribute with different values and no clear owner.

Why It Hurts

Values flip depending on the override setting, producing inconsistent data that is hard to explain.

Better Approach

Assign each attribute to one layer, and configure the override option to match.

ANTI-PATTERN 06Avoid
The Mistake

Hard-coding host names or instance IDs into configuration files that are shared among many copies.

Why It Hurts

Many copies report the same identity, so metrics collide and traces cannot be tied to a single copy.

Better Approach

Derive identity at start time from the platform, such as the pod name, or let a detector generate a unique instance ID.

22Best Practices and Common Mistakes

A practical checklist for resources you can trust.

Best practices

  • Always set the service name. It is the first thing every tool uses, and the most common reason for confusing dashboards.
  • Set version and environment. They let you compare releases and separate production from testing.
  • Provide a unique instance ID. It keeps copies of the same service apart in traces and metrics.
  • Use the standard names. Follow the semantic conventions, and avoid inventing your own spellings.
  • Standardise with templates. Let your deployment tools fill in labels, so developers cannot get them wrong.
  • Decide where each fact is detected. One owner per attribute, with the Collector override setting matching that choice.
  • Use short timeouts. Detectors that call the network must never be allowed to hold up your startup for long.
  • Review before production. Print real resources in a test environment, and check them for privacy and correctness.
  • Be selective with labels in metrics. Keep most resource facts in the resource, and promote only a short list.
  • Watch naming changes. Read release notes, test dashboards and normalise old and new names during upgrades.
  • Test it. Add an automatic test that checks the presence of required resource attributes for every service.

Common mistakes beginners make

  • Believing that detectors set the service name for you. They usually cannot know it.
  • Mixing up the resource detection processor with the Kubernetes attributes processor.
  • Forgetting that a resource cannot change after the SDK starts.
  • Assuming that every detector is on by default in every language.
  • Using the resource for data that changes per request.
  • Not checking what was actually exported, and trusting the configuration instead.
  • Letting secrets slip into resource settings or captured command lines.
  • Promoting too many resource attributes to metric labels.
  • Ignoring conflicts between the SDK and the Collector.

23Real-World and Industry Examples

How resource detectors show up in tools and platforms you may already know.

Amazon Web Services

The AWS Distro for OpenTelemetry and the open-source detector packages for Amazon’s cloud can recognise virtual machines, container tasks, managed Kubernetes clusters and serverless functions, and add facts such as region, account and task identity to telemetry. This gives teams on Amazon’s platforms rich labels without writing any code of their own.

Google Cloud

Google publishes resource detector libraries for its cloud, which discover facts such as project, region and zone for virtual machines, managed Kubernetes and serverless platforms. Google’s monitoring services use these labels to group and map data, which shows how a good detector makes a backend more useful.

Microsoft Azure

Azure’s monitoring products read the service name and namespace from the resource to decide how a service is shown in application maps, and detectors for Azure’s compute and Kubernetes services add subscription, resource group and region facts. A missing or wrong service name can cause several services to be shown as one.

The OpenTelemetry Operator on Kubernetes

When the Operator injects auto-instrumentation into a workload, it can automatically supply resource attributes taken from the pod, such as namespace and pod name. A platform team gets consistent Kubernetes labels on every service in a cluster by adding one annotation, with no application changes.

Agent Collectors Across Fleets

Large organisations run one Collector agent on every machine. By turning on the resource detection processor there, they add host and cloud details to the telemetry of every program on the machine, including programs from vendors that cannot be modified. This is often the first place teams see the benefit of centralised detection.

A typical journey for a growing company

1

Name Your Services

Set the service name, version and environment in every deployment, fixing the “unknown service” problem first.

2

Add Local Facts

Enable host, process and container detectors in the SDK or agent, and review the output.

3

Add Cloud and Cluster Facts

Use cloud detectors, the Downward API, the Operator or the Kubernetes lookup to add region, zone, pod and namespace.

4

Centralise Policy

Use a gateway Collector to enforce company labels, remove sensitive attributes and normalise old and new names.

5

Govern and Test

Add automatic checks for required attributes, review privacy regularly, and plan carefully for name changes.

24Frequently Asked Questions

Quick answers to questions beginners ask most.

Q1What is a resource detector in one sentence?
It is a small component that automatically discovers facts about the environment where your software runs, such as host, cloud and container details, and adds them to the resource that describes your telemetry’s sender.
Q2What is the difference between a resource and a resource detector?
The resource is the bundle of facts that describes the sender. A resource detector is a helper that finds some of those facts automatically.
Q3Do detectors set my service name?
Usually not. The service name is a choice made by your team. You provide it through standard settings or code. If nothing is provided, a placeholder beginning with “unknown service” is used.
Q4When does detection run?
Normally once, when the SDK starts. The result is then fixed for the life of that process. In the Collector, the processor runs its detectors at startup and can refresh them periodically, depending on its settings.
Q5Can a resource change while my program is running?
No. A resource is immutable once created. For values that change, use span attributes or metric attributes instead.
Q6What happens if two sources give different values for the same attribute?
The values are merged, and generally the later or more explicit source wins. Values from the dedicated service name setting win over the same value in the general resource settings. The order of your detector list also matters.
Q7What is the difference between the resource detection processor and the Kubernetes attributes processor?
The resource detection processor describes the environment where the Collector itself runs. The Kubernetes attributes processor looks up the pod details of each sender of data. For a central gateway, the second is usually the correct choice for Kubernetes facts.
Q8How do I get the pod name into my telemetry?
Pass it to the container with the Kubernetes Downward API and copy it into the resource settings, let the OpenTelemetry Operator do it when it injects instrumentation, or let a Collector processor look it up.
Q9Will detectors slow down my application?
Usually only at startup, and often very little. Detectors that make network calls to a metadata service can add delay, especially if the service does not answer. Use short timeouts and, in serverless functions, prefer detectors that read environment variables.
Q10Which attributes should I turn into metric labels?
Only a short, stable list, such as service, environment, region and cluster. Attributes that change on every restart, like pod name and process ID, can create too many series if promoted.
Q11Can detectors leak sensitive information?
Yes, if they capture things like full command lines or account identifiers that you do not want to share. Review the output in a test environment, turn off risky attributes, and scrub data in the Collector if needed.
Q12Do I need detectors if I already set everything with environment variables?
Not necessarily. Environment settings can carry all the facts you choose to provide. Detectors are helpful for facts that are tedious or impossible to type, such as cloud instance IDs, and for old applications you cannot change.
Q13Why did my dashboards break after upgrading?
Resource attribute names in the conventions have changed in some cases, so dashboards that look for the old names may no longer find the data. Read release notes, test, and normalise names in the Collector during the transition.
Q14Are the same resource facts used for traces, metrics and logs?
Yes. The same resource is shared by all three signals from one application, so you set it once and every signal carries the same identity.

25Summary and Key Takeaways

If you remember only a few things, remember these.

Key Takeaways

  • A resource is the luggage tag of your telemetry. It describes the sender, such as the service, host, cloud and container, and is attached once to every trace, metric and log.
  • Resource detectors fill in the tag automatically. They look at the environment, such as the machine, process, container, cloud and Kubernetes, and turn what they find into standard attributes.
  • You still must name your service. Detectors cannot guess the logical service name, version or environment, so set them with standard settings, or you will see “unknown service”.
  • Order and precedence matter. When sources disagree, later and more explicit values win, and the dedicated service name setting wins over the general one.
  • Detect in the right place. The SDK owns identity, an agent Collector beside the app owns host and cloud facts, and a central gateway should not pretend to describe distant senders. Use the Kubernetes lookup for pod facts.
  • Keep the resource stable and the labels few. Do not put changing or secret values there, and promote only a short list of resource attributes to metric labels.
  • Check, protect and plan. Print real resources before going live, scrub sensitive attributes, use short timeouts for network detectors, and prepare for naming changes between versions.