Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: better colored feature flag #95

Merged
merged 1 commit into from
Jan 15, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
cargo run --example simple_stdout
cargo run --example multiple_dispatches
cargo run --example custom_layout_filter
cargo run --features="no-color" --example simple_stdout
cargo run --no-default-features --example simple_stdout
cargo run --features="json" --example json_stdout
cargo run --features="json,rolling-file" --example rolling_file
cargo run --features="fastrace/enable" --example fastrace
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project will be documented in this file.

## [0.21.0] 2025-01-15

### Breaking changes

* Re-export `colored` to decouple the dependency. In addition, replace the `no-color` feature flag with the `colored` feature flag.

## [0.20.0] 2025-01-08

### Breaking changes
Expand Down
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["colored"]

colored = ["dep:colored"]
fastrace = ["dep:fastrace"]
journald = ["dep:libc"]
json = ["dep:serde_json", "dep:serde", "jiff/serde"]
native-tls = ["dep:native-tls", "fasyslog?/native-tls"]
no-color = ["colored/no-color"]
non-blocking = ["dep:crossbeam-channel"]
opentelemetry = [
"dep:opentelemetry",
Expand All @@ -48,12 +50,12 @@ syslog = ["non-blocking", "dep:fasyslog"]

[dependencies]
anyhow = { version = "1.0" }
colored = { version = "3.0" }
env_filter = { version = "0.1.1" }
jiff = { version = "0.1.14" }
log = { version = "0.4", features = ["std", "kv"] }

# Optional dependencies
colored = { version = "3.0", optional = true }
crossbeam-channel = { version = "0.5", optional = true }
fastrace = { version = "0.7", optional = true }
fasyslog = { version = "0.3", optional = true }
Expand Down
63 changes: 63 additions & 0 deletions src/color.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2024 FastLabs Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Color utilities.

use colored::{Color, ColoredString, Colorize};
use log::Level;

/// Colors for different log levels.
#[derive(Debug, Clone)]
pub struct LevelColor {
/// Color for error level logs.
pub error: Color,
/// Color for warning level logs.
pub warn: Color,
/// Color for info level logs.
pub info: Color,
/// Color for debug level logs.
pub debug: Color,
/// Color for trace level logs.
pub trace: Color,
}

impl Default for LevelColor {
fn default() -> Self {
Self {
error: Color::Red,
warn: Color::Yellow,
info: Color::Green,
debug: Color::Blue,
trace: Color::Magenta,
}
}
}

impl LevelColor {
/// Colorize the log level.
pub fn colorize_record_level(&self, no_color: bool, level: Level) -> ColoredString {
if no_color {
ColoredString::from(level.to_string())
} else {
let color = match level {
Level::Error => self.error,
Level::Warn => self.warn,
Level::Info => self.info,
Level::Debug => self.debug,
Level::Trace => self.trace,
};
ColoredString::from(level.to_string()).color(color)
}
}
}
3 changes: 2 additions & 1 deletion src/diagnostic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//! Mapped Diagnostic Context (MDC). A lighter technique consists of uniquely stamping each log request.
//! Mapped Diagnostic Context (MDC). A lighter technique consists of uniquely stamping each log
//! request.

use std::borrow::Cow;

Expand Down
1 change: 0 additions & 1 deletion src/layout/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
pub use custom::CustomLayout;
#[cfg(feature = "json")]
pub use json::JsonLayout;
pub use text::LevelColor;
pub use text::TextLayout;

use crate::Diagnostic;
Expand Down
161 changes: 70 additions & 91 deletions src/layout/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
use std::borrow::Cow;
use std::fmt::Write;

use colored::Color;
use colored::ColoredString;
use colored::Colorize;
use jiff::tz::TimeZone;
use jiff::Timestamp;
use jiff::Zoned;
Expand All @@ -27,6 +24,68 @@ use crate::diagnostic::Visitor;
use crate::layout::Layout;
use crate::Diagnostic;

#[cfg(feature = "colored")]
mod colored {
use super::*;
use crate::color::LevelColor;
use crate::colored::Color;
use crate::colored::ColoredString;

impl TextLayout {
/// Customize the color of each log level.
///
/// No effect if `no_color` is set to `true`.
pub fn colors(mut self, colors: LevelColor) -> Self {
self.colors = colors;
self
}

/// Customize the color of the error log level. Default to red.
///
/// No effect if `no_color` is set to `true`.
pub fn error_color(mut self, color: Color) -> Self {
self.colors.error = color;
self
}

/// Customize the color of the warn log level. Default to yellow.
///
/// No effect if `no_color` is set to `true`.
pub fn warn_color(mut self, color: Color) -> Self {
self.colors.warn = color;
self
}

/// Customize the color of the info log level/ Default to green.
///
/// No effect if `no_color` is set to `true`.
pub fn info_color(mut self, color: Color) -> Self {
self.colors.info = color;
self
}

/// Customize the color of the debug log level. Default to blue.
///
/// No effect if `no_color` is set to `true`.
pub fn debug_color(mut self, color: Color) -> Self {
self.colors.debug = color;
self
}

/// Customize the color of the trace log level. Default to magenta.
///
/// No effect if `no_color` is set to `true`.
pub fn trace_color(mut self, color: Color) -> Self {
self.colors.trace = color;
self
}

pub(crate) fn format_record_level(&self, level: Level) -> ColoredString {
self.colors.colorize_record_level(self.no_color, level)
}
}
}

/// A layout that formats log record as text.
///
/// Output format:
Expand All @@ -39,8 +98,8 @@ use crate::Diagnostic;
/// 2024-08-11T22:44:57.172382+08:00 TRACE rolling_file: examples/rolling_file.rs:55 Hello trace!
/// ```
///
/// By default, log levels are colored. You can turn on the `no-color` feature flag to disable this
/// feature. Instead, you can also set the `no_color` field to `true` to disable coloring.
/// By default, log levels are colored. You can set the `no_color` field to `true` to disable
/// coloring.
///
/// You can also customize the color of each log level by setting the `colors` field with a
/// [`LevelColor`] instance.
Expand All @@ -57,7 +116,8 @@ use crate::Diagnostic;
/// ```
#[derive(Debug, Clone, Default)]
pub struct TextLayout {
colors: LevelColor,
#[cfg(feature = "colored")]
colors: crate::color::LevelColor,
no_color: bool,
tz: Option<TimeZone>,
}
Expand All @@ -84,79 +144,9 @@ impl TextLayout {
self
}

/// Customize the color of each log level.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn colors(mut self, colors: LevelColor) -> Self {
self.colors = colors;
self
}

/// Customize the color of the error log level. Default to red.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn error_color(mut self, color: Color) -> Self {
self.colors.error = color;
self
}

/// Customize the color of the warn log level. Default to yellow.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn warn_color(mut self, color: Color) -> Self {
self.colors.warn = color;
self
}

/// Customize the color of the info log level/ Default to green.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn info_color(mut self, color: Color) -> Self {
self.colors.info = color;
self
}

/// Customize the color of the debug log level. Default to blue.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn debug_color(mut self, color: Color) -> Self {
self.colors.debug = color;
self
}

/// Customize the color of the trace log level. Default to magenta.
///
/// No effect if `no_color` is set to `true` or the `no-color` feature flag is enabled.
pub fn trace_color(mut self, color: Color) -> Self {
self.colors.trace = color;
self
}
}

/// Colors for different log levels.
#[derive(Debug, Clone)]
pub struct LevelColor {
/// Color for error level logs.
pub error: Color,
/// Color for warning level logs.
pub warn: Color,
/// Color for info level logs.
pub info: Color,
/// Color for debug level logs.
pub debug: Color,
/// Color for trace level logs.
pub trace: Color,
}

impl Default for LevelColor {
fn default() -> Self {
Self {
error: Color::Red,
warn: Color::Yellow,
info: Color::Green,
debug: Color::Blue,
trace: Color::Magenta,
}
#[cfg(not(feature = "colored"))]
pub(crate) fn format_record_level(&self, level: Level) -> String {
level.to_string()
}
}

Expand All @@ -170,18 +160,7 @@ impl TextLayout {
Some(tz) => Timestamp::now().to_zoned(tz),
None => Zoned::now(),
};
let level = if self.no_color {
ColoredString::from(record.level().to_string())
} else {
let color = match record.level() {
Level::Error => self.colors.error,
Level::Warn => self.colors.warn,
Level::Info => self.colors.info,
Level::Debug => self.colors.debug,
Level::Trace => self.colors.trace,
};
ColoredString::from(record.level().to_string()).color(color)
};
let level = self.format_record_level(record.level());
let target = record.target();
let file = filename(record);
let line = record.line().unwrap_or_default();
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@

#![cfg_attr(docsrs, feature(doc_auto_cfg))]

#[cfg(feature = "colored")]
pub extern crate colored;
#[cfg(feature = "colored")]
pub mod color;

pub mod append;
pub mod diagnostic;
pub mod filter;
Expand Down