Resource Detectors in OpenTelemetry Python

Resource detectors are used to automatically detect and collect information about the environment in which your application is running. This information is then attached to the telemetry data (traces, metrics, and logs) to provide additional context.

The Python SDK detects resources from a variety of sources, and by default will use all available resource detectors: environment (OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME), host, operating system, and process information.

By default, all SDK resource detectors are used, but you can use the environment variable OTEL_EXPERIMENTAL_RESOURCE_DETECTORS to enable only certain detectors, or completely disable them:

bash
# Use only specific detectors
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="env,host,os"
python app.py

# Disable all detectors (only use "otel" base detector)
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="otel"
python app.py

Built-in detectors

The Python SDK includes several built-in resource detectors:

  • otel - base detector that sets SDK information
  • env - reads OTEL_RESOURCE_ATTRIBUTES and OTEL_SERVICE_NAME
  • host - detects host information
  • os - detects operating system details
  • process - detects process information

Available detector packages

Resource detectors for generic platforms or vendor-specific environments can be installed as pip packages.

Container Detection

This package provides an OpenTelemetry ResourceDetector which will detect docker container id at runtime, using cgroup information.

bash
pip install opentelemetry-resourcedetector-container
bash
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="container,env,host"
python app.py

Kubernetes Detection

This package provides resource detection for Kubernetes environments.

bash
pip install opentelemetry-resourcedetector-kubernetes
bash
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="kubernetes,env"
python app.py

AWS Services

AWS resource detectors are available in the AWS SDK extension package.

bash
pip install opentelemetry-sdk-extension-aws

The AWS detectors include:

  • aws_ec2 - EC2 instance metadata
  • aws_ecs - ECS task metadata
  • aws_eks - EKS cluster metadata
  • aws_lambda - Lambda function metadata
  • aws_beanstalk - Elastic Beanstalk environment
bash
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="aws_ec2,env"
python app.py

Custom resource via environment

If there is not an SDK detector for the resource you need, you can add arbitrary resources via the OTEL_RESOURCE_ATTRIBUTES environment variable, which is interpreted by the env detector:

bash
export OTEL_RESOURCE_ATTRIBUTES="service.name=my_service,service.namespace=demo,service.version=1.0,deployment.environment=development"
python app.py

Custom resource in code

Custom resources can also be configured in your code. Here, the default resources (detected as described above) are merged with custom resources:

python
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.semconv.resource import ResourceAttributes

# Create custom resource
custom_resource = Resource.create({
    ResourceAttributes.SERVICE_NAMESPACE: "foo",
    ResourceAttributes.SERVICE_NAME: "bar",
    ResourceAttributes.SERVICE_INSTANCE_ID: "1",
    ResourceAttributes.SERVICE_VERSION: "0.1",
    ResourceAttributes.DEPLOYMENT_ENVIRONMENT: "development",
})

# The SDK will automatically merge with default detected resources
tracer_provider = TracerProvider(resource=custom_resource)
tracer_provider.add_span_processor(
    BatchSpanProcessor(ConsoleSpanExporter())
)

Custom resource detector

If you need to detect custom information, you can create your own resource detector by implementing the ResourceDetector abstract class:

python
from opentelemetry.sdk.resources import Resource, ResourceDetector
from opentelemetry.semconv.resource import ResourceAttributes

class CustomResourceDetector(ResourceDetector):
    def detect(self) -> Resource:
        attributes = {
            "custom.key": "custom-value",
            "environment.type": "production",
        }

        # Add conditional detection logic
        try:
            import psutil
            attributes["system.memory.total"] = str(psutil.virtual_memory().total)
        except ImportError:
            pass

        return Resource(attributes)

# Use custom detector by registering it as entry point
# or by using get_aggregated_resources

Programmatic detector selection

You can also programmatically select which detectors to use:

python
from opentelemetry.sdk.resources import get_aggregated_resources
from opentelemetry.sdk.trace import TracerProvider

# Custom detector selection (for advanced use cases)
custom_detector = CustomResourceDetector()
resource = get_aggregated_resources([custom_detector])

tracer_provider = TracerProvider(resource=resource)

Production considerations

Performance

Resource detection runs during application initialization. For production systems:

  • Use OTEL_EXPERIMENTAL_RESOURCE_DETECTORS to disable unused detectors
  • Set timeouts for slow detectors (default is 5 seconds)
  • Consider the startup time impact of cloud metadata services

Error handling

Resource detectors are designed to be resilient:

  • Failed detectors are logged but don't prevent application startup
  • Missing dependencies are handled gracefully
  • Network failures in cloud detectors fall back to partial information

Example production configuration

python
import os
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.semconv.resource import ResourceAttributes

# Configure based on environment
env = os.getenv("DEPLOYMENT_ENV", "development")

if env == "production":
    # In production, be explicit about resource attributes
    resource = Resource.create({
        ResourceAttributes.SERVICE_NAME: os.getenv("SERVICE_NAME", "unknown"),
        ResourceAttributes.SERVICE_VERSION: os.getenv("SERVICE_VERSION", "unknown"),
        ResourceAttributes.DEPLOYMENT_ENVIRONMENT: env,
    })

    # Use minimal detectors for faster startup
    os.environ["OTEL_EXPERIMENTAL_RESOURCE_DETECTORS"] = "env,host"
else:
    # In development, use all detectors for better debugging
    resource = Resource.create({
        ResourceAttributes.SERVICE_NAME: "my-dev-service",
    })

tracer_provider = TracerProvider(resource=resource)

What's next?