diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..bd307c3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,19 @@ +# 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. + +[alias] +x = "run --package x --" + +[env] +CARGO_WORKSPACE_DIR = { value = "", relative = true } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96d7cbf..f64b707 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,13 +47,7 @@ jobs: - uses: taiki-e/install-action@v2 with: tool: typos-cli,taplo-cli,hawkeye - - name: Check all - run: | - hawkeye check - taplo format --check - typos - cargo +nightly fmt --all -- --check - cargo +nightly clippy --all-targets --all-features -- -D warnings + - run: cargo x lint msrv: name: Resolve MSRV @@ -89,10 +83,9 @@ jobs: run: cargo build --workspace --all-features --bins --tests --examples --benches --lib - name: Run unit tests shell: bash - run: cargo test --all-features -- --nocapture + run: cargo x test --no-capture - name: Run examples shell: bash - working-directory: logforth run: | set -x cargo run --features="bridge-log" --example simple_stdout diff --git a/Cargo.toml b/Cargo.toml index 80f7bfc..085642a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,11 +15,13 @@ [workspace] members = [ "core", + "examples", "logforth", "appenders/*", "bridges/*", "diagnostics/*", "layouts/*", + "xtask", ] resolver = "2" @@ -34,6 +36,7 @@ rust-version = "1.85.0" [workspace.dependencies] # Workspace dependencies +logforth = { version = "0.29.1", path = "logforth" } logforth-append-async = { version = "0.3.0", path = "appenders/async" } logforth-append-fastrace = { version = "0.3.0", path = "appenders/fastrace" } logforth-append-file = { version = "0.3.0", path = "appenders/file" } @@ -52,6 +55,7 @@ logforth-layout-text = { version = "0.3.0", path = "layouts/text" } # Crates.io dependencies anyhow = { version = "1.0" } arc-swap = { version = "1.7.1" } +clap = { version = "4.5.49", features = ["derive"] } colored = { version = "3.0" } crossbeam-channel = { version = "0.5.15" } fastrace = { version = "0.7" } @@ -71,9 +75,9 @@ serde_json = { version = "1.0" } tempfile = { version = "3.16" } tokio = { version = "1.47.1" } value-bag = { version = "1.11.1", features = ["inline-i128", "owned", "sval"] } +which = { version = "8.0.0" } [workspace.lints.rust] -missing_docs = "deny" unknown_lints = "deny" unused_must_use = "deny" diff --git a/README.md b/README.md index 0a8e176..1fb2978 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ fn main() { } ``` -Read more demos under the [examples](logforth/examples) directory. +Read more demos under the [examples](examples) directory. ## Features diff --git a/appenders/async/README.md b/appenders/async/README.md index 39fa161..e52468f 100644 --- a/appenders/async/README.md +++ b/appenders/async/README.md @@ -3,3 +3,4 @@ This appender is a remix of [spdlog-rs's AsyncPoolSink](https://docs.rs/spdlog-rs/*/spdlog/sink/struct.AsyncPoolSink.html), with several modifications to fit this crate's need: * Instead of a thread pool, it uses a single background thread to drain the log queue. +* `flush` will block until all pending log messages are processed. This avoids the need of `Append::exit` we once added. diff --git a/appenders/async/src/append.rs b/appenders/async/src/append.rs index 60aed83..f8c8d39 100644 --- a/appenders/async/src/append.rs +++ b/appenders/async/src/append.rs @@ -27,6 +27,28 @@ use crate::state::AsyncState; use crate::worker::Worker; /// A composable appender, logging and flushing asynchronously. +/// +/// # Examples +/// +/// ``` +/// use logforth_append_async::AsyncBuilder; +/// use logforth_core::append::Stderr; +/// +/// let async_append = AsyncBuilder::new("logforth-async-append") +/// .overflow_drop_incoming() +/// // for demonstration purposes; in practice, this can be a file appender, etc. +/// .append(Stderr::default()) +/// .build(); +/// ``` +/// +/// # Caveats +/// +/// The caller or application should ensure that the `flush` method is called before the program +/// exits to write out any buffered events, especially when this appender is used in a global +/// context. +/// +/// The drop glue will also flush the appender. But, in Rust, static items do not call `drop` +/// at the end of the program. #[derive(Debug)] pub struct Async { state: AsyncState, diff --git a/appenders/async/src/lib.rs b/appenders/async/src/lib.rs index edf945e..5d40e5d 100644 --- a/appenders/async/src/lib.rs +++ b/appenders/async/src/lib.rs @@ -15,6 +15,7 @@ //! A composable appender, logging and flushing asynchronously. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use logforth_core::Error; use logforth_core::kv; diff --git a/appenders/async/tests/flushes.rs b/appenders/async/tests/flushes.rs index 3b4ffe2..efb22c6 100644 --- a/appenders/async/tests/flushes.rs +++ b/appenders/async/tests/flushes.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Tests for asynchronous appenders wait on flushes. - use std::sync::Arc; use std::sync::Barrier; use std::sync::atomic::AtomicBool; diff --git a/appenders/fastrace/src/lib.rs b/appenders/fastrace/src/lib.rs index 307082c..a5a7dcc 100644 --- a/appenders/fastrace/src/lib.rs +++ b/appenders/fastrace/src/lib.rs @@ -15,6 +15,7 @@ //! Appender for integrating with [fastrace](https://crates.io/crates/fastrace). #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use std::borrow::Cow; @@ -42,10 +43,6 @@ use logforth_core::record::Record; /// The caller or application should ensure that the `flush` method or [`fastrace::flush`] is called /// before the program exits to collect the final events, especially when this appender is used /// in a global context. -/// -/// Both the `exit` method and the drop glue do not call `fastrace::flush`, because it uses -/// thread-local storage internally, which is not supported in `atexit` callbacks or arbitrary -/// drop cases. #[derive(Default, Debug, Clone)] #[non_exhaustive] pub struct FastraceEvent {} diff --git a/appenders/file/src/append.rs b/appenders/file/src/append.rs index 0335098..06e56c5 100644 --- a/appenders/file/src/append.rs +++ b/appenders/file/src/append.rs @@ -31,6 +31,8 @@ use crate::rolling::RollingFileWriterBuilder; use crate::rotation::Rotation; /// A builder to configure and create an [`File`] appender. +/// +/// See [module-level documentation](super) for usage examples. #[derive(Debug)] pub struct FileBuilder { builder: RollingFileWriterBuilder, diff --git a/appenders/file/src/lib.rs b/appenders/file/src/lib.rs index a2c5586..c8db4cc 100644 --- a/appenders/file/src/lib.rs +++ b/appenders/file/src/lib.rs @@ -38,6 +38,7 @@ //! ``` #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub use self::append::File; pub use self::append::FileBuilder; diff --git a/appenders/file/tests/global_file_limit.rs b/appenders/file/tests/global_file_limit.rs index c6faa6a..ee0e193 100644 --- a/appenders/file/tests/global_file_limit.rs +++ b/appenders/file/tests/global_file_limit.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Ensure max_log_files limits the total number of log files across multiple date patterns. - use std::fs; use std::num::NonZeroUsize; use std::path::Path; diff --git a/appenders/journald/src/lib.rs b/appenders/journald/src/lib.rs index fad3c4b..ffd3af5 100644 --- a/appenders/journald/src/lib.rs +++ b/appenders/journald/src/lib.rs @@ -16,6 +16,7 @@ #![cfg(unix)] #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use std::io::Write; use std::os::unix::net::UnixDatagram; diff --git a/appenders/opentelemetry/src/lib.rs b/appenders/opentelemetry/src/lib.rs index bb92350..d9c0f19 100644 --- a/appenders/opentelemetry/src/lib.rs +++ b/appenders/opentelemetry/src/lib.rs @@ -15,6 +15,7 @@ //! Appenders and utilities for integrating with OpenTelemetry. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use std::borrow::Cow; use std::fmt; diff --git a/appenders/syslog/src/lib.rs b/appenders/syslog/src/lib.rs index b0704da..8ce8938 100644 --- a/appenders/syslog/src/lib.rs +++ b/appenders/syslog/src/lib.rs @@ -31,6 +31,7 @@ //! ``` #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use std::io; use std::sync::Mutex; @@ -273,6 +274,8 @@ mod unix_ext { } /// An appender that writes log records to syslog. +/// +/// See [module-level documentation](self) for usage examples. #[derive(Debug)] pub struct Syslog { sender: Mutex, diff --git a/bridges/log/src/lib.rs b/bridges/log/src/lib.rs index 75b33a2..75bd7a0 100644 --- a/bridges/log/src/lib.rs +++ b/bridges/log/src/lib.rs @@ -15,6 +15,7 @@ //! A bridge to forward logs from the `log` crate to `logforth`. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use log::Metadata; use log::Record; diff --git a/core/src/lib.rs b/core/src/lib.rs index 65a1e78..dc5f75f 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -15,6 +15,7 @@ //! Core structs and functions for the logforth logging framework. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub mod append; pub mod diagnostic; diff --git a/diagnostics/fastrace/src/lib.rs b/diagnostics/fastrace/src/lib.rs index b0c1155..c5265b6 100644 --- a/diagnostics/fastrace/src/lib.rs +++ b/diagnostics/fastrace/src/lib.rs @@ -15,6 +15,7 @@ //! A diagnostic that enriches log records with trace context provided by the Fastrace library. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use fastrace::collector::SpanContext; use logforth_core::Diagnostic; @@ -25,16 +26,6 @@ use logforth_core::kv::Visitor; /// A diagnostic that enriches log records with trace context provided by the Fastrace library. /// -/// Output format: -/// -/// ```text -/// 2025-01-10T15:22:37.868815+08:00 ERROR fastrace: fastrace.rs:39 Hello syslog error! trace_id=37f9c45f918cbb477089afb0d7162e7e -/// 2025-01-10T15:22:37.868890+08:00 WARN fastrace: fastrace.rs:40 Hello syslog warn! trace_id=37f9c45f918cbb477089afb0d7162e7e -/// 2025-01-10T15:22:37.868921+08:00 INFO fastrace: fastrace.rs:41 Hello syslog info! trace_id=37f9c45f918cbb477089afb0d7162e7e -/// 2025-01-10T15:22:37.868949+08:00 DEBUG fastrace: fastrace.rs:42 Hello syslog debug! trace_id=37f9c45f918cbb477089afb0d7162e7e -/// 2025-01-10T15:22:37.868976+08:00 TRACE fastrace: fastrace.rs:43 Hello syslog trace! trace_id=37f9c45f918cbb477089afb0d7162e7e -/// ``` -/// /// ## Example /// /// ``` diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 0000000..0d64cb2 --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,134 @@ +# 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. + +[package] +name = "examples" +publish = false + +edition.workspace = true +rust-version.workspace = true + +[package.metadata.release] +release = false + +[features] +# Starters +starter-log = ["bridge-log", "append-file", "layout-text", "layout-json"] + +# Bridges +bridge-log = ["logforth/bridge-log"] + +# Appenders +append-async = ["logforth/append-async"] +append-fastrace = ["logforth/append-fastrace"] +append-file = ["logforth/append-file"] +append-journald = ["logforth/append-journald"] +append-opentelemetry = ["logforth/append-opentelemetry"] +append-syslog = ["logforth/append-syslog"] + +# Layouts +layout-google-cloud-logging = ["logforth/layout-google-cloud-logging"] +layout-json = ["logforth/layout-json"] +layout-logfmt = ["logforth/layout-logfmt"] +layout-text = ["logforth/layout-text"] + +# Diagnostics +diagnostic-fastrace = ["logforth/diagnostic-fastrace"] +diagnostic-task-local = ["logforth/diagnostic-task-local"] + +[dependencies] +logforth = { workspace = true } + +[dev-dependencies] +fastrace = { workspace = true, features = ["enable"] } +log = { workspace = true, features = ["kv_serde"] } +serde = { workspace = true } +tokio = { workspace = true, features = ["full"] } + +[lints] +workspace = true + +[[example]] +name = "asynchronous" +path = "src/asynchronous.rs" +required-features = ["starter-log", "append-async"] + +[[example]] +name = "testing" +path = "src/testing.rs" +required-features = ["bridge-log"] + +[[example]] +name = "simple_stdout" +path = "src/simple_stdout.rs" +required-features = ["bridge-log"] + +[[example]] +name = "log_with_logger" +path = "src/log_with_logger.rs" +required-features = ["bridge-log"] + +[[example]] +name = "json_stdout" +path = "src/json_stdout.rs" +required-features = ["starter-log"] + +[[example]] +name = "multiple_dispatches" +path = "src/multiple_dispatches.rs" +required-features = ["starter-log"] + +[[example]] +name = "rolling_file" +path = "src/rolling_file.rs" +required-features = ["starter-log"] + +[[example]] +name = "single_file" +path = "src/single_file.rs" +required-features = ["starter-log"] + +[[example]] +name = "task_local" +path = "src/task_local.rs" +required-features = ["starter-log", "diagnostic-task-local"] + +[[example]] +name = "custom_layout_filter" +path = "src/custom_layout_filter.rs" +required-features = ["starter-log"] + +[[example]] +name = "syslog" +path = "src/syslog.rs" +required-features = ["starter-log", "append-syslog"] + +[[example]] +name = "journald" +path = "src/journald.rs" +required-features = ["starter-log", "append-journald"] + +[[example]] +name = "fastrace" +path = "src/fastrace.rs" +required-features = ["starter-log", "append-fastrace", "diagnostic-fastrace"] + +[[example]] +name = "google_cloud_logging" +path = "src/google_cloud_logging.rs" +required-features = [ + "starter-log", + "diagnostic-fastrace", + "layout-google-cloud-logging", +] diff --git a/logforth/examples/asynchronous.rs b/examples/src/asynchronous.rs similarity index 92% rename from logforth/examples/asynchronous.rs rename to examples/src/asynchronous.rs index 88c9892..d7f4ead 100644 --- a/logforth/examples/asynchronous.rs +++ b/examples/src/asynchronous.rs @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging to a single file with async combinator. - +use logforth::append::asynchronous::AsyncBuilder; use logforth::append::file::FileBuilder; use logforth::layout::JsonLayout; use logforth::record::LevelFilter; -use logforth_append_async::AsyncBuilder; fn main() { let file = FileBuilder::new("logs", "my_app_async") diff --git a/logforth/examples/custom_layout_filter.rs b/examples/src/custom_layout_filter.rs similarity index 97% rename from logforth/examples/custom_layout_filter.rs rename to examples/src/custom_layout_filter.rs index fe7c12e..e6e92dc 100644 --- a/logforth/examples/custom_layout_filter.rs +++ b/examples/src/custom_layout_filter.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of custom layout and filter. - use logforth::Diagnostic; use logforth::Error; use logforth::Filter; diff --git a/logforth/examples/fastrace.rs b/examples/src/fastrace.rs similarity index 96% rename from logforth/examples/fastrace.rs rename to examples/src/fastrace.rs index 92176ed..e74fb87 100644 --- a/logforth/examples/fastrace.rs +++ b/examples/src/fastrace.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of using `fastrace` with `logforth`. - use fastrace::Span; use fastrace::collector::Config; use fastrace::collector::ConsoleReporter; diff --git a/logforth/examples/google_cloud_logging.rs b/examples/src/google_cloud_logging.rs similarity index 96% rename from logforth/examples/google_cloud_logging.rs rename to examples/src/google_cloud_logging.rs index c2c7567..75786a1 100644 --- a/logforth/examples/google_cloud_logging.rs +++ b/examples/src/google_cloud_logging.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of using `logforth` with `fastrace` and Google Cloud Logging format. - use fastrace::Span; use fastrace::collector::Config; use fastrace::collector::ConsoleReporter; diff --git a/logforth/examples/journald.rs b/examples/src/journald.rs similarity index 95% rename from logforth/examples/journald.rs rename to examples/src/journald.rs index 1bd5e3e..ffa8075 100644 --- a/logforth/examples/journald.rs +++ b/examples/src/journald.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of using `journald` with `logforth`. - #[cfg(unix)] fn main() { let append = logforth::append::Journald::new().unwrap(); diff --git a/logforth/examples/json_stdout.rs b/examples/src/json_stdout.rs similarity index 94% rename from logforth/examples/json_stdout.rs rename to examples/src/json_stdout.rs index adcfc5d..051b7b1 100644 --- a/logforth/examples/json_stdout.rs +++ b/examples/src/json_stdout.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging to stdout in JSON format. - use logforth::append; use logforth::layout::JsonLayout; diff --git a/logforth/examples/log_with_logger.rs b/examples/src/log_with_logger.rs similarity index 94% rename from logforth/examples/log_with_logger.rs rename to examples/src/log_with_logger.rs index cd5e335..1cf0d21 100644 --- a/logforth/examples/log_with_logger.rs +++ b/examples/src/log_with_logger.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging with a specific logger instance. - use logforth::append; use logforth::bridge::log::OwnedLogProxy; diff --git a/logforth/examples/multiple_dispatches.rs b/examples/src/multiple_dispatches.rs similarity index 91% rename from logforth/examples/multiple_dispatches.rs rename to examples/src/multiple_dispatches.rs index 6240346..ded88df 100644 --- a/logforth/examples/multiple_dispatches.rs +++ b/examples/src/multiple_dispatches.rs @@ -12,11 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of multiple dispatches with different filters and appenders. - use logforth::append; +use logforth::record::Level; use logforth::record::LevelFilter; -use logforth_core::record::Level; fn main() { logforth::starter_log::builder() diff --git a/logforth/examples/rolling_file.rs b/examples/src/rolling_file.rs similarity index 95% rename from logforth/examples/rolling_file.rs rename to examples/src/rolling_file.rs index 956c25d..d22f198 100644 --- a/logforth/examples/rolling_file.rs +++ b/examples/src/rolling_file.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging to rolling files in JSON format. - use logforth::append::file::FileBuilder; use logforth::layout::JsonLayout; use logforth::record::LevelFilter; diff --git a/logforth/examples/simple_stdout.rs b/examples/src/simple_stdout.rs similarity index 91% rename from logforth/examples/simple_stdout.rs rename to examples/src/simple_stdout.rs index caf5153..fb87a40 100644 --- a/logforth/examples/simple_stdout.rs +++ b/examples/src/simple_stdout.rs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of simple logging to stdout. - -use logforth_core::record::LevelFilter; +use logforth::record::LevelFilter; fn main() { logforth::starter_log::stdout() diff --git a/logforth/examples/single_file.rs b/examples/src/single_file.rs similarity index 95% rename from logforth/examples/single_file.rs rename to examples/src/single_file.rs index 2b5e2cb..af6d4d0 100644 --- a/logforth/examples/single_file.rs +++ b/examples/src/single_file.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging to a single file in JSON format. - use logforth::append::file::FileBuilder; use logforth::layout::JsonLayout; use logforth::record::LevelFilter; diff --git a/logforth/examples/syslog.rs b/examples/src/syslog.rs similarity index 96% rename from logforth/examples/syslog.rs rename to examples/src/syslog.rs index 5b64b07..d06a18d 100644 --- a/logforth/examples/syslog.rs +++ b/examples/src/syslog.rs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! An example of logging to syslog over TCP. - use logforth::append::syslog::SyslogBuilder; use logforth::record::LevelFilter; diff --git a/logforth/examples/task_local.rs b/examples/src/task_local.rs similarity index 94% rename from logforth/examples/task_local.rs rename to examples/src/task_local.rs index d7751a6..5e532d8 100644 --- a/logforth/examples/task_local.rs +++ b/examples/src/task_local.rs @@ -12,12 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Example of using task-local storage with `logForth`. - use logforth::diagnostic::TaskLocalDiagnostic; use logforth::diagnostic::task_local::FutureExt; +use logforth::layout::TextLayout; use logforth::record::LevelFilter; -use logforth_layout_text::TextLayout; #[tokio::main] async fn main() { diff --git a/logforth/examples/testing.rs b/examples/src/testing.rs similarity index 100% rename from logforth/examples/testing.rs rename to examples/src/testing.rs diff --git a/layouts/google-cloud-logging/src/lib.rs b/layouts/google-cloud-logging/src/lib.rs index 356f82c..f43f670 100644 --- a/layouts/google-cloud-logging/src/lib.rs +++ b/layouts/google-cloud-logging/src/lib.rs @@ -15,6 +15,7 @@ //! Layout for Google Cloud Structured Logging. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] use std::collections::BTreeMap; use std::collections::BTreeSet; diff --git a/layouts/json/src/lib.rs b/layouts/json/src/lib.rs index 39f01eb..5fed307 100644 --- a/layouts/json/src/lib.rs +++ b/layouts/json/src/lib.rs @@ -15,6 +15,7 @@ //! A JSON layout for formatting log records. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub extern crate jiff; diff --git a/layouts/logfmt/src/lib.rs b/layouts/logfmt/src/lib.rs index 8745d1d..e2c61df 100644 --- a/layouts/logfmt/src/lib.rs +++ b/layouts/logfmt/src/lib.rs @@ -15,6 +15,7 @@ //! A logfmt layout for formatting log records. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub extern crate jiff; diff --git a/layouts/text/src/lib.rs b/layouts/text/src/lib.rs index ad1e3d2..f9ec77f 100644 --- a/layouts/text/src/lib.rs +++ b/layouts/text/src/lib.rs @@ -15,6 +15,7 @@ //! A layout that formats log record as optionally colored text. #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub extern crate colored; pub extern crate jiff; diff --git a/logforth/Cargo.toml b/logforth/Cargo.toml index 5feb1df..1bd08f9 100644 --- a/logforth/Cargo.toml +++ b/logforth/Cargo.toml @@ -81,99 +81,13 @@ logforth-layout-logfmt = { workspace = true, optional = true } logforth-layout-text = { workspace = true, optional = true } [dev-dependencies] -fastrace = { workspace = true, features = ["enable"] } -log = { workspace = true, features = ["kv_serde"] } +log = { workspace = true } logforth-append-file = { workspace = true } -serde = { workspace = true } -tokio = { workspace = true, features = ["full"] } [lints] workspace = true -[[example]] -doc-scrape-examples = true -name = "asynchronous" -path = "examples/asynchronous.rs" -required-features = ["starter-log", "append-async"] - -[[example]] -doc-scrape-examples = true -name = "testing" -path = "examples/testing.rs" -required-features = ["bridge-log"] - -[[example]] -doc-scrape-examples = true -name = "simple_stdout" -path = "examples/simple_stdout.rs" -required-features = ["bridge-log"] - -[[example]] -doc-scrape-examples = true -name = "log_with_logger" -path = "examples/log_with_logger.rs" -required-features = ["bridge-log"] - -[[example]] -doc-scrape-examples = true -name = "json_stdout" -path = "examples/json_stdout.rs" +[[test]] +name = "recursive_logging" +path = "tests/recursive_logging.rs" required-features = ["starter-log"] - -[[example]] -doc-scrape-examples = true -name = "multiple_dispatches" -path = "examples/multiple_dispatches.rs" -required-features = ["starter-log"] - -[[example]] -doc-scrape-examples = true -name = "rolling_file" -path = "examples/rolling_file.rs" -required-features = ["starter-log"] - -[[example]] -doc-scrape-examples = true -name = "single_file" -path = "examples/single_file.rs" -required-features = ["starter-log"] - -[[example]] -doc-scrape-examples = true -name = "task_local" -path = "examples/task_local.rs" -required-features = ["starter-log", "diagnostic-task-local"] - -[[example]] -doc-scrape-examples = true -name = "custom_layout_filter" -path = "examples/custom_layout_filter.rs" -required-features = ["starter-log"] - -[[example]] -doc-scrape-examples = true -name = "syslog" -path = "examples/syslog.rs" -required-features = ["starter-log", "append-syslog"] - -[[example]] -doc-scrape-examples = true -name = "journald" -path = "examples/journald.rs" -required-features = ["starter-log", "append-journald"] - -[[example]] -doc-scrape-examples = true -name = "fastrace" -path = "examples/fastrace.rs" -required-features = ["starter-log", "append-fastrace", "diagnostic-fastrace"] - -[[example]] -doc-scrape-examples = true -name = "google_cloud_logging" -path = "examples/google_cloud_logging.rs" -required-features = [ - "starter-log", - "diagnostic-fastrace", - "layout-google-cloud-logging", -] diff --git a/logforth/src/lib.rs b/logforth/src/lib.rs index ae350f6..880a2c4 100644 --- a/logforth/src/lib.rs +++ b/logforth/src/lib.rs @@ -65,6 +65,7 @@ //! [README]: https://github.com/fast/logforth?tab=readme-ov-file #![cfg_attr(docsrs, feature(doc_cfg))] +#![deny(missing_docs)] pub use logforth_core::Error; pub use logforth_core::append::Append; diff --git a/logforth/tests/recursive_logging.rs b/logforth/tests/recursive_logging.rs index 8e979a2..946feec 100644 --- a/logforth/tests/recursive_logging.rs +++ b/logforth/tests/recursive_logging.rs @@ -12,10 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This case ensures our impl does properly handle recursive logging. - -#![cfg(feature = "starter-log")] - use std::num::NonZeroUsize; use logforth::Diagnostic; diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000..02d2cdc --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,27 @@ +# 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. + +[package] +name = "x" +publish = false + +edition.workspace = true +rust-version.workspace = true + +[dependencies] +clap = { workspace = true } +which = { workspace = true } + +[lints] +workspace = true diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000..ed4daeb --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,197 @@ +// 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. + +use std::process::Command as StdCommand; + +use clap::Parser; +use clap::Subcommand; + +#[derive(Parser)] +struct Command { + #[clap(subcommand)] + sub: SubCommand, +} + +impl Command { + fn run(self) { + match self.sub { + SubCommand::Build(cmd) => cmd.run(), + SubCommand::Lint(cmd) => cmd.run(), + SubCommand::Test(cmd) => cmd.run(), + } + } +} + +#[derive(Subcommand)] +enum SubCommand { + #[clap(about = "Compile workspace packages.")] + Build(CommandBuild), + #[clap(about = "Run format and clippy checks.")] + Lint(CommandLint), + #[clap(about = "Run unit tests.")] + Test(CommandTest), +} + +#[derive(Parser)] +struct CommandBuild { + #[arg(long, help = "Assert that `Cargo.lock` will remain unchanged.")] + locked: bool, +} + +impl CommandBuild { + fn run(self) { + run_command(make_build_cmd(self.locked)); + } +} + +#[derive(Parser)] +struct CommandTest { + #[arg(long, help = "Run tests serially and do not capture output.")] + no_capture: bool, +} + +impl CommandTest { + fn run(self) { + run_command(make_test_cmd(self.no_capture)); + } +} + +#[derive(Parser)] +#[clap(name = "lint")] +struct CommandLint { + #[arg(long, help = "Automatically apply lint suggestions.")] + fix: bool, +} + +impl CommandLint { + fn run(self) { + run_command(make_clippy_cmd(self.fix)); + run_command(make_format_cmd(self.fix)); + run_command(make_taplo_cmd(self.fix)); + run_command(make_typos_cmd()); + run_command(make_hawkeye_cmd(self.fix)); + } +} + +fn find_command(cmd: &str) -> StdCommand { + match which::which(cmd) { + Ok(exe) => { + let mut cmd = StdCommand::new(exe); + cmd.current_dir(env!("CARGO_WORKSPACE_DIR")); + cmd + } + Err(err) => { + panic!("{cmd} not found: {err}"); + } + } +} + +fn ensure_installed(bin: &str, crate_name: &str) { + if which::which(bin).is_err() { + let mut cmd = find_command("cargo"); + cmd.args(["install", crate_name]); + run_command(cmd); + } +} + +fn run_command(mut cmd: StdCommand) { + println!("{cmd:?}"); + let status = cmd.status().expect("failed to execute process"); + assert!(status.success(), "command failed: {status}"); +} + +fn make_build_cmd(locked: bool) -> StdCommand { + let mut cmd = find_command("cargo"); + cmd.args([ + "build", + "--workspace", + "--all-features", + "--tests", + "--examples", + "--benches", + "--bins", + ]); + if locked { + cmd.arg("--locked"); + } + cmd +} + +fn make_test_cmd(no_capture: bool) -> StdCommand { + let mut cmd = find_command("cargo"); + cmd.args(["test", "--workspace", "--all-features"]); + if no_capture { + cmd.args(["--", "--nocapture"]); + } + cmd +} + +fn make_format_cmd(fix: bool) -> StdCommand { + let mut cmd = find_command("cargo"); + cmd.args(["+nightly", "fmt", "--all"]); + if !fix { + cmd.arg("--check"); + } + cmd +} + +fn make_clippy_cmd(fix: bool) -> StdCommand { + let mut cmd = find_command("cargo"); + cmd.args([ + "+nightly", + "clippy", + "--tests", + "--all-features", + "--all-targets", + "--workspace", + ]); + if fix { + cmd.args(["--allow-staged", "--allow-dirty", "--fix"]); + } else { + cmd.args(["--", "-D", "warnings"]); + } + cmd +} + +fn make_hawkeye_cmd(fix: bool) -> StdCommand { + ensure_installed("hawkeye", "hawkeye"); + let mut cmd = find_command("hawkeye"); + if fix { + cmd.args(["format", "--fail-if-updated=false"]); + } else { + cmd.args(["check"]); + } + cmd +} + +fn make_typos_cmd() -> StdCommand { + ensure_installed("typos", "typos-cli"); + find_command("typos") +} + +fn make_taplo_cmd(fix: bool) -> StdCommand { + ensure_installed("taplo", "taplo-cli"); + let mut cmd = find_command("taplo"); + if fix { + cmd.args(["format"]); + } else { + cmd.args(["format", "--check"]); + } + cmd +} + +fn main() { + let cmd = Command::parse(); + cmd.run() +}