Skip to content

Commit

Permalink
Merge pull request #9 from microsoft/docsrs
Browse files Browse the repository at this point in the history
Docsrs
  • Loading branch information
Robo210 committed Aug 21, 2024
2 parents 4938147 + f573fda commit 3663164
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 33 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ harness = false
[[bench]]
name = "user_events"
harness = false

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
2 changes: 1 addition & 1 deletion benches/etw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn etw_benchmark(c: &mut Criterion) {
}

session
.enable_provider(&provider_id.into(), 0xFF)
.enable_provider(&provider_id.to_u128().into(), 0xFF)
.expect("can't enable provider to session");

// Spans
Expand Down
2 changes: 1 addition & 1 deletion src/_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ where

// This struct needs to be public as it implements the tracing_subscriber::Layer::Filter trait.
#[doc(hidden)]
#[cfg(not(feature = "global_filter"))]
#[cfg(any(not(feature = "global_filter"), docsrs))]
pub struct EtwFilter<S, Mode: ProviderTypes>
where
Mode::Provider: crate::native::EventWriter<Mode> + 'static
Expand Down
95 changes: 65 additions & 30 deletions src/layer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::marker::PhantomData;
use std::time::SystemTime;
#[allow(unused_imports)]
use std::{pin::Pin, sync::Arc};

#[allow(unused_imports)] // Many imports are used exclusively by feature-gated code
Expand All @@ -11,12 +12,29 @@ use tracing_subscriber::filter::{combinator::And, FilterExt, Filtered, Targets};
use tracing_subscriber::layer::Filter;
use tracing_subscriber::{registry::LookupSpan, Layer};

use crate::_details::{EtwFilter, EtwLayer};
#[cfg(any(not(feature = "global_filter"), docsrs))]
use crate::_details::EtwFilter;
use crate::_details::EtwLayer;
use crate::native::{EventWriter, GuidWrapper, ProviderTypes};
use crate::native;
use crate::values::*;
use crate::statics::*;

/// Builds a [tracing_subscriber::Layer] that will logs events from a single
/// ETW or user_events provider. Use [LayerBuilder::new] to construct a new
/// builder for the given provider name. Use the `with_*` methods to set
/// additional properties for the provider, such as the keyword to use
/// for events (default: 1) or a specific provider GUID (default: a hash of
/// the provider name).
///
/// Use [LayerBuilder::new_common_schema_events] to create a layer that
/// will log events in the Common Schema 4.0 mapping. Only use this if
/// you know that you need events in this format.
///
/// Multiple `tracing_etw` layers can be created at the same time,
/// 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
Expand Down Expand Up @@ -48,7 +66,7 @@ impl LayerBuilder<native::common_schema::Provider> {
/// 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(feature = "common_schema")]
#[cfg(any(feature = "common_schema", docsrs))]
pub fn new_common_schema_events(
name: &str,
) -> LayerBuilder<native::common_schema::Provider> {
Expand Down Expand Up @@ -80,10 +98,21 @@ where
/// Get the current provider ID that will be used for the ETW provider.
/// This is a convenience function to help with tools that do not implement
/// the standard provider name to ID algorithm.
pub fn get_provider_id(&self) -> &GuidWrapper {
&self.provider_id
pub fn get_provider_id(&self) -> GuidWrapper {
self.provider_id.clone()
}


/// Set the keyword used for events that do not explicitly set a keyword.
///
/// Events logged with the [crate::etw_event!] macro specify a keyword for the event.
/// Events and spans logged with the [tracing::event!], [tracing::span!],
/// or other similar `tracing` macros will use the default keyword.
///
/// If this method is not called, the default keyword will be `1`.
///
/// Keyword value `0` is special in ETW (but not user_events), and should
/// not be used.
pub fn with_default_keyword(mut self, kw: u64) -> Self {
self.default_keyword = kw;
self
Expand Down Expand Up @@ -116,7 +145,7 @@ where
}
}

#[cfg(not(feature = "global_filter"))]
#[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);

Expand Down Expand Up @@ -166,41 +195,45 @@ where
}
}

#[allow(clippy::type_complexity)]
#[cfg(not(feature = "global_filter"))]
pub fn build_with_target<S>(
self,
target: &'static str,
) -> Filtered<EtwLayer<S, Mode>, And<EtwFilter<S, Mode>, Targets, S>, S>
#[cfg_attr(docsrs, doc(cfg(feature = "global_filter")))]
#[cfg(any(feature = "global_filter", docsrs))]
pub fn build<S>(self) -> EtwLayer<S, Mode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
{
self.validate_config();

let layer = self.build_layer();

let filter = self.build_filter(layer.provider.clone());

let targets = self.build_target_filter(target);

layer.with_filter(filter.and(targets))
self.build_layer()
}

#[cfg(feature = "global_filter")]
pub fn build<S>(self) -> EtwLayer<S, Mode::Provider>
#[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) -> Filtered<EtwLayer<S, Mode>, EtwFilter<S, Mode>, S>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter + 'static,
Mode::Provider: EventWriter<Mode> + 'static,
{
self.validate_config();

self.build_layer()
let layer = self.build_layer();

let filter = self.build_filter(layer.provider.clone());

layer.with_filter(filter)
}

/// Constructs the configured layer with a target [tracing_subscriber::filter] applied.
/// This can be used to target specific events to specific layers, and in effect allow
/// specific events to be logged only from specific ETW/user_event providers.
#[allow(clippy::type_complexity)]
#[cfg(not(feature = "global_filter"))]
pub fn build<S>(self) -> Filtered<EtwLayer<S, Mode>, EtwFilter<S, Mode>, S>
#[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,
) -> Filtered<EtwLayer<S, Mode>, And<EtwFilter<S, Mode>, Targets, S>, S>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Mode::Provider: EventWriter<Mode> + 'static,
Expand All @@ -211,11 +244,13 @@ where

let filter = self.build_filter(layer.provider.clone());

layer.with_filter(filter)
let targets = self.build_target_filter(target);

layer.with_filter(filter.and(targets))
}
}

#[cfg(not(feature = "global_filter"))]
#[cfg(any(not(feature = "global_filter"), docsrs))]
impl<S, Mode> Filter<S> for EtwFilter<S, Mode>
where
S: Subscriber + for<'a> LookupSpan<'a>,
Expand Down Expand Up @@ -300,7 +335,7 @@ where
// Late init when the layer is attached to a subscriber
}

#[cfg(feature = "global_filter")]
#[cfg(any(feature = "global_filter", docsrs))]
fn register_callsite(
&self,
metadata: &'static tracing::Metadata<'static>,
Expand All @@ -312,7 +347,7 @@ where
self.default_keyword
};

if P::supports_enable_callback() {
if Mode::supports_enable_callback() {
if self.provider.enabled(metadata.level(), keyword) {
tracing::subscriber::Interest::always()
} else {
Expand All @@ -325,7 +360,7 @@ where
}
}

#[cfg(feature = "global_filter")]
#[cfg(any(feature = "global_filter", docsrs))]
fn enabled(
&self,
metadata: &tracing::Metadata<'_>,
Expand All @@ -341,7 +376,7 @@ where
self.provider.enabled(metadata.level(), keyword)
}

#[cfg(feature = "global_filter")]
#[cfg(any(feature = "global_filter", docsrs))]
fn event_enabled(
&self,
event: &tracing::Event<'_>,
Expand Down
6 changes: 5 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,18 @@
//! Keywords are a fundamental part of efficient event filtering in ETW,
//! and naming events make them easier to understand in tools like WPA.
//! It is highly recommended that every event have a non-zero keyword;
//! the [default_keyword] function can set the default keyword assigned
//! the [LayerBuilder::with_default_keyword] function can set the default keyword assigned
//! to every event logged through the `tracing` macros (e.g. `event!`).
//!
//! This extra information is stored as static metadata in the final
//! compiled binary, and relies on linker support to work properly.
//! It has been tested with Microsoft's, GCC's, and LLVM's linker.
//!

// only enables the `doc_cfg` feature when
// the `docsrs` configuration attribute is defined
#![cfg_attr(docsrs, feature(doc_cfg))]

mod layer;
// Module that abstracts the native ETW and Linux user_events APIs, depending on the target platform.
// Consumers of the crate should not need to use this module directly.
Expand Down
11 changes: 11 additions & 0 deletions src/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub(crate) use tracelogging_dynamic::Guid as native_guid;
pub(crate) use eventheader::Guid as native_guid;

#[doc(hidden)]
#[derive(Copy, Clone)]
pub struct GuidWrapper(u128);

impl From<&native_guid> for GuidWrapper {
Expand Down Expand Up @@ -68,10 +69,20 @@ impl From<&GuidWrapper> for u128 {
}
}

impl AsRef<u128> for GuidWrapper {
fn as_ref(&self) -> &u128 {
&self.0
}
}

impl GuidWrapper {
pub fn from_name(name: &str) -> Self {
Self(native_guid::from_name(name).to_u128())
}

pub fn to_u128(&self) -> u128 {
self.0
}
}

#[doc(hidden)]
Expand Down

0 comments on commit 3663164

Please sign in to comment.