From 1245a65fc84b71b50ae7b23345feb2dd178ee29f Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 27 Aug 2021 10:51:23 -0700 Subject: [PATCH 1/3] docs: fix a bunch of RustDoc warnings/errors This branch fixes some minor RustDoc issues. In particular: - The `broken_intra_doc_links` lint was renamed to `rustdoc::broken_intra_doc_links`. This generates a warning, since the old name was deprecated. - `ignore` code blocks are specifically for _Rust_ code that should not be compiled, not for other text blocks. We were using `ignore` on JSON blocks, which generates a warning. - A bunch of links in `tracing-subscriber`'s RustDocs were broken. This fixes that. --- tracing-appender/src/lib.rs | 2 +- tracing-attributes/src/lib.rs | 2 +- tracing-core/src/lib.rs | 2 +- tracing-core/src/metadata.rs | 2 +- tracing-error/src/lib.rs | 2 +- tracing-flame/src/lib.rs | 2 +- tracing-futures/src/lib.rs | 2 +- tracing-journald/src/lib.rs | 2 +- tracing-log/src/lib.rs | 2 +- tracing-macros/src/lib.rs | 2 +- tracing-opentelemetry/src/lib.rs | 2 +- tracing-serde/src/lib.rs | 2 +- .../src/filter/layer_filters.rs | 422 ++++++++++++++++++ tracing-subscriber/src/fmt/format/json.rs | 4 +- tracing-subscriber/src/fmt/writer.rs | 50 ++- tracing-subscriber/src/lib.rs | 2 +- tracing-tower/src/lib.rs | 2 +- tracing/src/lib.rs | 2 +- 18 files changed, 479 insertions(+), 27 deletions(-) create mode 100644 tracing-subscriber/src/filter/layer_filters.rs diff --git a/tracing-appender/src/lib.rs b/tracing-appender/src/lib.rs index 2b822f709d..2c9c86a6fd 100644 --- a/tracing-appender/src/lib.rs +++ b/tracing-appender/src/lib.rs @@ -127,7 +127,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-attributes/src/lib.rs b/tracing-attributes/src/lib.rs index 09b42e840e..3e095ca03f 100644 --- a/tracing-attributes/src/lib.rs +++ b/tracing-attributes/src/lib.rs @@ -57,7 +57,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-core/src/lib.rs b/tracing-core/src/lib.rs index 9b8ad0a1dc..e272164c04 100644 --- a/tracing-core/src/lib.rs +++ b/tracing-core/src/lib.rs @@ -91,7 +91,7 @@ issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-core/src/metadata.rs b/tracing-core/src/metadata.rs index 742c6fe6b8..5b9b5584f7 100644 --- a/tracing-core/src/metadata.rs +++ b/tracing-core/src/metadata.rs @@ -217,7 +217,7 @@ pub struct Kind(KindInner); /// [`TRACE`]: Level::TRACE /// [`Subscriber::enabled`]: crate::subscriber::Subscriber::enabled /// [`Subscriber::max_level_hint`]: crate::subscriber::Subscriber::max_level_hint -/// [subscriber]: crate::subscriber::Subscriber +/// [`Subscriber`]: crate::subscriber::Subscriber /// [envfilter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct Level(LevelInner); diff --git a/tracing-error/src/lib.rs b/tracing-error/src/lib.rs index 4a0df115d7..02851828a7 100644 --- a/tracing-error/src/lib.rs +++ b/tracing-error/src/lib.rs @@ -185,7 +185,7 @@ //! supported compiler version is not considered a semver breaking change as //! long as doing so complies with this policy. //! -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![doc(html_root_url = "https://docs.rs/tracing-error/0.1.2")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", diff --git a/tracing-flame/src/lib.rs b/tracing-flame/src/lib.rs index 05fa1a4c9e..c90a80fe1f 100644 --- a/tracing-flame/src/lib.rs +++ b/tracing-flame/src/lib.rs @@ -113,7 +113,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-futures/src/lib.rs b/tracing-futures/src/lib.rs index 7ac986aa02..574528ab45 100644 --- a/tracing-futures/src/lib.rs +++ b/tracing-futures/src/lib.rs @@ -101,7 +101,7 @@ while_true )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #[cfg(feature = "std-future")] use pin_project_lite::pin_project; diff --git a/tracing-journald/src/lib.rs b/tracing-journald/src/lib.rs index 395b067dce..530e68ddf9 100644 --- a/tracing-journald/src/lib.rs +++ b/tracing-journald/src/lib.rs @@ -36,7 +36,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #[cfg(unix)] use std::os::unix::net::UnixDatagram; use std::{fmt, io, io::Write}; diff --git a/tracing-log/src/lib.rs b/tracing-log/src/lib.rs index a814431765..3be108c10e 100644 --- a/tracing-log/src/lib.rs +++ b/tracing-log/src/lib.rs @@ -110,7 +110,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-macros/src/lib.rs b/tracing-macros/src/lib.rs index f554cffd1b..5286e8708b 100644 --- a/tracing-macros/src/lib.rs +++ b/tracing-macros/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #[doc(hidden)] pub use tracing; diff --git a/tracing-opentelemetry/src/lib.rs b/tracing-opentelemetry/src/lib.rs index 560b5dd21e..938240e2ee 100644 --- a/tracing-opentelemetry/src/lib.rs +++ b/tracing-opentelemetry/src/lib.rs @@ -97,7 +97,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] /// Implementation of the trace::Layer as a source of OpenTelemetry data. mod layer; diff --git a/tracing-serde/src/lib.rs b/tracing-serde/src/lib.rs index b0901610b0..94b486fbbc 100644 --- a/tracing-serde/src/lib.rs +++ b/tracing-serde/src/lib.rs @@ -130,7 +130,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, // missing_docs, // TODO: add documentation diff --git a/tracing-subscriber/src/filter/layer_filters.rs b/tracing-subscriber/src/filter/layer_filters.rs new file mode 100644 index 0000000000..c42b36bbc5 --- /dev/null +++ b/tracing-subscriber/src/filter/layer_filters.rs @@ -0,0 +1,422 @@ +use super::LevelFilter; +use crate::{ + layer::{Context, Layer}, + registry, +}; +use std::{any::type_name, cell::Cell, fmt, marker::PhantomData, thread_local}; +use tracing_core::{ + span, + subscriber::{Interest, Subscriber}, + Event, Metadata, +}; + +/// A filter that determines whether a span or event is enabled. +pub trait Filter { + fn enabled(&self, meta: &Metadata<'_>, cx: &Context<'_, S>) -> bool; + + fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { + let _ = meta; + Interest::sometimes() + } + + fn max_level_hint(&self) -> Option { + None + } +} + +#[derive(Debug, Clone)] +pub struct Filtered { + filter: F, + layer: L, + id: FilterId, + _s: PhantomData, +} + +pub struct FilterFn< + S, + F = fn(&Metadata<'_>, &Context<'_, S>) -> bool, + R = fn(&'static Metadata<'static>) -> Interest, +> { + enabled: F, + register_callsite: Option, + max_level_hint: Option, + _s: PhantomData, +} + +#[derive(Copy, Clone, Debug)] +pub struct FilterId(u8); + +#[derive(Default, Copy, Clone)] +pub(crate) struct FilterMap { + bits: u64, +} + +thread_local! { + /// The current state of `enabled` calls to per-layer filters on this + /// thread. + /// + /// When `Filtered::enabled` is called, the filter will set the bit + /// corresponding to its ID if it will disable the event/span being + /// filtered. When the event or span is recorded, the per-layer filter will + /// check its bit to determine if it disabled that event or span, and skip + /// forwarding the event or span to the inner layer if the bit is set. Once + /// a span or event has been skipped by a per-layer filter, it unsets its + /// bit, so that the `FilterMap` has been cleared for the next set of + /// `enabled` calls. + /// + /// This is also read by the `Registry`, for two reasons: + /// + /// 1. When filtering a span, the registry must store the `FilterMap` + /// generated by `Filtered::enabled` calls for that span as part of the + /// span's per-span data. This allows `Filtered` layers to determine + /// whether they previously disabled a given span, and avoid showing it + /// to the wrapped layer if it was disabled. + /// + /// This is the mechanism that allows `Filtered` layers to also filter + /// out the spans they disable from span traversals (such as iterating + /// over parents, etc). + /// 2. If all the bits are set, then every per-layer filter has decided it + /// doesn't want to enable that span or event. In that case, the + /// `Registry`'s `enabled` method will return `false`, so that we can + /// skip recording it entirely. + pub(crate) static FILTERING: Cell = Cell::new(FilterMap::default()); + pub(crate) static INTERESTING: Cell = Cell::new(Interest::never()); +} + +// === impl Filter === + +impl Filter for LevelFilter { + fn enabled(&self, meta: &Metadata<'_>, _: &Context<'_, S>) -> bool { + meta.level() <= self + } + + fn callsite_enabled(&self, meta: &'static Metadata<'static>) -> Interest { + if meta.level() <= self { + Interest::always() + } else { + Interest::never() + } + } + + fn max_level_hint(&self) -> Option { + Some(*self) + } +} + +// === impl Filtered === + +impl Filtered { + pub fn new(layer: L, filter: F) -> Self { + Self { + layer, + filter, + id: FilterId(255), + _s: PhantomData, + } + } + + fn did_enable(&self, f: impl FnOnce()) { + FILTERING.with(|filtering| { + if filtering.get().is_enabled(self.id) { + f(); + + filtering.set(filtering.get().set(self.id, true)); + } + }) + } +} + +impl Layer for Filtered +where + S: Subscriber + for<'span> registry::LookupSpan<'span> + 'static, + F: Filter + 'static, + L: Layer, +{ + fn on_register(&mut self, subscriber: &mut S) { + self.id = subscriber.register_filter(); + self.layer.on_register(subscriber); + } + + // TODO(eliza): can we figure out a nice way to make the `Filtered` layer + // not call `is_enabled_for` in hooks that the inner layer doesn't actually + // have real implementations of? probably not... + // + // it would be cool if there was some wild rust reflection way of checking + // if a trait impl has the default impl of a trait method or not, but that's + // almsot certainly impossible...right? + + fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest { + // self.filter.callsite_enabled(metadata) + Interest::sometimes() + } + + fn enabled(&self, metadata: &Metadata<'_>, cx: Context<'_, S>) -> bool { + let enabled = self.filter.enabled(metadata, &cx.with_filter(self.id)); + FILTERING.with(|filtering| filtering.set(filtering.get().set(self.id, enabled))); + true // keep filtering + } + + fn new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) { + self.did_enable(|| { + self.layer.new_span(attrs, id, cx.with_filter(self.id)); + }) + } + + #[doc(hidden)] + fn max_level_hint(&self) -> Option { + self.filter.max_level_hint() + } + + fn on_record(&self, span: &span::Id, values: &span::Record<'_>, cx: Context<'_, S>) { + if let Some(cx) = cx.if_enabled_for(span, self.id) { + self.layer.on_record(span, values, cx) + } + } + + fn on_follows_from(&self, span: &span::Id, follows: &span::Id, cx: Context<'_, S>) { + // only call `on_follows_from` if both spans are enabled by us + if cx.is_enabled_for(span, self.id) && cx.is_enabled_for(follows, self.id) { + self.layer + .on_follows_from(span, follows, cx.with_filter(self.id)) + } + } + + fn on_event(&self, event: &Event<'_>, cx: Context<'_, S>) { + self.did_enable(|| { + self.layer.on_event(event, cx.with_filter(self.id)); + }) + } + + fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) { + if let Some(cx) = cx.if_enabled_for(id, self.id) { + self.layer.on_enter(id, cx) + } + } + + fn on_exit(&self, id: &span::Id, cx: Context<'_, S>) { + if let Some(cx) = cx.if_enabled_for(id, self.id) { + self.layer.on_exit(id, cx) + } + } + + fn on_close(&self, id: span::Id, cx: Context<'_, S>) { + if let Some(cx) = cx.if_enabled_for(&id, self.id) { + self.layer.on_close(id, cx) + } + } + + // XXX(eliza): the existence of this method still makes me sad... + fn on_id_change(&self, old: &span::Id, new: &span::Id, cx: Context<'_, S>) { + if let Some(cx) = cx.if_enabled_for(old, self.id) { + self.layer.on_id_change(old, new, cx) + } + } +} + +// === impl FilterFn === + +pub fn filter_fn(f: F) -> FilterFn +where + F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, +{ + FilterFn::new(f) +} + +impl FilterFn +where + F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, +{ + pub fn new(enabled: F) -> Self { + Self { + enabled, + register_callsite: None, + max_level_hint: None, + _s: PhantomData, + } + } +} + +impl FilterFn +where + F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, +{ + pub fn with_max_level_hint(self, max_level_hint: LevelFilter) -> Self { + Self { + max_level_hint: Some(max_level_hint), + ..self + } + } + + pub fn with_callsite_filter(self, callsite_enabled: R2) -> FilterFn + where + R2: Fn(&'static Metadata<'static>) -> Interest, + { + let register_callsite = Some(callsite_enabled); + let FilterFn { + enabled, + max_level_hint, + _s, + .. + } = self; + FilterFn { + enabled, + register_callsite, + max_level_hint, + _s, + } + } + + fn is_below_max_level(&self, metadata: &Metadata<'_>) -> bool { + self.max_level_hint + .as_ref() + .map(|hint| metadata.level() <= hint) + .unwrap_or(true) + } + + fn default_callsite_enabled(&self, metadata: &Metadata<'_>) -> Interest { + if (self.enabled)(metadata, &Context::none()) { + Interest::always() + } else { + Interest::never() + } + } +} + +impl Filter for FilterFn +where + F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, + R: Fn(&'static Metadata<'static>) -> Interest, +{ + fn enabled(&self, metadata: &Metadata<'_>, cx: &Context<'_, S>) -> bool { + let enabled = (self.enabled)(metadata, cx); + debug_assert!( + !enabled || self.is_below_max_level(metadata), + "FilterFn<{}> claimed it would only enable {:?} and below, \ + but it enabled metadata with the {:?} level\nmetadata={:#?}", + type_name::(), + self.max_level_hint.unwrap(), + metadata.level(), + metadata, + ); + + enabled + } + + fn callsite_enabled(&self, metadata: &'static Metadata<'static>) -> Interest { + let interest = self + .register_callsite + .as_ref() + .map(|callsite_enabled| callsite_enabled(metadata)) + .unwrap_or_else(|| self.default_callsite_enabled(metadata)); + debug_assert!( + interest.is_never() || self.is_below_max_level(metadata), + "FilterFn<{}, {}> claimed it was only interested in {:?} and below, \ + but it enabled metadata with the {:?} level\nmetadata={:#?}", + type_name::(), + type_name::(), + self.max_level_hint.unwrap(), + metadata.level(), + metadata, + ); + + interest + } + + fn max_level_hint(&self) -> Option { + self.max_level_hint + } +} + +impl fmt::Debug for FilterFn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut s = f.debug_struct("FilterFn"); + s.field("enabled", &format_args!("{}", type_name::())); + if self.register_callsite.is_some() { + s.field( + "register_callsite", + &format_args!("Some({})", type_name::()), + ); + } else { + s.field("register_callsite", &format_args!("None")); + } + + s.field("max_level_hint", &self.max_level_hint) + .field("subscriber_type", &format_args!("{}", type_name::())) + .finish() + } +} + +impl Clone for FilterFn +where + F: Clone, + R: Clone, +{ + fn clone(&self) -> Self { + Self { + enabled: self.enabled.clone(), + register_callsite: self.register_callsite.clone(), + max_level_hint: self.max_level_hint, + _s: PhantomData, + } + } +} + +impl From for FilterFn +where + F: Fn(&Metadata<'_>, &Context<'_, S>) -> bool, +{ + fn from(f: F) -> Self { + Self::new(f) + } +} + +// === impl FilterId === + +impl FilterId { + pub(crate) fn new(id: u8) -> Self { + assert!(id < 64, "filter IDs may not be greater than 64"); + Self(id) + } +} + +// === impl FilterMap === + +impl FilterMap { + pub(crate) fn set(self, FilterId(idx): FilterId, enabled: bool) -> Self { + debug_assert!(idx < 64 || idx == 255); + if idx >= 64 { + return self; + } + + if enabled { + Self { + bits: self.bits & !(1 << idx), + } + } else { + Self { + bits: self.bits | (1 << idx), + } + } + } + + pub(crate) fn is_enabled(self, FilterId(idx): FilterId) -> bool { + debug_assert!(idx < 64 || idx == 255); + if idx >= 64 { + return false; + } + + self.bits & (1 << idx) == 0 + } + + pub(crate) fn any_enabled(self) -> bool { + self.bits != u64::MAX + } +} + +impl fmt::Debug for FilterMap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("FilterMap") + .field("bits", &format_args!("{:#b}", self.bits)) + .finish() + } +} diff --git a/tracing-subscriber/src/fmt/format/json.rs b/tracing-subscriber/src/fmt/format/json.rs index 2c86504f00..8e06db111b 100644 --- a/tracing-subscriber/src/fmt/format/json.rs +++ b/tracing-subscriber/src/fmt/format/json.rs @@ -21,13 +21,13 @@ use tracing_serde::AsSerde; #[cfg(feature = "tracing-log")] use tracing_log::NormalizeEvent; -/// Marker for `Format` that indicates that the verbose json log format should be used. +/// Marker for `Format` that indicates that the verbose JSON log format should be used. /// /// The full format includes fields from all entered spans. /// /// # Example Output /// -/// ```ignore,json +/// ```json /// { /// "timestamp":"Feb 20 11:28:15.096", /// "level":"INFO", diff --git a/tracing-subscriber/src/fmt/writer.rs b/tracing-subscriber/src/fmt/writer.rs index ba04ba817d..23dafaf4d7 100644 --- a/tracing-subscriber/src/fmt/writer.rs +++ b/tracing-subscriber/src/fmt/writer.rs @@ -10,11 +10,12 @@ use tracing_core::Metadata; /// A type that can create [`io::Write`] instances. /// -/// `MakeWriter` is used by [`fmt::Subscriber`] or [`fmt::Layer`] to print formatted text representations of -/// [`Event`]s. +/// `MakeWriter` is used by [`fmt::Subscriber`] or [`fmt::Layer`] to print +/// formatted text representations of [`Event`]s. /// -/// This trait is already implemented for function pointers and immutably-borrowing closures that -/// return an instance of [`io::Write`], such as [`io::stdout`] and [`io::stderr`]. +/// This trait is already implemented for function pointers and +/// immutably-borrowing closures that return an instance of [`io::Write`], such +/// as [`io::stdout`] and [`io::stderr`]. /// /// The [`MakeWriter::make_writer_for`] method takes [`Metadata`] describing a /// span or event and returns a writer. `MakeWriter`s can optionally provide @@ -75,8 +76,8 @@ use tracing_core::Metadata; /// ``` /// /// [`io::Write`]: std::io::Write -/// [`fmt::Collector`]: super::super::fmt::Collector -/// [`fmt::Subscriber`]: super::super::fmt::Subscriber +/// [`fmt::Layer`]: crate::fmt::Layer +/// [`fmt::Subscriber`]: crate::fmt::Subscriber /// [`Event`]: tracing_core::event::Event /// [`io::stdout`]: std::io::stdout() /// [`io::stderr`]: std::io::stderr() @@ -412,7 +413,32 @@ pub trait MakeWriterExt: MakeWriter { /// ``` /// /// `and` can be used in conjunction with filtering combinators. For - /// example, if we want to write to a number of outputs depending on + /// example, if we want to write to a number of outputs depending on the + /// level of an event, we could write: + /// + /// ``` + /// use tracing::Level; + /// # use tracing_subscriber::fmt::writer::MakeWriterExt; + /// use std::{sync::Arc, fs::File}; + /// # // don't actually create the file when running the tests. + /// # fn docs() -> std::io::Result<()> { + /// let debug_log = Arc::new(File::create("debug.log")?); + /// + /// // Write everything to the debug log. + /// let mk_writer = debug_log + /// // Write the `ERROR` and `WARN` levels to stderr. + /// .and(std::io::stderr.with_max_level(Level::WARN)) + /// // Write `INFO` to `stdout`. + /// .and(std::io::stdout + /// .with_max_level(Level::INFO) + /// .with_min_level(Level::INFO) + /// ); + /// + /// tracing_subscriber::fmt().with_writer(mk_writer).init(); + /// # Ok(()) } + /// ``` + /// + /// [writers]: std::io::Write fn and(self, other: B) -> Tee where Self: Sized, @@ -441,6 +467,8 @@ pub trait MakeWriterExt: MakeWriter { /// /// tracing_subscriber::fmt().with_writer(mk_writer).init(); /// ``` + /// + /// [`make_writer`]: MakeWriter::make_writer fn or_else(self, other: B) -> OrElse where Self: MakeWriter> + Sized, @@ -530,7 +558,7 @@ pub type OptionalWriter = EitherWriter; /// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans /// and events with metadata at or below a specified verbosity [`Level`]. /// -/// This is returned by the [`MakeWriterExt::with_max_level] method. See the +/// This is returned by the [`MakeWriterExt::with_max_level`] method. See the /// method documentation for details. /// /// [writer]: std::io::Write @@ -544,7 +572,7 @@ pub struct WithMaxLevel { /// A [`MakeWriter`] combinator that only returns an enabled [writer] for spans /// and events with metadata at or above a specified verbosity [`Level`]. /// -/// This is returned by the [`MakeWriterExt::with_min_level] method. See the +/// This is returned by the [`MakeWriterExt::with_min_level`] method. See the /// method documentation for details. /// /// [writer]: std::io::Write @@ -556,7 +584,7 @@ pub struct WithMinLevel { } /// A [`MakeWriter`] combinator that wraps a [`MakeWriter`] with a predicate for -/// span and event [`Metadata`], so that the [`MakeWriterExt::make_writer_for`] +/// span and event [`Metadata`], so that the [`MakeWriter::make_writer_for`] /// method returns [`OptionalWriter::some`] when the predicate returns `true`, /// and [`OptionalWriter::none`] when the predicate returns `false`. /// @@ -901,6 +929,8 @@ impl Tee { /// outputs. /// /// See the documentation for [`MakeWriterExt::and`] for details. + /// + /// [writers]: std::io::Write pub fn new(a: A, b: B) -> Self { Self { a, b } } diff --git a/tracing-subscriber/src/lib.rs b/tracing-subscriber/src/lib.rs index e35beaedf8..6cc877bddb 100644 --- a/tracing-subscriber/src/lib.rs +++ b/tracing-subscriber/src/lib.rs @@ -72,7 +72,7 @@ html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" )] -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![warn( missing_debug_implementations, missing_docs, diff --git a/tracing-tower/src/lib.rs b/tracing-tower/src/lib.rs index d3975fceb0..633dbb599b 100644 --- a/tracing-tower/src/lib.rs +++ b/tracing-tower/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" diff --git a/tracing/src/lib.rs b/tracing/src/lib.rs index 4fbe76a83c..94e60c4ca5 100644 --- a/tracing/src/lib.rs +++ b/tracing/src/lib.rs @@ -853,7 +853,7 @@ //! [instrument]: https://docs.rs/tracing-attributes/latest/tracing_attributes/attr.instrument.html //! [flags]: #crate-feature-flags #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(docsrs, feature(doc_cfg), deny(broken_intra_doc_links))] +#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![doc(html_root_url = "https://docs.rs/tracing/0.1.26")] #![doc( html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", From 42888d2a8ca4fdad0f04c58e4a723d1ff397d6ec Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 27 Aug 2021 10:58:48 -0700 Subject: [PATCH 2/3] chore: check docs build without warnings on CI Signed-off-by: Eliza Weisman --- .github/workflows/CI.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2aa3655a65..f4081a9e33 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -231,6 +231,7 @@ jobs: run: (cd tracing-core && cargo test --no-default-features) - name: "Test tracing no-std support" run: (cd tracing && cargo test --no-default-features) + style: # Check style. needs: check @@ -249,6 +250,27 @@ jobs: command: fmt args: --all -- --check + check-docs: + # Check docs compile. + name "Check RustDoc" + needs: check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustdoc + profile: minimal + override: true + - name: rustdoc check + uses: actions-rs/cargo@v1 + with: + command: doc + args: --workspace --all-features + env: + RUSTDOCFLAGS: "--cfg docsrs -D warnings" + warnings: # Check for any warnings. This is informational and thus is allowed to fail. runs-on: ubuntu-latest From 189be2e84b5b1a537f59efd4656820c788ff1f18 Mon Sep 17 00:00:00 2001 From: Eliza Weisman Date: Fri, 27 Aug 2021 11:02:36 -0700 Subject: [PATCH 3/3] actually just make Netlify do that Signed-off-by: Eliza Weisman --- .github/workflows/CI.yml | 21 --------------------- netlify.toml | 2 +- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f4081a9e33..a6aee16db4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -250,27 +250,6 @@ jobs: command: fmt args: --all -- --check - check-docs: - # Check docs compile. - name "Check RustDoc" - needs: check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@main - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - components: rustdoc - profile: minimal - override: true - - name: rustdoc check - uses: actions-rs/cargo@v1 - with: - command: doc - args: --workspace --all-features - env: - RUSTDOCFLAGS: "--cfg docsrs -D warnings" - warnings: # Check for any warnings. This is informational and thus is allowed to fail. runs-on: ubuntu-latest diff --git a/netlify.toml b/netlify.toml index 10a933adbd..baf318735f 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,6 +1,6 @@ [build] command = "rustup install nightly --profile minimal && cargo doc --no-deps && cp -r target/doc _netlify_out" - environment = { RUSTDOCFLAGS= "--cfg docsrs" } + environment = { RUSTDOCFLAGS= "--cfg docsrs -D warnings" } publish = "_netlify_out" [[redirects]]