From 5c49d180bf38f4855fb6af124705dee9064c8285 Mon Sep 17 00:00:00 2001 From: hamz2a Date: Wed, 18 Dec 2024 12:52:53 +0100 Subject: [PATCH] editoast: setup tracing with opentelemetry for TestApp Signed-off-by: hamz2a --- editoast/src/client/telemetry_config.rs | 10 ++++++ editoast/src/main.rs | 42 ++++++++++++++++++------- editoast/src/views/mod.rs | 2 +- editoast/src/views/test_app.rs | 31 ++++++++++++------ 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/editoast/src/client/telemetry_config.rs b/editoast/src/client/telemetry_config.rs index 738fc2c0ec6..6bbaf1e4ba6 100644 --- a/editoast/src/client/telemetry_config.rs +++ b/editoast/src/client/telemetry_config.rs @@ -17,6 +17,16 @@ pub struct TelemetryConfig { pub telemetry_endpoint: Url, } +#[cfg(test)] +impl From for TelemetryConfig { + fn from(_value: crate::views::test_app::OpentelemetryConfig) -> Self { + Self { + telemetry_kind: TelemetryKind::Opentelemetry, + ..Default::default() + } + } +} + #[derive(Default, ValueEnum, Debug, Derivative, Clone, strum::Display)] #[strum(serialize_all = "lowercase")] pub enum TelemetryKind { diff --git a/editoast/src/main.rs b/editoast/src/main.rs index 7ca4b46553f..e196c752f16 100644 --- a/editoast/src/main.rs +++ b/editoast/src/main.rs @@ -30,13 +30,18 @@ use client::user::UserCommand; use client::Client; use client::Color; use client::Commands; +use client::TelemetryConfig; use editoast_models::DbConnectionPoolV2; use models::RollingStockModel; use opentelemetry::trace::TracerProvider as _; +use opentelemetry_sdk::export::trace::SpanExporter; use opentelemetry_sdk::propagation::TraceContextPropagator; use opentelemetry_sdk::resource::EnvResourceDetector; use opentelemetry_sdk::resource::SdkProvidedResourceDetector; use opentelemetry_sdk::resource::TelemetryResourceDetector; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::Layer; pub use views::AppState; use models::prelude::*; @@ -50,9 +55,6 @@ use std::sync::Arc; use std::time::Duration; use thiserror::Error; use tracing::error; -use tracing_subscriber::layer::SubscriberExt as _; -use tracing_subscriber::util::SubscriberInitExt as _; -use tracing_subscriber::Layer as _; pub use valkey_utils::ValkeyClient; pub use valkey_utils::ValkeyConnection; @@ -66,12 +68,23 @@ pub use valkey_utils::ValkeyConnection; /// - we *expect* a webserver to output logging information, so since it's an expected /// output (and not extra information), it should be on stdout #[derive(Debug, PartialEq)] -enum EditoastMode { +pub enum EditoastMode { Webservice, Cli, } -fn init_tracing(mode: EditoastMode, telemetry_config: &client::TelemetryConfig) { +#[cfg(test)] +impl From for EditoastMode { + fn from(_value: views::test_app::WebserviceMode) -> Self { + Self::Webservice + } +} + +pub fn create_tracing_subscriber( + mode: EditoastMode, + telemetry_config: TelemetryConfig, + exporter: T, +) -> impl tracing::Subscriber { let env_filter_layer = tracing_subscriber::EnvFilter::builder() // Set the default log level to 'info' .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) @@ -89,11 +102,6 @@ fn init_tracing(mode: EditoastMode, telemetry_config: &client::TelemetryConfig) let telemetry_layer = match telemetry_config.telemetry_kind { client::TelemetryKind::None => None, client::TelemetryKind::Opentelemetry => { - let exporter = opentelemetry_otlp::SpanExporter::builder() - .with_tonic() - .with_endpoint(telemetry_config.telemetry_endpoint.as_str()) - .build() - .expect("failed to build a span exporter"); let resource = Resource::new(vec![KeyValue::new( opentelemetry_semantic_conventions::resource::SERVICE_NAME, telemetry_config.service_name.clone(), @@ -116,11 +124,11 @@ fn init_tracing(mode: EditoastMode, telemetry_config: &client::TelemetryConfig) Some(layer) } }; + tracing_subscriber::registry() .with(telemetry_layer) .with(env_filter_layer) .with(fmt_layer) - .init(); } impl EditoastMode { @@ -151,7 +159,17 @@ async fn main() { async fn run() -> Result<(), Box> { let client = Client::parse(); - init_tracing(EditoastMode::from_client(&client), &client.telemetry_config); + let exporter = opentelemetry_otlp::SpanExporter::builder() + .with_tonic() + .with_endpoint(client.telemetry_config.telemetry_endpoint.as_str()) + .build() + .expect("failed to build a span exporter"); + create_tracing_subscriber( + EditoastMode::from_client(&client), + client.telemetry_config, + exporter, + ) + .init(); let pg_config = client.postgres_config; let db_pool = diff --git a/editoast/src/views/mod.rs b/editoast/src/views/mod.rs index 824fd3d6259..b418628ba38 100644 --- a/editoast/src/views/mod.rs +++ b/editoast/src/views/mod.rs @@ -22,7 +22,7 @@ pub mod train_schedule; pub mod work_schedules; #[cfg(test)] -mod test_app; +pub mod test_app; use ::core::str; use std::collections::HashSet; diff --git a/editoast/src/views/test_app.rs b/editoast/src/views/test_app.rs index 9ab47d93081..0912b9182ef 100644 --- a/editoast/src/views/test_app.rs +++ b/editoast/src/views/test_app.rs @@ -9,12 +9,17 @@ use axum_tracing_opentelemetry::middleware::OtelAxumLayer; use dashmap::DashMap; use editoast_models::DbConnectionPoolV2; use editoast_osrdyne_client::OsrdyneClient; +use futures::future::BoxFuture; +use opentelemetry_sdk::export::trace::ExportResult; +use opentelemetry_sdk::export::trace::SpanData; +use opentelemetry_sdk::export::trace::SpanExporter; use serde::de::DeserializeOwned; use tower_http::trace::TraceLayer; use url::Url; use crate::{ core::{mocking::MockingClient, CoreClient}, + create_tracing_subscriber, generated_data::speed_limit_tags_config::SpeedLimitTagIds, infra_cache::InfraCache, map::MapLayers, @@ -26,6 +31,15 @@ use axum_test::TestServer; use super::{authentication_middleware, CoreConfig, OsrdyneConfig, PostgresConfig, ServerConfig}; +#[derive(Debug)] +pub struct NoopSpanExporter; + +impl SpanExporter for NoopSpanExporter { + fn export(&mut self, _: Vec) -> BoxFuture<'static, ExportResult> { + Box::pin(std::future::ready(Ok(()))) + } +} + /// A builder interface for [TestApp] /// /// It allows configuring some parameters for the app service. @@ -106,15 +120,11 @@ impl TestAppBuilder { }; // Setup tracing - let sub = tracing_subscriber::fmt() - .pretty() - .with_env_filter( - tracing_subscriber::EnvFilter::builder() - .with_default_directive(tracing_subscriber::filter::LevelFilter::DEBUG.into()) - .from_env_lossy(), - ) - .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE) - .finish(); + let sub = create_tracing_subscriber( + WebserviceMode.into(), + OpentelemetryConfig.into(), + NoopSpanExporter, + ); let tracing_guard = tracing::subscriber::set_default(sub); // Config valkey @@ -180,6 +190,9 @@ impl TestAppBuilder { } } +pub(crate) struct WebserviceMode; +pub(crate) struct OpentelemetryConfig; + /// Wraps an underlying, fully configured, actix service /// /// It also holds a reference to the database connection pool and the core client,