Skip to content

Commit

Permalink
Improve Provider generics (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Robo210 authored Dec 13, 2024
1 parent 62a5bcb commit e350142
Show file tree
Hide file tree
Showing 14 changed files with 731 additions and 918 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ crate-type = ["rlib"]

[features]
global_filter = []
common_schema = []
default = ["common_schema"]

[dependencies]
tracing = {version = "0.1", default-features = false, features = ["std"]}
Expand Down
2 changes: 1 addition & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {

#[cfg(not(feature = "global_filter"))]
let registry = registry.with(LayerBuilder::new("test").build().unwrap());
#[cfg(all(not(feature = "global_filter"), feature = "common_schema"))]
#[cfg(not(feature = "global_filter"))]
let registry = registry.with(
LayerBuilder::new_common_schema_events("test2")
.build_with_target("geneva")
Expand Down
10 changes: 4 additions & 6 deletions src/layer/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ use tracing::Subscriber;
use tracing_subscriber::{layer::Filter, registry::LookupSpan};

use crate::{
native::{EventWriter, ProviderTypes},
native::{OutputMode, ProviderTraits},
statics::get_event_metadata,
};

use super::*;
use super::EtwFilter;

impl<S, Mode> Filter<S> for EtwFilter<S, Mode>
impl<S, OutMode: OutputMode> Filter<S> for EtwFilter<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode: ProviderTypes + 'static,
Mode::Provider: EventWriter<Mode> + 'static,
{
fn callsite_enabled(
&self,
Expand All @@ -25,7 +23,7 @@ where
self.layer.default_keyword
};

if Mode::supports_enable_callback() {
if crate::native::Provider::<OutMode>::supports_enable_callback() {
if self.layer.provider.enabled(metadata.level(), keyword) {
tracing::subscriber::Interest::always()
} else {
Expand Down
9 changes: 4 additions & 5 deletions src/layer/layer_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use tracing_core::{callsite, span};
use tracing_subscriber::{registry::LookupSpan, Layer};

use crate::{
native::{EventWriter, ProviderTypes},
native::EventWriter,
statics::*,
values::{span_values::*, *},
};
Expand All @@ -20,11 +20,10 @@ struct SpanData {
start_time: SystemTime,
}

impl<S, Mode> Layer<S> for EtwLayer<S, Mode>
impl<S, OutMode: OutputMode + 'static> Layer<S> for EtwLayer<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode: ProviderTypes + 'static,
Mode::Provider: EventWriter<Mode> + 'static,
crate::native::Provider<OutMode>: EventWriter<OutMode>,
{
fn on_register_dispatch(&self, _collector: &tracing::Dispatch) {
// Late init when the layer is installed as a subscriber
Expand All @@ -46,7 +45,7 @@ where
self.layer.default_keyword
};

if Mode::supports_enable_callback() {
if crate::native::Provider::<OutMode>::supports_enable_callback() {
if self.layer.provider.enabled(metadata.level(), keyword) {
tracing::subscriber::Interest::always()
} else {
Expand Down
32 changes: 9 additions & 23 deletions src/layer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,17 @@ use tracing_core::callsite;
use tracing_subscriber::registry::LookupSpan;

use crate::{
native::{EventWriter, ProviderTypes},
native::{OutputMode, ProviderTraits},
statics::get_event_metadata,
};

pub(crate) struct _EtwLayer<S, Mode: ProviderTypes>
where
Mode::Provider: crate::native::EventWriter<Mode> + 'static,
{
pub(crate) provider: Pin<Arc<Mode::Provider>>,
pub(crate) struct _EtwLayer<S, OutMode: OutputMode> {
pub(crate) provider: Pin<Arc<crate::native::Provider<OutMode>>>,
pub(crate) default_keyword: u64,
pub(crate) _p: PhantomData<S>,
}

impl<S, Mode: ProviderTypes> Clone for _EtwLayer<S, Mode>
where
Mode::Provider: crate::native::EventWriter<Mode> + 'static,
{
impl<S, OutMode: OutputMode> Clone for _EtwLayer<S, OutMode> {
fn clone(&self) -> Self {
_EtwLayer {
provider: self.provider.clone(),
Expand All @@ -38,28 +32,20 @@ where

// This struct needs to be public as it implements the tracing_subscriber::Layer and tracing_subscriber::Layer::Filter traits.
#[doc(hidden)]
pub struct EtwLayer<S, Mode: ProviderTypes>
where
Mode::Provider: EventWriter<Mode> + 'static,
{
pub(crate) layer: _EtwLayer<S, Mode>,
pub struct EtwLayer<S, OutMode: OutputMode> {
pub(crate) layer: _EtwLayer<S, OutMode>,
}

// This struct needs to be public as it implements the tracing_subscriber::Layer::Filter trait.
#[doc(hidden)]
#[cfg(any(not(feature = "global_filter"), docsrs))]
pub struct EtwFilter<S, Mode: ProviderTypes>
where
Mode::Provider: EventWriter<Mode> + 'static,
{
pub(crate) layer: _EtwLayer<S, Mode>,
pub struct EtwFilter<S, OutMode: OutputMode> {
pub(crate) layer: _EtwLayer<S, OutMode>,
}

impl<S, Mode> _EtwLayer<S, Mode>
impl<S, OutMode: OutputMode> _EtwLayer<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode: ProviderTypes + 'static,
Mode::Provider: EventWriter<Mode> + 'static,
{
fn is_enabled(&self, callsite: &callsite::Identifier, level: &tracing_core::Level) -> bool {
let etw_meta = get_event_metadata(callsite);
Expand Down
116 changes: 41 additions & 75 deletions src/layer_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ 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::{EventWriter, GuidWrapper, ProviderTypes};
use crate::{error::EtwError, native};
use crate::native::{
CommonSchemaOutput, EventWriter, GuidWrapper, NormalOutput, OutputMode, ProviderTraits,
};

/// Builds a [tracing_subscriber::Layer] that will logs events from a single
/// ETW or user_events provider. Use [LayerBuilder::new] to construct a new
Expand All @@ -32,53 +34,46 @@ use crate::{error::EtwError, native};
/// with different provider names/IDs, keywords, or output formats.
/// (Target filters)[tracing_subscriber::filter] can then be used to direct
/// specific events to specific layers.
pub struct LayerBuilder<Mode>
where
Mode: ProviderTypes,
{
provider_name: String,
pub struct LayerBuilder<OutMode: OutputMode> {
provider_name: Box<str>,
provider_id: GuidWrapper,
provider_group: Option<Mode::ProviderGroupType>,
provider_group: Option<crate::native::ProviderGroupType>,
default_keyword: u64,
_m: PhantomData<Mode>,
_o: PhantomData<OutMode>,
}

impl LayerBuilder<native::Provider> {
impl LayerBuilder<NormalOutput> {
#[allow(clippy::new_ret_no_self)]
pub fn new(name: &str) -> LayerBuilder<native::Provider> {
LayerBuilder::<native::Provider> {
provider_name: name.to_owned(),
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,
_m: PhantomData,
_o: PhantomData,
}
}
}

impl LayerBuilder<native::common_schema::Provider> {
impl LayerBuilder<CommonSchemaOutput> {
/// For advanced scenarios.
/// Emit events that follow the Common Schema 4.0 mapping.
/// Recommended only for compatibility with specialized event consumers.
/// Most ETW consumers will not benefit from events in this schema, and
/// may perform worse. Common Schema events are much slower to generate
/// and should not be enabled unless absolutely necessary.
#[cfg(any(feature = "common_schema", docsrs))]
pub fn new_common_schema_events(name: &str) -> LayerBuilder<native::common_schema::Provider> {
LayerBuilder::<native::common_schema::Provider> {
provider_name: name.to_owned(),
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,
_m: PhantomData,
_o: PhantomData,
}
}
}

impl<Mode> LayerBuilder<Mode>
where
Mode: ProviderTypes + 'static,
{
impl<OutMode: OutputMode + 'static> LayerBuilder<OutMode> {
/// For advanced scenarios.
/// Assign a provider ID to the ETW provider rather than use
/// one generated from the provider name.
Expand Down Expand Up @@ -116,56 +111,26 @@ where
/// Set the provider group to join this provider to.
pub fn with_provider_group<G>(mut self, group_id: &G) -> Self
where
for<'a> &'a G: Into<Mode::ProviderGroupType>,
for<'a> &'a G: Into<crate::native::ProviderGroupType>,
{
self.provider_group = Some(group_id.into());
self
}

fn validate_config(&self) -> Result<(), EtwError> {
#[cfg(target_os = "linux")]
{
if self
.provider_name
.contains(|f: char| !f.is_ascii_alphanumeric() && f != '_')
{
// The perf command is very particular about the provider names it accepts.
// The Linux kernel itself cares less, and other event consumers should also presumably not need this check.
return Err(EtwError::InvalidProviderNameCharacters(
self.provider_name.clone(),
));
}

let group_name_len = match &self.provider_group {
None => 0,
Some(ref name) => Mode::get_provider_group(&name).as_ref().len(),
};

if self.provider_name.len() + group_name_len >= 234 {
return Err(EtwError::TooManyCharacters(
self.provider_name.len() + group_name_len,
));
}
}

match &self.provider_group {
None => Ok(()),
Some(value) => Mode::is_valid(value),
}
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);

#[cfg(target_os = "linux")]
match self.provider_group {
None => {}
Some(ref name) => {
targets = targets
.with_target(Mode::get_provider_group(name).as_ref(), LevelFilter::TRACE);
}
}
let mut targets = Targets::new().with_target(&*self.provider_name, LevelFilter::TRACE);

if !target.is_empty() {
targets = targets.with_target(target, LevelFilter::TRACE)
Expand All @@ -174,14 +139,14 @@ where
targets
}

fn build_layer<S>(&self) -> EtwLayer<S, Mode>
fn build_layer<S>(&self) -> EtwLayer<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
crate::native::Provider<OutMode>: EventWriter<OutMode>,
{
EtwLayer::<S, Mode> {
EtwLayer::<S, OutMode> {
layer: _EtwLayer {
provider: Mode::Provider::new(
provider: crate::native::Provider::<OutMode>::new(
&self.provider_name,
&self.provider_id,
&self.provider_group,
Expand All @@ -194,12 +159,11 @@ where
}

#[cfg(any(not(feature = "global_filter"), docsrs))]
fn build_filter<S>(&self, layer: _EtwLayer<S, Mode>) -> EtwFilter<S, Mode>
fn build_filter<S>(&self, layer: _EtwLayer<S, OutMode>) -> EtwFilter<S, OutMode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
{
EtwFilter::<S, Mode> { layer }
EtwFilter::<S, OutMode> { layer }
}

#[cfg_attr(docsrs, doc(cfg(feature = "global_filter")))]
Expand All @@ -217,10 +181,12 @@ where
#[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, Mode>, EtwFilter<S, Mode>, S>, EtwError>
pub fn build<S>(
self,
) -> Result<Filtered<EtwLayer<S, OutMode>, EtwFilter<S, OutMode>, S>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
crate::native::Provider<OutMode>: EventWriter<OutMode>,
{
self.validate_config()?;

Expand All @@ -240,10 +206,10 @@ where
pub fn build_with_target<S>(
self,
target: &'static str,
) -> Result<Filtered<EtwLayer<S, Mode>, And<EtwFilter<S, Mode>, Targets, S>, S>, EtwError>
) -> Result<Filtered<EtwLayer<S, OutMode>, And<EtwFilter<S, OutMode>, Targets, S>, S>, EtwError>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
crate::native::Provider<OutMode>: EventWriter<OutMode>,
{
self.validate_config()?;

Expand Down
Loading

0 comments on commit e350142

Please sign in to comment.