use std::marker::PhantomData;
#[allow(unused_imports)]
use std::{pin::Pin, sync::Arc};
#[allow(unused_imports)] use tracing::metadata::LevelFilter;
use tracing::Subscriber;
#[allow(unused_imports)]
use tracing_subscriber::filter::{combinator::And, FilterExt, Filtered, Targets};
use tracing_subscriber::registry::LookupSpan;
#[allow(unused_imports)]
use tracing_subscriber::{layer::Filter, Layer};
use crate::error::EtwError;
#[cfg(any(not(feature = "global_filter"), docsrs))]
use crate::layer::EtwFilter;
use crate::layer::{EtwLayer, _EtwLayer};
use crate::native::{
CommonSchemaOutput, EventWriter, GuidWrapper, NormalOutput, OutputMode, ProviderTraits,
};
pub struct LayerBuilder<OutMode: OutputMode> {
provider_name: Box<str>,
provider_id: GuidWrapper,
provider_group: Option<crate::native::ProviderGroupType>,
default_keyword: u64,
_o: PhantomData<OutMode>,
}
impl LayerBuilder<NormalOutput> {
#[allow(clippy::new_ret_no_self)]
pub fn new(name: &str) -> LayerBuilder<NormalOutput> {
LayerBuilder::<NormalOutput> {
provider_name: name.to_string().into_boxed_str(),
provider_id: GuidWrapper::from_name(name),
provider_group: None,
default_keyword: 1,
_o: PhantomData,
}
}
}
impl LayerBuilder<CommonSchemaOutput> {
pub fn new_common_schema_events(name: &str) -> LayerBuilder<CommonSchemaOutput> {
LayerBuilder::<CommonSchemaOutput> {
provider_name: name.to_string().into_boxed_str(),
provider_id: GuidWrapper::from_name(name),
provider_group: None,
default_keyword: 1,
_o: PhantomData,
}
}
}
impl<OutMode: OutputMode + 'static> LayerBuilder<OutMode> {
pub fn with_provider_id<G>(mut self, guid: &G) -> Self
where
for<'a> &'a G: Into<GuidWrapper>,
{
self.provider_id = guid.into();
self
}
pub fn get_provider_id(&self) -> GuidWrapper {
self.provider_id
}
pub fn with_default_keyword(mut self, kw: u64) -> Self {
self.default_keyword = kw;
self
}
pub fn with_provider_group<G>(mut self, group_id: &G) -> Self
where
for<'a> &'a G: Into<crate::native::ProviderGroupType>,
{
self.provider_group = Some(group_id.into());
self
}
fn validate_config(&self) -> Result<(), EtwError> {
crate::native::Provider::<OutMode>::is_valid_provider(&self.provider_name).and_then(|_| {
self.provider_group.as_ref().map_or_else(
|| Ok(()),
|group| {
crate::native::Provider::<OutMode>::is_valid_group(&self.provider_name, group)
},
)
})
}
#[cfg(any(not(feature = "global_filter"), docsrs))]
fn build_target_filter(&self, target: &'static str) -> Targets {
let mut targets = Targets::new().with_target(&*self.provider_name, LevelFilter::TRACE);
if !target.is_empty() {
targets = targets.with_target(target, LevelFilter::TRACE)
}
targets
}
fn build_layer<S>(&self) -> EtwLayer<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
crate::native::Provider<OutMode>: ProviderTraits + EventWriter<OutMode>,
{
EtwLayer::<S, OutMode> {
layer: _EtwLayer {
provider: crate::native::Provider::<OutMode>::new(
&self.provider_name,
&self.provider_id,
&self.provider_group,
self.default_keyword,
),
default_keyword: self.default_keyword,
_p: PhantomData,
},
}
}
#[cfg(any(not(feature = "global_filter"), docsrs))]
fn build_filter<S>(&self, layer: _EtwLayer<S, OutMode>) -> EtwFilter<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
EtwFilter::<S, OutMode> { layer }
}
#[cfg_attr(docsrs, doc(cfg(feature = "global_filter")))]
#[cfg(any(feature = "global_filter", docsrs))]
pub fn build_global_filter<S>(self) -> Result<EtwLayer<S, OutMode>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
crate::native::Provider<OutMode>: ProviderTraits + EventWriter<OutMode>,
{
self.validate_config()?;
Ok(self.build_layer())
}
#[allow(clippy::type_complexity)]
#[cfg_attr(docsrs, doc(cfg(not(feature = "global_filter"))))]
#[cfg(any(not(feature = "global_filter"), docsrs))]
pub fn build<S>(
self,
) -> Result<Filtered<EtwLayer<S, OutMode>, EtwFilter<S, OutMode>, S>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
crate::native::Provider<OutMode>: ProviderTraits + EventWriter<OutMode>,
{
self.validate_config()?;
let layer = self.build_layer();
let filter = self.build_filter(layer.layer.clone());
Ok(layer.with_filter(filter))
}
#[allow(clippy::type_complexity)]
#[cfg_attr(docsrs, doc(cfg(not(feature = "global_filter"))))]
#[cfg(any(not(feature = "global_filter"), docsrs))]
pub fn build_with_target<S>(
self,
target: &'static str,
) -> Result<Filtered<EtwLayer<S, OutMode>, And<EtwFilter<S, OutMode>, Targets, S>, S>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
crate::native::Provider<OutMode>: ProviderTraits + EventWriter<OutMode>,
{
self.validate_config()?;
let layer = self.build_layer();
let filter = self.build_filter(layer.layer.clone());
let targets = self.build_target_filter(target);
Ok(layer.with_filter(filter.and(targets)))
}
#[doc(hidden)]
pub fn __build_for_test<S>(
self,
) -> Result<EtwLayer<S, OutMode>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
crate::native::Provider<OutMode>: ProviderTraits + EventWriter<OutMode>,
{
Ok(self.build_layer())
}
}