Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ uv-git-types = { path = "crates/uv-git-types" }
uv-globfilter = { path = "crates/uv-globfilter" }
uv-install-wheel = { path = "crates/uv-install-wheel", default-features = false }
uv-installer = { path = "crates/uv-installer" }
uv-logging = { path = "crates/uv-logging" }
uv-macros = { path = "crates/uv-macros" }
uv-metadata = { path = "crates/uv-metadata" }
uv-normalize = { path = "crates/uv-normalize" }
Expand Down Expand Up @@ -180,7 +181,7 @@ toml = { version = "0.9.2", features = ["fast_hash"] }
toml_edit = { version = "0.23.2", features = ["serde"] }
tracing = { version = "0.1.40" }
tracing-durations-export = { version = "0.3.0", features = ["plot"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "registry"] }
tracing-subscriber = { version = "0.3.18" } # Default feature set for uv_build, uv activates extra features
tracing-test = { version = "0.2.5" }
tracing-tree = { version = "0.4.0" }
unicode-width = { version = "0.2.0" }
Expand Down
3 changes: 3 additions & 0 deletions crates/uv-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ license = { workspace = true }

[dependencies]
uv-build-backend = { workspace = true }
uv-logging = { workspace = true }
uv-version = { workspace = true }

anstream = { workspace = true }
anyhow = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }

[lints]
workspace = true
24 changes: 23 additions & 1 deletion crates/uv-build/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
use anyhow::{Context, Result, bail};
use std::env;
use std::io::Write;
use std::path::PathBuf;

use anyhow::{Context, Result, bail};
use tracing_subscriber::filter::LevelFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, Layer};

use uv_logging::UvFormat;

/// Entrypoint for the `uv-build` Python package.
fn main() -> Result<()> {
// Support configuring the log level with `RUST_LOG` (shows only the error level by default) and
// color.
//
// This configuration is a simplified version of the uv logging configuration. When using
// uv_build through uv proper, the uv logging configuration applies.
let filter = EnvFilter::builder()
.with_default_directive(LevelFilter::OFF.into())
.from_env()
.context("Invalid RUST_LOG directives")?;
let stderr_layer = tracing_subscriber::fmt::layer()
.event_format(UvFormat::default())
.with_writer(std::sync::Mutex::new(anstream::stderr()))
.with_filter(filter);
tracing_subscriber::registry().with(stderr_layer).init();

// Handrolled to avoid the large clap dependency
let mut args = env::args_os();
// Skip the name of the binary
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ tokio = { workspace = true }
tokio-util = { workspace = true }
tracing = { workspace = true }
tracing-durations-export = { workspace = true, features = ["plot"] }
tracing-subscriber = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
uv-performance-memory-allocator = { path = "../uv-performance-memory-allocator", optional = true }
walkdir = { workspace = true }

Expand Down
22 changes: 22 additions & 0 deletions crates/uv-logging/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "uv-logging"
version = "0.0.1"
edition = { workspace = true }
rust-version = { workspace = true }
homepage = { workspace = true }
documentation = { workspace = true }
repository = { workspace = true }
authors = { workspace = true }
license = { workspace = true }

[lib]
doctest = false

[lints]
workspace = true

[dependencies]
jiff = { workspace = true }
owo-colors = { workspace = true }
tracing-subscriber = { workspace = true }
tracing = { workspace = true }
95 changes: 95 additions & 0 deletions crates/uv-logging/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::fmt;

use jiff::Timestamp;
use owo_colors::OwoColorize;
use tracing::{Event, Subscriber};
use tracing_subscriber::fmt::format::Writer;
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
use tracing_subscriber::registry::LookupSpan;

/// The style of a uv logging line.
pub struct UvFormat {
pub display_timestamp: bool,
pub display_level: bool,
pub show_spans: bool,
}

impl Default for UvFormat {
/// Regardless of the tracing level, show messages without any adornment.
fn default() -> Self {
Self {
display_timestamp: false,
display_level: true,
show_spans: false,
}
}
}

/// See <https://docs.rs/tracing-subscriber/0.3.18/src/tracing_subscriber/fmt/format/mod.rs.html#1026-1156>
impl<S, N> FormatEvent<S, N> for UvFormat
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
let meta = event.metadata();
let ansi = writer.has_ansi_escapes();

if self.display_timestamp {
if ansi {
write!(writer, "{} ", Timestamp::now().dimmed())?;
} else {
write!(writer, "{} ", Timestamp::now())?;
}
}

if self.display_level {
let level = meta.level();
// Same colors as tracing
if ansi {
match *level {
tracing::Level::TRACE => write!(writer, "{} ", level.purple())?,
tracing::Level::DEBUG => write!(writer, "{} ", level.blue())?,
tracing::Level::INFO => write!(writer, "{} ", level.green())?,
tracing::Level::WARN => write!(writer, "{} ", level.yellow())?,
tracing::Level::ERROR => write!(writer, "{} ", level.red())?,
}
} else {
write!(writer, "{level} ")?;
}
}

if self.show_spans {
let span = event.parent();
let mut seen = false;

let span = span
.and_then(|id| ctx.span(id))
.or_else(|| ctx.lookup_current());

let scope = span.into_iter().flat_map(|span| span.scope().from_root());

for span in scope {
seen = true;
if ansi {
write!(writer, "{}:", span.metadata().name().bold())?;
} else {
write!(writer, "{}:", span.metadata().name())?;
}
}

if seen {
writer.write_char(' ')?;
}
}

ctx.field_format().format_fields(writer.by_ref(), event)?;

writeln!(writer)
}
}
4 changes: 2 additions & 2 deletions crates/uv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ uv-git = { workspace = true }
uv-git-types = { workspace = true }
uv-install-wheel = { workspace = true, default-features = false }
uv-installer = { workspace = true }
uv-logging = { workspace = true }
uv-normalize = { workspace = true }
uv-pep440 = { workspace = true }
uv-pep508 = { workspace = true }
Expand Down Expand Up @@ -82,7 +83,6 @@ indicatif = { workspace = true }
indoc = { workspace = true }
itertools = { workspace = true }
h2 = { workspace = true }
jiff = { workspace = true }
miette = { workspace = true, features = ["fancy-no-backtrace"] }
owo-colors = { workspace = true }
petgraph = { workspace = true }
Expand All @@ -102,7 +102,7 @@ toml = { workspace = true }
toml_edit = { workspace = true }
tracing = { workspace = true }
tracing-durations-export = { workspace = true, features = ["plot"], optional = true }
tracing-subscriber = { workspace = true, features = ["json"] }
tracing-subscriber = { workspace = true, features = ["env-filter", "json", "registry"] }
tracing-tree = { workspace = true }
unicode-width = { workspace = true }
url = { workspace = true }
Expand Down
92 changes: 2 additions & 90 deletions crates/uv/src/logging.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
use std::fmt;
use std::str::FromStr;

use anyhow::Context;
use jiff::Timestamp;
use owo_colors::OwoColorize;
use tracing::{Event, Subscriber};
#[cfg(feature = "tracing-durations-export")]
use tracing_durations_export::{
DurationsLayer, DurationsLayerBuilder, DurationsLayerDropGuard, plot::PlotConfig,
};
use tracing_subscriber::filter::Directive;
use tracing_subscriber::fmt::format::Writer;
use tracing_subscriber::fmt::{FmtContext, FormatEvent, FormatFields};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::registry::LookupSpan;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, Layer, Registry};
use tracing_tree::HierarchicalLayer;
use tracing_tree::time::Uptime;

use uv_cli::ColorChoice;
use uv_logging::UvFormat;
use uv_static::EnvVars;

#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
Expand All @@ -31,81 +25,6 @@ pub(crate) enum Level {
TraceAll,
}

struct UvFormat {
display_timestamp: bool,
display_level: bool,
show_spans: bool,
}

/// See <https://docs.rs/tracing-subscriber/0.3.18/src/tracing_subscriber/fmt/format/mod.rs.html#1026-1156>
impl<S, N> FormatEvent<S, N> for UvFormat
where
S: Subscriber + for<'a> LookupSpan<'a>,
N: for<'a> FormatFields<'a> + 'static,
{
fn format_event(
&self,
ctx: &FmtContext<'_, S, N>,
mut writer: Writer<'_>,
event: &Event<'_>,
) -> fmt::Result {
let meta = event.metadata();
let ansi = writer.has_ansi_escapes();

if self.display_timestamp {
if ansi {
write!(writer, "{} ", Timestamp::now().dimmed())?;
} else {
write!(writer, "{} ", Timestamp::now())?;
}
}

if self.display_level {
let level = meta.level();
// Same colors as tracing
if ansi {
match *level {
tracing::Level::TRACE => write!(writer, "{} ", level.purple())?,
tracing::Level::DEBUG => write!(writer, "{} ", level.blue())?,
tracing::Level::INFO => write!(writer, "{} ", level.green())?,
tracing::Level::WARN => write!(writer, "{} ", level.yellow())?,
tracing::Level::ERROR => write!(writer, "{} ", level.red())?,
}
} else {
write!(writer, "{level} ")?;
}
}

if self.show_spans {
let span = event.parent();
let mut seen = false;

let span = span
.and_then(|id| ctx.span(id))
.or_else(|| ctx.lookup_current());

let scope = span.into_iter().flat_map(|span| span.scope().from_root());

for span in scope {
seen = true;
if ansi {
write!(writer, "{}:", span.metadata().name().bold())?;
} else {
write!(writer, "{}:", span.metadata().name())?;
}
}

if seen {
writer.write_char(' ')?;
}
}

ctx.field_format().format_fields(writer.by_ref(), event)?;

writeln!(writer)
}
}

/// Configure `tracing` based on the given [`Level`], taking into account the `RUST_LOG` environment
/// variable.
///
Expand Down Expand Up @@ -183,18 +102,11 @@ pub(crate) fn setup_logging(
)
.init();
} else {
// Regardless of the tracing level, show messages without any adornment.
let format = UvFormat {
display_timestamp: false,
display_level: true,
show_spans: false,
};

tracing_subscriber::registry()
.with(durations_layer)
.with(
tracing_subscriber::fmt::layer()
.event_format(format)
.event_format(UvFormat::default())
.with_writer(writer)
.with_ansi(ansi)
.with_filter(filter),
Expand Down
Loading
Loading