Skip to content

Commit

Permalink
Merge pull request #88 from 4t145/support-tardis-tracing-standalone-mode
Browse files Browse the repository at this point in the history
1. add standalone mode for tardis tracing
2. add some shortcuts for some build env varibles
  • Loading branch information
4t145 authored Oct 31, 2023
2 parents 0af3ff3 + 53c23f2 commit 40e3f16
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 66 deletions.
179 changes: 117 additions & 62 deletions tardis/src/basic/tracing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::sync::Once;
use std::sync::{Arc, Once};

use crate::basic::result::TardisResult;
use crate::config::config_dto::LogConfig;
Expand All @@ -7,11 +7,16 @@ use crate::config::config_dto::LogConfig;
use crate::consts::*;
use crate::TARDIS_INST;
pub use tracing_subscriber::filter::Directive;
use tracing_subscriber::layer::Layered;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
#[allow(unused_imports)]
use tracing_subscriber::{fmt::Layer as FmtLayer, layer::SubscriberExt, prelude::*, reload::Layer as ReloadLayer, Registry};
use tracing_subscriber::{
fmt::Layer as FmtLayer,
layer::{Layered, SubscriberExt},
prelude::*,
registry::LookupSpan,
reload::Layer as ReloadLayer,
util::SubscriberInitExt,
EnvFilter, Registry,
};

/// # Tardis Tracing
/// Tardis tracing is a wrapper of tracing-subscriber. It provides configurable layers as runtime.
Expand All @@ -26,14 +31,14 @@ pub struct TardisTracing<C = LogConfig> {
}

// create a configurable layer, recieve a layer and a configer, return a reload layer and a config function
fn create_configurable_layer<L, S, C>(layer: L, configer: impl Fn(&C) -> TardisResult<L> + Send + Sync) -> TardisResult<(ReloadLayer<L, S>, impl Fn(&C) -> TardisResult<()>)> {
fn create_configurable_layer<L, S, C>(layer: L, configer: impl Fn(&C) -> TardisResult<L> + Send + Sync) -> (ReloadLayer<L, S>, impl Fn(&C) -> TardisResult<()>) {
let (reload_layer, reload_handle) = ReloadLayer::new(layer);
let config_layer_fn = move |conf: &C| -> TardisResult<()> {
let layer = configer(conf)?;
reload_handle.reload(layer)?;
Ok(())
};
Ok((reload_layer, config_layer_fn))
(reload_layer, config_layer_fn)
}

/// Tardis tracing initializer
Expand Down Expand Up @@ -79,17 +84,17 @@ where
mut self,
layer: L,
configer: impl Fn(&C) -> TardisResult<L> + 'static + Send + Sync,
) -> TardisResult<TardisTracingInitializer<Layered<ReloadLayer<L, S>, L0>, C>>
) -> TardisTracingInitializer<Layered<ReloadLayer<L, S>, L0>, C>
where
ReloadLayer<L, S>: tracing_subscriber::Layer<L0>,
L: 'static + Send + Sync,
{
let (reload_layer, config_layer_fn) = create_configurable_layer::<L, S, C>(layer, configer)?;
let (reload_layer, config_layer_fn) = create_configurable_layer::<L, S, C>(layer, configer);
self.configers.push(Box::new(config_layer_fn));
Ok(TardisTracingInitializer {
TardisTracingInitializer {
configers: self.configers,
layered: self.layered.with(reload_layer),
})
}
}

pub fn with_layer<L>(self, layer: L) -> TardisTracingInitializer<Layered<L, L0>, C>
Expand All @@ -103,11 +108,91 @@ where
}
}

type BoxLayer<S> = Box<dyn tracing_subscriber::Layer<S> + Send + Sync + 'static>;
impl<L0> TardisTracingInitializer<L0, LogConfig>
where
L0: SubscriberExt,
{
pub fn with_fmt_layer<S>(self) -> TardisTracingInitializer<Layered<BoxLayer<S>, L0>, LogConfig>
where
S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
BoxLayer<S>: tracing_subscriber::Layer<L0>,
{
self.with_layer(FmtLayer::default().boxed())
}
pub fn with_env_layer<S>(self) -> TardisTracingInitializer<Layered<ReloadLayer<BoxLayer<S>, S>, L0>, LogConfig>
where
S: tracing::Subscriber,
ReloadLayer<BoxLayer<S>, S>: tracing_subscriber::Layer<L0>,
{
self.with_configurable_layer(EnvFilter::from_default_env().boxed(), |config: &LogConfig| {
let mut env_filter = EnvFilter::from_default_env();
env_filter = env_filter.add_directive(config.level.clone());
for directive in &config.directives {
env_filter = env_filter.add_directive(directive.clone());
}
std::env::set_var("RUST_LOG", env_filter.to_string());
Ok(env_filter.boxed())
})
}

#[cfg(feature = "tracing")]
pub fn with_opentelemetry_layer<S>(self) -> TardisTracingInitializer<Layered<ReloadLayer<BoxLayer<S>, S>, L0>, LogConfig>
where
S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
ReloadLayer<BoxLayer<S>, S>: tracing_subscriber::Layer<L0>,
{
self.with_configurable_layer(
tracing_opentelemetry::layer().with_tracer(TardisTracing::<LogConfig>::create_otlp_tracer()).boxed(),
|conf: &LogConfig| {
if std::env::var_os(OTEL_EXPORTER_OTLP_ENDPOINT).is_none() {
std::env::set_var(OTEL_EXPORTER_OTLP_ENDPOINT, conf.tracing.endpoint.as_str());
}
if std::env::var_os(OTEL_EXPORTER_OTLP_PROTOCOL).is_none() {
std::env::set_var(OTEL_EXPORTER_OTLP_PROTOCOL, conf.tracing.protocol.to_string());
}
if std::env::var_os(OTEL_SERVICE_NAME).is_none() {
std::env::set_var(OTEL_SERVICE_NAME, conf.tracing.server_name.as_str());
}
Ok(tracing_opentelemetry::layer().with_tracer(TardisTracing::<LogConfig>::create_otlp_tracer()).boxed())
},
)
}

#[cfg(feature = "console-subscriber")]
pub fn with_console_layer<S>(self) -> TardisTracingInitializer<Layered<BoxLayer<S>, L0>, LogConfig>
where
S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
BoxLayer<S>: tracing_subscriber::Layer<L0>,
{
self.with_layer(console_subscriber::ConsoleLayer::builder().with_default_env().spawn().boxed())
}

#[cfg(feature = "tracing-appender")]
pub fn with_appender_layer<S>(self) -> TardisTracingInitializer<Layered<ReloadLayer<BoxLayer<S>, S>, L0>, LogConfig>
where
S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
ReloadLayer<BoxLayer<S>, S>: tracing_subscriber::Layer<L0>,
{
use crate::config::config_dto::log::TracingAppenderConfig;
let config_file_layer = |cfg: Option<&TracingAppenderConfig>| {
if let Some(cfg) = &cfg {
let file_appender = tracing_appender::rolling::RollingFileAppender::new(cfg.rotation.into(), &cfg.dir, &cfg.filename);
FmtLayer::default().with_writer(file_appender).boxed()
} else {
FmtLayer::default().with_writer(std::io::sink).boxed()
}
};
self.with_configurable_layer(config_file_layer(None), move |cfg| TardisResult::Ok(config_file_layer(cfg.tracing_appender.as_ref())))
}
}

impl<L> TardisTracingInitializer<L>
where
L: SubscriberInitExt + 'static,
{
pub fn init(self) {
/// Initialize tardis tracing, this will set the global tardis tracing instance.
pub(crate) fn init(self) -> Arc<TardisTracing> {
static INITIALIZED: Once = Once::new();
let configer_list = self.configers;
if INITIALIZED.is_completed() {
Expand All @@ -116,12 +201,23 @@ where
INITIALIZED.call_once(|| self.layered.init());
TARDIS_INST.tracing.set(TardisTracing { configer: configer_list });
}
crate::TardisFuns::tracing()
}

/// Initialize tardis tracing as standalone, this will not set the global tardis tracing instance.
/// # Warning
/// Config this standalong instance will also change the value of env variable `RUST_LOG`,
/// if you are using the global tardis tracing instance, you should use [`TardisTracingInitializer::init`] instead.
pub fn init_standalone(self) -> TardisTracing {
let configer_list = self.configers;
self.layered.init();
TardisTracing { configer: configer_list }
}
}

impl TardisTracing<LogConfig> {
/// Get an initializer for tardis tracing
pub fn init() -> TardisTracingInitializer<Registry, LogConfig> {
pub fn initializer() -> TardisTracingInitializer<Registry, LogConfig> {
TardisTracingInitializer::default()
}

Expand All @@ -138,67 +234,26 @@ impl TardisTracing<LogConfig> {

pub(crate) fn init_default() -> TardisResult<()> {
tracing::info!("[Tardis.Tracing] Initializing by defualt initializer.");
let initializer = TardisTracingInitializer::default();
let initializer = initializer.with_layer(FmtLayer::default());
let initializer = initializer.with_configurable_layer(EnvFilter::from_default_env(), |config: &LogConfig| {
let mut env_filter = EnvFilter::from_default_env();
env_filter = env_filter.add_directive(config.level.clone());
for directive in &config.directives {
env_filter = env_filter.add_directive(directive.clone());
}
std::env::set_var("RUST_LOG", env_filter.to_string());
Ok(env_filter)
})?;
let initializer = TardisTracingInitializer::default().with_fmt_layer().with_env_layer();
tracing::debug!("[Tardis.Tracing] Added fmt layer and env filter.");
#[cfg(feature = "tracing")]
let initializer = {
let initializer = initializer.with_configurable_layer(tracing_opentelemetry::layer().with_tracer(Self::create_otlp_tracer()?), |conf: &LogConfig| {
if std::env::var_os(OTEL_EXPORTER_OTLP_ENDPOINT).is_none() {
std::env::set_var(OTEL_EXPORTER_OTLP_ENDPOINT, conf.tracing.endpoint.as_str());
}
if std::env::var_os(OTEL_EXPORTER_OTLP_PROTOCOL).is_none() {
std::env::set_var(OTEL_EXPORTER_OTLP_PROTOCOL, conf.tracing.protocol.to_string());
}
if std::env::var_os(OTEL_SERVICE_NAME).is_none() {
std::env::set_var(OTEL_SERVICE_NAME, conf.tracing.server_name.as_str());
}
Ok(tracing_opentelemetry::layer().with_tracer(Self::create_otlp_tracer()?))
})?;
tracing::debug!("[Tardis.Tracing] Added fmt layer and env filter.");
initializer
};
let initializer = initializer.with_opentelemetry_layer();
#[cfg(feature = "console-subscriber")]
let initializer = {
use console_subscriber::ConsoleLayer;
tracing::info!("[Tardis.Tracing] Initializing console subscriber. To make it work, you need to enable tokio and runtime tracing targets at **TRACE** level.");
let layer = ConsoleLayer::builder().with_default_env().spawn();
initializer.with_layer(layer)
};
let initializer = initializer.with_console_layer();
#[cfg(feature = "tracing-appender")]
let initializer = {
use crate::config::config_dto::log::TracingAppenderConfig;
let config_file_layer = |cfg: Option<&TracingAppenderConfig>| {
if let Some(cfg) = &cfg {
let file_appender = tracing_appender::rolling::RollingFileAppender::new(cfg.rotation.into(), &cfg.dir, &cfg.filename);
FmtLayer::default().with_writer(file_appender).boxed()
} else {
FmtLayer::default().with_writer(std::io::sink).boxed()
}
};
initializer.with_configurable_layer(config_file_layer(None), move |cfg| TardisResult::Ok(config_file_layer(cfg.tracing_appender.as_ref())))?
};
let initializer = initializer.with_appender_layer();
tracing::info!("[Tardis.Tracing] Initialize finished.");
initializer.init();
Ok(())
}

#[cfg(feature = "tracing")]
fn create_otlp_tracer() -> TardisResult<opentelemetry::sdk::trace::Tracer> {
fn create_otlp_tracer() -> opentelemetry::sdk::trace::Tracer {
use opentelemetry_otlp::WithExportConfig;

use crate::config::config_dto::OtlpProtocol;
tracing::debug!("[Tardis.Tracing] Initializing otlp tracer");
let protocol = std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL).ok().map(|s| s.parse::<OtlpProtocol>()).transpose()?.unwrap_or_default();
let protocol = std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL).ok().map(|s| s.parse::<OtlpProtocol>().unwrap_or_default()).unwrap_or_default();
let mut tracer = opentelemetry_otlp::new_pipeline().tracing();
match protocol {
OtlpProtocol::Grpc => {
Expand All @@ -218,9 +273,9 @@ impl TardisTracing<LogConfig> {
}
};
tracing::debug!("[Tardis.Tracing] Batch installing tracer. If you are blocked here, try running tokio in multithread.");
let tracer = tracer.install_batch(opentelemetry::runtime::Tokio)?;
let tracer = tracer.install_batch(opentelemetry::runtime::Tokio).expect("fail to install otlp tracer");
tracing::debug!("[Tardis.Tracing] Initialized otlp tracer");
Ok(tracer)
tracer
}

#[cfg(feature = "tracing")]
Expand Down
3 changes: 3 additions & 0 deletions tardis/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ pub const OTEL_EXPORTER_OTLP_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
pub const OTEL_EXPORTER_OTLP_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_PROTOCOL";
pub const OTEL_EXPORTER_OTLP_HEADERS: &str = "OTEL_EXPORTER_OTLP_HEADERS";
pub const OTEL_SERVICE_NAME: &str = "OTEL_SERVICE_NAME";

// shortcuts for build info
pub const TARDIS_VERSION: &str = env!("CARGO_PKG_VERSION");
1 change: 1 addition & 0 deletions tardis/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ pub mod tardis_component;
pub(crate) use tardis_component::*;
pub mod initializer;
pub mod mapper;
pub mod package_name;
pub mod tardis_static;
6 changes: 6 additions & 0 deletions tardis/src/utils/package_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[macro_export]
macro_rules! pkg {
() => {
env!("CARGO_PKG_NAME")
};
}
6 changes: 3 additions & 3 deletions tardis/tests/test_basic_tracing.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::app::req::test_req;
use tardis::basic::result::TardisResult;
use tardis::TardisFuns;
use tardis::basic::{result::TardisResult, tracing::TardisTracing};
use tracing::{error, info};

#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_basic_tracing() -> TardisResult<()> {
// env::set_var("RUST_LOG", "OFF");
// env::set_var("RUST_LOG", "info");
TardisFuns::init(Some("tests/config")).await?;
let _tardis_tracing = TardisTracing::initializer().with_fmt_layer().with_env_layer().with_opentelemetry_layer().init_standalone();
// TardisFuns::init(Some("tests/config")).await?;
let _g = tracing::trace_span!("main");
let _g = _g.enter();
info!("main info...");
Expand Down
1 change: 0 additions & 1 deletion tardis/tests/test_os_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use tardis::TardisFuns;
async fn test_os_client() -> TardisResult<()> {
env::set_var("RUST_LOG", "info,tardis=trace");
TardisFuns::init_log()?;

TardisTestContainer::minio(|url| async move {
let os_module_config = OSModuleConfig::builder().kind("s3").endpoint(url).ak("minioadmin").sk("minioadmin").region("us-east-1").build();
TardisFuns::init_conf(TardisConfig::builder().fw(FrameworkConfig::builder().os(os_module_config).build()).build()).await?;
Expand Down

0 comments on commit 40e3f16

Please sign in to comment.