Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PLATFORM-1698]: Support automatic extraction of K8S env vars for traces and metrics #99

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/layer/kube_env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use opentelemetry::KeyValue;
use tracing::{span, Subscriber};
use tracing_opentelemetry::OtelData;
use tracing_subscriber::{layer::Context, Layer};

// Extracts KUBE_APP_PART_OF, KUBE_APP_MANAGED_BY, KUBE_APP_VERSION and KUBE_APP_INSTANCE from the environment
// and adds them to span attributes
pub struct KubeEnvLayer {
pub kube_app_part_of: Option<String>,
pub kube_app_managed_by: Option<String>,
pub kube_app_version: Option<String>,
pub kube_app_instance: Option<String>,
}

impl Default for KubeEnvLayer {
fn default() -> Self {
Self {
kube_app_part_of: std::env::var("KUBE_APP_PART_OF").ok(),
kube_app_managed_by: std::env::var("KUBE_APP_MANAGED_BY").ok(),
kube_app_version: std::env::var("KUBE_APP_VERSION").ok(),
kube_app_instance: std::env::var("KUBE_APP_INSTANCE").ok(),
}
}
}

impl<S> Layer<S> for KubeEnvLayer
where
S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
{
fn on_new_span(&self, _attrs: &span::Attributes<'_>, id: &span::Id, ctx: Context<'_, S>) {
let span = ctx.span(id).expect("Span not found, this is a bug");
let mut extensions = span.extensions_mut();

if let Some(otel_data) = extensions.get_mut::<OtelData>() {
let builder = &mut otel_data.builder;
if let Some(ref mut attributes) = builder.attributes {
if let Some(ref part_of) = self.kube_app_part_of {
attributes.push(KeyValue::new("kube_app_part_of", part_of.clone()));
}
if let Some(ref managed_by) = self.kube_app_managed_by {
attributes.push(KeyValue::new("kube_app_managed_by", managed_by.clone()));
}
if let Some(ref version) = self.kube_app_version {
attributes.push(KeyValue::new("kube_app_version", version.clone()));
}
if let Some(ref instance) = self.kube_app_instance {
attributes.push(KeyValue::new("kube_app_instance", instance.clone()));
}
}
}
}
}
2 changes: 2 additions & 0 deletions src/layer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub use error::ErrorLayer;
pub use kube_env::KubeEnvLayer;
pub use version::VersionLayer;

mod error;
mod kube_env;
mod version;
2 changes: 2 additions & 0 deletions src/subscriber.rs
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ pub fn configure_subscriber<T: EventFormatter + Send + Sync + 'static>(
version: _config.version.clone(),
})
.with(crate::layer::ErrorLayer)
.with(crate::layer::KubeEnvLayer::default())
};

#[cfg(not(feature = "json-logger"))]
@@ -41,6 +42,7 @@ pub fn configure_subscriber<T: EventFormatter + Send + Sync + 'static>(
use crate::json::storage::PrimaJsonStorage;
subscriber
.with(PrimaJsonStorage)
.with(crate::layer::KubeEnvLayer::default())
.with(PrimaFormattingLayer::new(
_config.service.clone(),
_config.country.to_string(),