Skip to content

Commit

Permalink
refactor: Merge logging infra and error management into a single crat…
Browse files Browse the repository at this point in the history
…e `weaver_common` (#119)
  • Loading branch information
lquerel authored Apr 17, 2024
1 parent 393f248 commit 2d33626
Show file tree
Hide file tree
Showing 42 changed files with 440 additions and 521 deletions.
218 changes: 106 additions & 112 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ rust-version = "1.76"
[workspace.dependencies]
serde = { version = "1.0.198", features = ["derive"] }
serde_yaml = "0.9.32"
serde_json = { version = "1.0.115"}
serde_json = { version = "1.0.116"}
thiserror = "1.0.58"
ureq = "2.9.6"
regex = "1.10.3"
Expand All @@ -39,7 +39,7 @@ anyhow = "1.0.81"

# Features definition =========================================================
[features]
experimental = ["tantivy"]
experimental = ["tantivy", "weaver_schema", "weaver_template"]

# Crate definitions ===========================================================
[[bin]]
Expand All @@ -49,13 +49,13 @@ name = "weaver"

[dependencies]
# local crates dependencies
weaver_logger = { path = "crates/weaver_logger" }
weaver_common = { path = "crates/weaver_common" }
weaver_resolver = { path = "crates/weaver_resolver" }
weaver_template = { path = "crates/weaver_template" }
weaver_template = { path = "crates/weaver_template", optional = true }
weaver_semconv = { path = "crates/weaver_semconv" }
weaver_resolved_schema = { path = "crates/weaver_resolved_schema" }
weaver_semconv_gen = { path = "crates/weaver_semconv_gen" }
weaver_schema = { path = "crates/weaver_schema" }
weaver_schema = { path = "crates/weaver_schema", optional = true }
weaver_cache = { path = "crates/weaver_cache" }
weaver_forge = { path = "crates/weaver_forge" }
weaver_checker = { path = "crates/weaver_checker" }
Expand All @@ -64,7 +64,7 @@ clap = { version = "4.5.4", features = ["derive"] }
crossterm = "0.27.0"
ratatui = "0.26.1"
tui-textarea = "0.4.0"
tantivy = { version = "0.21.1", optional = true }
tantivy = { version = "0.22.0", optional = true }

# workspace dependencies
serde.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/weaver_checker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ workspace = true


[dependencies]
weaver_common = { path = "../weaver_common" }

thiserror.workspace = true
serde.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion crates/weaver_checker/allowed-external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
# the public API. Ideally this can have a few exceptions as possible.
allowed_external_types = [
"serde::ser::Serialize",
"serde::de::Deserialize"
"serde::de::Deserialize",
"weaver_common::error::WeaverError"
]
12 changes: 12 additions & 0 deletions crates/weaver_checker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
//! evaluate policies.
use crate::violation::Violation;
use crate::Error::CompoundError;
use serde::Serialize;
use serde_json::to_value;
use std::path::Path;
use weaver_common::error::WeaverError;

pub mod violation;

Expand Down Expand Up @@ -51,6 +53,16 @@ pub enum Error {
CompoundError(Vec<Error>),
}

impl WeaverError for Error {
/// Retrieves a list of error messages associated with this error.
fn errors(&self) -> Vec<String> {
match self {
CompoundError(errors) => errors.iter().flat_map(WeaverError::errors).collect(),
_ => vec![self.to_string()],
}
}
}

impl Error {
/// Formats the given errors into a single string.
/// This used to render compound errors.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "weaver_logger"
name = "weaver_common"
version = "0.1.0"
authors.workspace = true
repository.workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/weaver_common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Weaver Common

A set of common tools and cross-cutting functions for the Weaver project such
as error management and generic logging infrastructure.
103 changes: 103 additions & 0 deletions crates/weaver_common/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: Apache-2.0

//! A generic trait for errors that can be returned by the weaver crates.
//! This trait is used by the logging infrastructure to print errors in
//! a consistent way.
use crate::Logger;
use std::process::exit;

/// A trait for custom error handling in the `weaver` crates.
pub trait WeaverError {
/// Retrieves a list of error messages associated with this error.
/// For compound errors, this method should return a list of all
/// error messages. For simple errors, this method should return
/// a list with a single error message.
///
/// # Returns
/// A `Vec<String>` containing human-readable error messages.
fn errors(&self) -> Vec<String>;
}

/// A trait for types that can cleanly exit the application if an error
/// is encountered.
pub trait ExitIfError<T, E> {
/// Processes the `Result` and exits the application if it is an `Err`.
/// If `Ok`, the contained value is returned.
///
/// # Arguments
/// * `self` - The `Result` to process.
/// * `logger` - An object implementing the `Logger` trait used to log any
/// errors.
///
/// # Returns
/// The contained value if the result is `Ok`.
/// Exits the process if the result is `Err`.
fn exit_if_error(self, logger: impl Logger) -> T;

/// Processes the `Result` and exits the application with a specified exit
/// code if it is an `Err`.
/// If `Ok`, the contained value is returned.
///
/// # Arguments
/// * `self` - The `Result` to process.
/// * `code` - The exit code to use if the result is an `Err`.
/// * `logger` - An object implementing the `Logger` trait used to log any
/// errors.
///
/// # Returns
/// The contained value if the result is `Ok`.
/// Exits the process with the specified `code` if the result is `Err`.
#[allow(dead_code)]
fn exit_with_code_if_error(self, code: i32, logger: impl Logger) -> T;
}

/// Provides default implementations of the `ExitIfError` trait for any
/// `Result<T, E>` where `E` implements `WeaverError`.
impl<T, E: WeaverError> ExitIfError<T, E> for Result<T, E> {
/// Processes the `Result` and exits the application if it is an `Err`.
/// If `Ok`, the contained value is returned.
///
/// # Arguments
/// * `self` - The `Result` to process.
/// * `logger` - An object implementing the `Logger` trait used to log any
/// errors.
///
/// # Returns
/// The contained value if the result is `Ok`.
/// Exits the process if the result is `Err`.
fn exit_if_error(self, logger: impl Logger) -> T {
match self {
Ok(value) => value,
Err(e) => {
e.errors().iter().for_each(|msg| logger.error(msg));
#[allow(clippy::exit)] // Expected behavior
exit(1)
}
}
}

/// Processes the `Result` and exits the application with a specified exit
/// code if it is an `Err`.
/// If `Ok`, the contained value is returned.
///
/// # Arguments
/// * `self` - The `Result` to process.
/// * `code` - The exit code to use if the result is an `Err`.
/// * `logger` - An object implementing the `Logger` trait used to log any
/// errors.
///
/// # Returns
/// The contained value if the result is `Ok`.
/// Exits the process with the specified `code` if the result is `Err`.
fn exit_with_code_if_error(self, code: i32, logger: impl Logger) -> T {
match self {
Ok(value) => value,
Err(e) => {
e.errors().iter().for_each(|msg| logger.error(msg));
#[allow(clippy::exit)] // Expected behavior
exit(code)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

//! A generic logger that can be used to log messages to the console.
pub mod error;
pub mod quiet;

use std::sync::atomic::AtomicUsize;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion crates/weaver_forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ workspace = true

[dependencies]
weaver_diff = { path = "../weaver_diff" }
weaver_logger = { path = "../weaver_logger" }
weaver_common = { path = "../weaver_common" }
weaver_resolver = { path = "../weaver_resolver" }
weaver_resolved_schema = { path = "../weaver_resolved_schema" }
weaver_semconv = { path = "../weaver_semconv" }
Expand Down
2 changes: 1 addition & 1 deletion crates/weaver_forge/allowed-external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ allowed_external_types = [
"serde::ser::Serialize",
"serde::de::Deserialize",
"serde_json::value::Value",
"weaver_logger::*",
"weaver_common::*",
"weaver_resolved_schema::*",
"weaver_semconv::*",
]
4 changes: 2 additions & 2 deletions crates/weaver_forge/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use crate::error::Error;
use crate::error::Error::{CompoundError, TemplateEvaluationFailed};
use indexmap::IndexMap;
use weaver_logger::Logger;
use weaver_common::Logger;

/// Return a nice summary of the error.
pub(crate) fn error_summary(error: minijinja::Error) -> String {
Expand Down Expand Up @@ -91,7 +91,7 @@ mod tests {

#[test]
fn test_print_dedup_errors() {
let logger = weaver_logger::TestLogger::new();
let logger = weaver_common::TestLogger::new();
let error = CompoundError(vec![
TargetNotSupported {
// <-- These 3 errors are deduplicated
Expand Down
11 changes: 11 additions & 0 deletions crates/weaver_forge/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::error::Error::CompoundError;
use std::path::PathBuf;
use weaver_common::error::WeaverError;
use weaver_resolved_schema::attribute::AttributeRef;

/// Errors emitted by this crate.
Expand Down Expand Up @@ -125,6 +126,16 @@ pub enum Error {
CompoundError(Vec<Error>),
}

impl WeaverError for Error {
/// Retrieves a list of error messages associated with this error.
fn errors(&self) -> Vec<String> {
match self {
CompoundError(errors) => errors.iter().flat_map(|e| e.errors()).collect(),
_ => vec![self.to_string()],
}
}
}

/// Handles a list of errors and returns a compound error if the list is not
/// empty or () if the list is empty.
pub fn handle_errors(errors: Vec<Error>) -> Result<(), Error> {
Expand Down
4 changes: 2 additions & 2 deletions crates/weaver_forge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use error::Error::{
ContextSerializationFailed, InvalidTemplateDir, InvalidTemplateFile, TargetNotSupported,
TemplateEvaluationFailed, WriteGeneratedCodeFailed,
};
use weaver_logger::Logger;
use weaver_common::Logger;

use crate::config::{ApplicationMode, CaseConvention, TargetConfig};
use crate::debug::error_summary;
Expand Down Expand Up @@ -464,8 +464,8 @@ mod tests {
use walkdir::WalkDir;

use crate::config::{ApplicationMode, TemplateConfig};
use weaver_common::TestLogger;
use weaver_diff::diff_output;
use weaver_logger::TestLogger;
use weaver_resolver::SchemaResolver;
use weaver_semconv::SemConvRegistry;

Expand Down
5 changes: 0 additions & 5 deletions crates/weaver_logger/README.md

This file was deleted.

2 changes: 1 addition & 1 deletion crates/weaver_resolver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rust-version.workspace = true
workspace = true

[dependencies]
weaver_logger = { path = "../weaver_logger" }
weaver_common = { path = "../weaver_common" }
weaver_semconv = { path = "../weaver_semconv" }
weaver_schema = { path = "../weaver_schema" }
weaver_version = { path = "../weaver_version" }
Expand Down
2 changes: 1 addition & 1 deletion crates/weaver_resolver/allowed-external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ allowed_external_types = [

"weaver_resolved_schema::*",
"weaver_semconv::*",
"weaver_logger::*",
"weaver_common::*",
"weaver_cache::Cache",
"weaver_schema::*",
"weaver_version::*",
Expand Down
15 changes: 13 additions & 2 deletions crates/weaver_resolver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use walkdir::DirEntry;

use weaver_cache::Cache;
use weaver_checker::violation::Violation;
use weaver_logger::Logger;
use weaver_common::error::WeaverError;
use weaver_common::Logger;
use weaver_resolved_schema::catalog::Catalog;
use weaver_resolved_schema::registry::Constraint;
use weaver_resolved_schema::ResolvedTelemetrySchema;
Expand Down Expand Up @@ -171,6 +172,16 @@ pub enum Error {
CompoundError(Vec<Error>),
}

impl WeaverError for Error {
/// Returns a list of human-readable error messages.
fn errors(&self) -> Vec<String> {
match self {
Error::CompoundError(errors) => errors.iter().flat_map(|e| e.errors()).collect(),
_ => vec![self.to_string()],
}
}
}

/// Handles a list of errors and returns a compound error if the list is not
/// empty or () if the list is empty.
pub fn handle_errors(errors: Vec<Error>) -> Result<(), Error> {
Expand Down Expand Up @@ -639,7 +650,7 @@ impl SchemaResolver {
#[cfg(test)]
mod test {
use weaver_cache::Cache;
use weaver_logger::{ConsoleLogger, Logger};
use weaver_common::{ConsoleLogger, Logger};

use crate::SchemaResolver;

Expand Down
1 change: 1 addition & 0 deletions crates/weaver_semconv_gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ edition.workspace = true
rust-version.workspace = true

[dependencies]
weaver_common = { path = "../weaver_common" }
weaver_cache = { path = "../weaver_cache" }
weaver_diff = { path = "../weaver_diff" }
weaver_resolver = { path = "../weaver_resolver" }
Expand Down
1 change: 1 addition & 0 deletions crates/weaver_semconv_gen/allowed-external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ allowed_external_types = [
"weaver_semconv::path::RegistryPath",
"weaver_resolver::Error",
"weaver_cache::Cache",
"weaver_common::error::WeaverError"
]
11 changes: 11 additions & 0 deletions crates/weaver_semconv_gen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use std::fs;

use weaver_cache::Cache;
use weaver_common::error::WeaverError;
use weaver_diff::diff_output;
use weaver_resolved_schema::attribute::{Attribute, AttributeRef};
use weaver_resolved_schema::registry::{Group, Registry};
Expand Down Expand Up @@ -77,6 +78,16 @@ pub enum Error {
ResolverError(#[from] weaver_resolver::Error),
}

impl WeaverError for Error {
/// Retrieves a list of error messages associated with this error.
fn errors(&self) -> Vec<String> {
// Note: If the CompoundError pattern is implemented for this crate
// the following must be updated to return the errors of the compound
// error.
vec![self.to_string()]
}
}

// TODO - this is based on https://github.com/open-telemetry/build-tools/blob/main/semantic-conventions/src/opentelemetry/semconv/templating/markdown/__init__.py#L503
// We can likely model this much better.
/// Parameters users can specify for generating markdown.
Expand Down
Loading

0 comments on commit 2d33626

Please sign in to comment.