Overview
A Resource represents the entity producing telemetry data. Resources are immutable and contain attributes that describe your application, service, host, and environment.
Resource attributes
Common resource attributes include:
service.name - Your service name
service.version - Application version
service.instance.id - Unique instance identifier
host.name - Hostname
process.pid - Process ID
deployment.environment - Environment (dev, staging, prod)
Resource builders
OpenTelemetry Rust provides two ways to create resources:
Default builder
Includes built-in detectors:
use opentelemetry_sdk :: Resource ;
let resource = Resource :: builder ()
. with_service_name ( "my-service" )
. build ();
The default builder includes:
SdkProvidedResourceDetector - SDK name and version
TelemetryResourceDetector - Telemetry SDK information
EnvResourceDetector - Environment variables
Empty builder
Start with no attributes:
use opentelemetry_sdk :: Resource ;
use opentelemetry :: KeyValue ;
let resource = Resource :: builder_empty ()
. with_attributes ( vec! [
KeyValue :: new ( "service.name" , "my-service" ),
KeyValue :: new ( "service.version" , "1.0.0" ),
])
. build ();
Built-in resource detectors
SdkProvidedResourceDetector
Provides OpenTelemetry SDK information:
use opentelemetry_sdk :: resource :: SdkProvidedResourceDetector ;
let detector = SdkProvidedResourceDetector ;
let resource = detector . detect ();
// Attributes detected:
// - telemetry.sdk.name = "opentelemetry"
// - telemetry.sdk.language = "rust"
// - telemetry.sdk.version = "0.31.0"
TelemetryResourceDetector
Provides telemetry SDK-specific information:
use opentelemetry_sdk :: resource :: TelemetryResourceDetector ;
let detector = TelemetryResourceDetector ;
let resource = detector . detect ();
EnvResourceDetector
Detects resources from environment variables:
use opentelemetry_sdk :: resource :: EnvResourceDetector ;
let detector = EnvResourceDetector :: new ();
let resource = detector . detect ();
Environment variables:
OTEL_RESOURCE_ATTRIBUTES - Key-value pairs: key1=value1,key2=value2
OTEL_SERVICE_NAME - Service name (overrides service.name in attributes)
Example:
export OTEL_SERVICE_NAME = my-service
export OTEL_RESOURCE_ATTRIBUTES = "service.version=1.0.0,deployment.environment=production"
Service name priority
Service name is resolved in this order (highest to lowest priority):
OTEL_SERVICE_NAME environment variable
service.name in OTEL_RESOURCE_ATTRIBUTES
with_service_name() builder method
service.name in custom attributes
Default: "unknown_service"
use opentelemetry_sdk :: Resource ;
// Priority 3: Builder method
let resource = Resource :: builder ()
. with_service_name ( "my-service" )
. build ();
// Priority 1: Environment variable (overrides builder)
// export OTEL_SERVICE_NAME=production-service
Custom resource detectors
Implement the ResourceDetector trait:
use opentelemetry_sdk :: resource :: ResourceDetector ;
use opentelemetry :: KeyValue ;
struct CustomDetector ;
impl ResourceDetector for CustomDetector {
fn detect ( & self ) -> Vec < KeyValue > {
vec! [
KeyValue :: new ( "custom.attribute" , "value" ),
KeyValue :: new ( "build.id" , env! ( "BUILD_ID" )),
]
}
}
Use custom detector:
let resource = Resource :: builder_empty ()
. with_detector ( Box :: new ( CustomDetector ))
. build ();
Merging resources
Merge multiple resources together:
use opentelemetry_sdk :: Resource ;
use opentelemetry :: KeyValue ;
let base_resource = Resource :: builder ()
. with_service_name ( "my-service" )
. build ();
let custom_resource = Resource :: builder_empty ()
. with_attributes ( vec! [
KeyValue :: new ( "deployment.environment" , "production" ),
KeyValue :: new ( "service.version" , "2.0.0" ),
])
. build ();
// Merge resources (custom_resource takes precedence)
let merged = base_resource . merge ( & custom_resource );
Schema URLs
Resources can include a schema URL that identifies the semantic convention version:
use opentelemetry_sdk :: Resource ;
use opentelemetry :: KeyValue ;
let resource = Resource :: builder_empty ()
. with_schema_url ( "https://opentelemetry.io/schemas/1.21.0" )
. with_attributes ( vec! [
KeyValue :: new ( "service.name" , "my-service" ),
])
. build ();
When merging resources with different schema URLs, the operation may fail if the schemas are incompatible.
Using resources with providers
TracerProvider
use opentelemetry_sdk :: {
trace :: TracerProvider ,
Resource ,
};
let resource = Resource :: builder ()
. with_service_name ( "my-trace-service" )
. build ();
let provider = TracerProvider :: builder ()
. with_resource ( resource )
. build ();
MeterProvider
use opentelemetry_sdk :: {
metrics :: MeterProvider ,
Resource ,
};
let resource = Resource :: builder ()
. with_service_name ( "my-metrics-service" )
. build ();
let provider = MeterProvider :: builder ()
. with_resource ( resource )
. build ();
LoggerProvider
use opentelemetry_sdk :: {
logs :: LoggerProvider ,
Resource ,
};
let resource = Resource :: builder ()
. with_service_name ( "my-logging-service" )
. build ();
let provider = LoggerProvider :: builder ()
. with_resource ( resource )
. build ();
Complete example
use opentelemetry :: KeyValue ;
use opentelemetry_sdk :: {
trace :: { TracerProvider , BatchSpanProcessor },
Resource ,
};
use opentelemetry_otlp :: SpanExporter ;
#[tokio :: main]
async fn main () -> Result <(), Box < dyn std :: error :: Error >> {
// Create custom resource
let resource = Resource :: builder ()
. with_service_name ( env! ( "CARGO_PKG_NAME" ))
. with_attributes ( vec! [
KeyValue :: new ( "service.version" , env! ( "CARGO_PKG_VERSION" )),
KeyValue :: new ( "deployment.environment" , "production" ),
KeyValue :: new ( "service.instance.id" , uuid :: Uuid :: new_v4 () . to_string ()),
])
. build ();
// Use resource in provider
let exporter = SpanExporter :: builder () . with_http () . build () ? ;
let processor = BatchSpanProcessor :: builder ( exporter , opentelemetry_sdk :: runtime :: Tokio ) . build ();
let provider = TracerProvider :: builder ()
. with_resource ( resource )
. with_span_processor ( processor )
. build ();
Ok (())
}
OS and Process detectors
For more advanced resource detection (OS, process, host info), use the separate opentelemetry-resource-detectors crate:
[ dependencies ]
opentelemetry-resource-detectors = "0.1"
use opentelemetry_resource_detectors :: { OsResourceDetector , ProcessResourceDetector };
use opentelemetry_sdk :: Resource ;
let resource = Resource :: builder ()
. with_detector ( Box :: new ( OsResourceDetector ))
. with_detector ( Box :: new ( ProcessResourceDetector ))
. build ();
This provides:
host.name
host.arch
os.type
os.description
process.pid
process.executable.name
process.command_line
process.runtime.name
process.runtime.version
Best practices
Always set service.name - This is the most important resource attribute for identifying your service in observability backends.
Environment-based configuration - Use OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES environment variables for deployment-specific configuration.
Resources concept Learn about resource fundamentals
Semantic conventions Standard attribute names