Description
There appears to be an inconsistency between the documented/implied behavior and actual implementation regarding resource configuration in OpenTelemetry Erlang, specifically with respect to processor-specific resource configurations.
Observed Behavior
When configuring a resource at the processor level like this:
config :opentelemetry,
processors: [
otel_batch_processor: %{
resource: %{
"service.name" => "my_service",
"custom.attribute" => "value"
},
exporter: {...}
}
]
The processor initialization code in otel_batch_processor.erl appears to handle this configuration:
Resource = case maps:find(resource, Args) of
{ok, R} ->
R;
error ->
otel_resource_detector:get_resource()
end,
However, when spans are exported, this processor-specific resource is not used. Instead, the export function in otel_exporter_traces_otlp.erl uses the global resource passed to it:
export(Tab, Resource, #state{...}) ->
case otel_otlp_traces:to_proto(Tab, Resource) of
...
Attempting to use processor-specific resources leads to errors like:
[info] span exporter threw exception: exporter=:opentelemetry_exporter exception error: no function clause matching
otel_attributes:dropped(undefined) (src/otel_attributes.erl, line 92)
in function otel_otlp_traces:to_proto/2 (.../deps/opentelemetry_exporter/src/otel_otlp_traces.erl, line 39)
This occurs because while the processor initialization accepts a resource configuration, this resource is never passed to the export function.
Expected Behavior
One of the following should be true:
- If processor-specific resources are intended to be supported, then the processor-specific resource should be passed to the export function and merged with or override the global resource.
- If processor-specific resources are not intended to be supported, then the configuration option should either be removed from the processor initialization or clearly documented as not functioning.
Questions
- Is it intentional that processor-specific resources don't affect the exported spans?
- Should users always configure resources at the global level (config :opentelemetry, resource: %{...}) instead of at the processor level?
- If processor-specific resources are intended to be supported, is there a bug in how they're passed to the export function?
Environment
- Erlang/OTP: 26.1
- Elixir: 1.18.3
- opentelemetry: 1.5.0
- opentelemetry_api: 1.4.0
- opentelemetry_exporter: 1.8.0
Workaround
The current workaround is to always configure resources at the global level:
config :opentelemetry,
resource: %{
"service.name" => "my_service",
"custom.attribute" => "value"
},
processors: [
otel_batch_processor: %{
exporter: {...}
}
]
This ensures that all resources are properly included in exported spans. However, we may not want this if using multiple processors.