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:
# 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_ATTRIBUTESandOTEL_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.
pip install opentelemetry-resourcedetector-container
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="container,env,host"
python app.py
Kubernetes Detection
This package provides resource detection for Kubernetes environments.
pip install opentelemetry-resourcedetector-kubernetes
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="kubernetes,env"
python app.py
AWS Services
AWS resource detectors are available in the AWS SDK extension package.
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
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:
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:
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:
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:
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_DETECTORSto 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
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)