mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
feat: set OTEL resource attributes from the instance settings
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RbLzVfFDZ9pjBGHSzCSrNZ
This commit is contained in:
co-authored by
Claude Opus 5
parent
385086ffc2
commit
971f50993d
@@ -732,6 +732,8 @@ struct OtelSetting {
|
||||
otel_exporter_otlp_protocol: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_exporter_otlp_compression: Option<String>,
|
||||
#[serde(default, deserialize_with = "empty_as_none")]
|
||||
otel_resource_attributes: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn load_otel(db: &DB) {
|
||||
@@ -788,6 +790,15 @@ pub async fn load_otel(db: &DB) {
|
||||
std::env::set_var("OTEL_EXPORTER_OTLP_COMPRESSION", compression);
|
||||
}
|
||||
}
|
||||
if let Some(resource_attributes) = o.otel_resource_attributes {
|
||||
let merged = windmill_common::tracing_init::merge_otel_resource_attributes(
|
||||
&resource_attributes,
|
||||
std::env::var("OTEL_RESOURCE_ATTRIBUTES").ok().as_deref(),
|
||||
);
|
||||
unsafe {
|
||||
std::env::set_var("OTEL_RESOURCE_ATTRIBUTES", merged);
|
||||
}
|
||||
}
|
||||
println!("OTEL settings loaded: tracing ({tracing_enabled}), logs ({logs_enabled}), metrics ({metrics_enabled}), endpoint ({:?}), headers defined: ({})",
|
||||
endpoint, headers.is_some());
|
||||
} else {
|
||||
|
||||
@@ -745,3 +745,22 @@ fn test_otlp_resource_dedicated_overrides_win() {
|
||||
Some(windmill_common::utils::GIT_VERSION)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial_test::serial]
|
||||
fn test_otlp_resource_setting_attributes_keep_pod_attributes() {
|
||||
let merged = windmill_common::tracing_init::merge_otel_resource_attributes(
|
||||
"team=platform,region=eu-west-1",
|
||||
Some("k8s.pod.uid=abc-123,region=us-east-1"),
|
||||
);
|
||||
std::env::set_var("OTEL_RESOURCE_ATTRIBUTES", merged);
|
||||
let attrs = resource_attrs();
|
||||
std::env::remove_var("OTEL_RESOURCE_ATTRIBUTES");
|
||||
|
||||
assert_eq!(
|
||||
attrs.get("k8s.pod.uid").map(String::as_str),
|
||||
Some("abc-123")
|
||||
);
|
||||
assert_eq!(attrs.get("team").map(String::as_str), Some("platform"));
|
||||
assert_eq!(attrs.get("region").map(String::as_str), Some("us-east-1"));
|
||||
}
|
||||
|
||||
@@ -631,6 +631,8 @@ pub struct OtelSettings {
|
||||
pub otel_exporter_otlp_protocol: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub otel_exporter_otlp_compression: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub otel_resource_attributes: Option<String>,
|
||||
}
|
||||
|
||||
/// Per-language HTTP request tracing proxy configuration.
|
||||
|
||||
@@ -48,6 +48,17 @@ pub const VERBOSE_TARGET: &str = "windmill_verbose";
|
||||
/// when `OTEL_JOB_LOGS=true`. Stripped before forwarding to the tracing layer.
|
||||
pub const OTEL_PREFIX: &str = "OTEL: ";
|
||||
|
||||
/// Combines the instance setting's resource attributes with the `OTEL_RESOURCE_ATTRIBUTES` the
|
||||
/// process started with, which a deployment sets per pod (e.g. `k8s.pod.uid` from the downward
|
||||
/// API). Overwriting it would drop those; the env's pairs go last because the SDK keeps the last
|
||||
/// value of a duplicate key, so the pod's own value wins.
|
||||
pub fn merge_otel_resource_attributes(from_setting: &str, from_env: Option<&str>) -> String {
|
||||
match from_env.map(str::trim).filter(|v| !v.is_empty()) {
|
||||
Some(from_env) => format!("{from_setting},{from_env}"),
|
||||
None => from_setting.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a Targets filter that optionally filters out verbose logs when quiet mode is enabled.
|
||||
fn create_targets_filter(default_env_filter: LevelFilter) -> Targets {
|
||||
let targets =
|
||||
|
||||
@@ -694,6 +694,26 @@
|
||||
<option value="http/protobuf">http/protobuf</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<label
|
||||
for="OTEL_RESOURCE_ATTRIBUTES"
|
||||
class="block text-xs font-semibold text-emphasis">Resource attributes</label
|
||||
>
|
||||
<TextInput
|
||||
inputProps={{
|
||||
type: 'text',
|
||||
placeholder: 'team=platform,region=eu-west-1',
|
||||
id: 'OTEL_RESOURCE_ATTRIBUTES',
|
||||
disabled: !$enterpriseLicense
|
||||
}}
|
||||
bind:value={$values[setting.key].otel_resource_attributes}
|
||||
/>
|
||||
<span class="text-2xs font-normal text-secondary">
|
||||
Added to everything Windmill exports, alongside the OTEL_RESOURCE_ATTRIBUTES env
|
||||
var, which wins on a shared key. Windmill's own service.name, service.version,
|
||||
host.name and deployment.environment take precedence over both.
|
||||
</span>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else if setting.fieldType == 'otel_tracing_proxy'}
|
||||
|
||||
Reference in New Issue
Block a user