graduate log to stable and add crasdump

This commit is contained in:
sevki 2024-05-28 14:01:09 +01:00
parent 7a056e8d14
commit b88150cb5a
11 changed files with 257 additions and 298 deletions

215
Cargo.lock generated
View file

@ -32,12 +32,6 @@ version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
[[package]]
name = "arc-swap"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
[[package]]
name = "arrayvec"
version = "0.7.4"
@ -93,12 +87,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bitvec"
version = "1.0.1"
@ -144,6 +132,27 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "colored"
version = "1.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355"
dependencies = [
"is-terminal",
"lazy_static",
"winapi",
]
[[package]]
name = "colored"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
dependencies = [
"lazy_static",
"windows-sys 0.48.0",
]
[[package]]
name = "core2"
version = "0.3.3"
@ -234,36 +243,6 @@ dependencies = [
"uuid",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dmsort"
version = "1.0.2"
@ -315,6 +294,16 @@ dependencies = [
"core2",
]
[[package]]
name = "fern"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee"
dependencies = [
"colored 1.9.4",
"log",
]
[[package]]
name = "flate2"
version = "1.0.29"
@ -435,17 +424,6 @@ dependencies = [
"slab",
]
[[package]]
name = "getrandom"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.28.1"
@ -586,16 +564,6 @@ version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags 2.5.0",
"libc",
]
[[package]]
name = "lock_api"
version = "0.4.11"
@ -665,7 +633,7 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfb67c6dd0fa9b00619c41c5700b6f92d5f418be49b45ddb9970fbd4569df3c8"
dependencies = [
"bitflags 1.3.2",
"bitflags",
]
[[package]]
@ -697,12 +665,6 @@ dependencies = [
"nom",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num_cpus"
version = "1.16.0"
@ -724,7 +686,7 @@ dependencies = [
[[package]]
name = "ok_macros"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"darling",
"proc-macro2",
@ -735,23 +697,23 @@ dependencies = [
[[package]]
name = "okstd"
version = "0.1.3"
version = "0.1.4"
dependencies = [
"anyhow",
"backtrace",
"base64",
"colored 2.1.0",
"crc16",
"fastvlq",
"fern",
"futures",
"hex",
"log",
"num_cpus",
"ok_macros",
"rustc-demangle",
"serde",
"serde_json",
"slog",
"slog-scope",
"slog-term",
"sourcemap",
"symbolic",
"termcolor",
@ -812,7 +774,7 @@ version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4e89a9f2f40b2389ba6da0814c8044bf942bece03dffa1514f84e3b525f4f9a"
dependencies = [
"bitflags 1.3.2",
"bitflags",
"elsa",
"maybe-owned",
"pdb",
@ -853,12 +815,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
@ -906,18 +862,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891"
dependencies = [
"getrandom",
"libredox",
"thiserror",
"bitflags",
]
[[package]]
@ -970,12 +915,6 @@ dependencies = [
"semver 0.9.0",
]
[[package]]
name = "rustversion"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
[[package]]
name = "ryu"
version = "1.0.17"
@ -1108,30 +1047,6 @@ version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06"
[[package]]
name = "slog-scope"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f95a4b4c3274cd2869549da82b57ccc930859bdbf5bcea0424bc5f140b3c786"
dependencies = [
"arc-swap",
"lazy_static",
"slog",
]
[[package]]
name = "slog-term"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6e022d0b998abfe5c3782c1f03551a596269450ccd677ea51c56f8b214610e8"
dependencies = [
"is-terminal",
"slog",
"term",
"thread_local",
"time",
]
[[package]]
name = "smallvec"
version = "1.13.2"
@ -1321,17 +1236,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.4.1"
@ -1361,47 +1265,6 @@ dependencies = [
"syn 2.0.63",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"num-conv",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View file

@ -1,11 +1,23 @@
[package]
name = "okstd"
version = "0.1.3"
version = "0.1.4"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
unstable = ["dep:symbolic", "dep:sourcemap"]
[dependencies]
symbolic = { version = "12.8.0", features = [
"common-serde",
"debuginfo-serde",
"demangle",
"symcache",
"debuginfo",
], optional = true }
sourcemap = { version = "8.0.1", optional = true }
anyhow = "1.0.81"
backtrace = { version = "0.3.71", features = ["serde", "serialize-serde"] }
base64 = "0.22.0"
@ -14,21 +26,14 @@ fastvlq = "1.1.1"
futures = "0.3.30"
hex = "0.4.3"
num_cpus = "1.16.0"
ok_macros = { version = "0.1.3", path = "ok_macros", registry = "oksoftware" }
ok_macros = { version = "0.1.4", path = "ok_macros", registry = "oksoftware" }
rustc-demangle = "0.1.23"
serde = "*"
serde_json = "*"
slog = "2.7.0"
slog-scope = "4.4.0"
slog-term = "2.9.1"
sourcemap = "8.0.1"
symbolic = { version = "12.8.0", features = [
"common-serde",
"debuginfo-serde",
"demangle",
"symcache",
"debuginfo",
] }
log = "0.4"
colored = "2"
fern = { version = "0.6", features = ["colored"] }
termcolor = "1.4.1"
tokio = { version = "1.37.0", features = ["full"] }
url = "2.5.0"

View file

@ -22,7 +22,7 @@ async fn main() {
something();
}
```
## Experimental Features
### `okstd::log`
```rust
#[okstd::log(debug)]
@ -31,3 +31,33 @@ fn something() {
println!("Hello, world!");
}
```
## Experimental Features under `unstable` feature flag
```bash
> [!CAUTION]
> Very unstable and will likely change in the future.
### `okstd::crashdump`
```rust
#[okstd::log(info)]
#[okstd::crashdump]
#[okstd::main]
async fn main() {
let a = 0;
let b = 1;
let c = b / a;
panic!("This is a panic");
}
```
will return a crashdump string like so
```text
SourceMap { file: Some("integration/src/panics.rs"), tokens: [], index: [], names: ["backtrace::backtrace::trace_unsynchronized", "backtrace::backtrace::trace", "okstd::notokpanic::panic_hook", "core::ops::function::Fn::call", "<alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call", "std::panicking::rust_panic_with_hook", "std::panicking::begin_panic_handler::{{closure}}", "std::sys_common::backtrace::__rust_end_short_backtrace", "rust_begin_unwind", "core::panicking::panic_fmt", "core::panicking::panic", "panics::old_main::{{closure}}", "tokio::runtime::park::CachedParkThread::block_on::{{closure}}", "tokio::runtime::park::CachedParkThread::block_on", "tokio::runtime::context::blocking::BlockingRegionGuard::block_on", "tokio::runtime::scheduler::multi_thread::MultiThread::block_on::{{closure}}", "tokio::runtime::context::runtime::enter_runtime", "tokio::runtime::scheduler::multi_thread::MultiThread::block_on", "tokio::runtime::runtime::Runtime::block_on", "<okstd::okasync::Runtimes as okstd::okasync::Runtime>::block_on", "panics::main", "core::ops::function::FnOnce::call_once", "std::sys_common::backtrace::__rust_begin_short_backtrace", "std::rt::lang_start::{{closure}}", "std::panicking::try::do_call", "std::panicking::try", "std::panic::catch_unwind", "std::rt::lang_start_internal::{{closure}}", "std::rt::lang_start_internal", "std::rt::lang_start", "main", "_start"], source_root: None, sources: [], sources_prefixed: None, sources_content: [], debug_id: None }
Filename: Ok("/scratch/cargo_target/debug/panics")
Crashdump URL: https://crashdu.mp/🐧/♔/aea3ab2067116e3327bb51dc3bed94cd0/g98qBgj9qBg80qBg7r2Ng7gmOg4nxOgrnxOgt9wOgnmxOg4gpBghhpBggnpBg2spBg7npBg9lpBgp9pBgjsqBgk9pBgwqqBgl+pBgxmpBg/upOg4mqBg4kqBg500Cgnl6Kg6yuDgilvOg500Cgnl6Kg6yuDgohvOgzkqBg9mpBgslpB?cGFuaWMgb2NjdXJyZWQ6IGF0dGVtcHQgdG8gZGl2aWRlIGJ5IHplcm8gYXQgaW50ZWdyYXRpb24vc3JjL3Bhbmljcy5yczoxMToxMw
```
[crashdu.mp/🐧/♔/aea3ab2067116e3327bb51dc3bed94cd0/g98qBgj9qBg80qBg7r2Ng7gmOg4nxOgrnxOgt9wOgnmxOg4gpBghhpBggnpBg2spBg7npBg9lpBgp9pBgjsqBgk9pBgwqqBgl+pBgxmpBg/upOg4mqBg4kqBg500Cgnl6Kg6yuDgilvOg500Cgnl6Kg6yuDgohvOgzkqBg9mpBgslpB?cGFuaWMgb2NjdXJyZWQ6IGF0dGVtcHQgdG8gZGl2aWRlIGJ5IHplcm8gYXQgaW50ZWdyYXRpb24vc3JjL3Bhbmljcy5yczoxMToxMw](https://crashdu.mp/🐧/♔/aea3ab2067116e3327bb51dc3bed94cd0/g98qBgj9qBg80qBg7r2Ng7gmOg4nxOgrnxOgt9wOgnmxOg4gpBghhpBggnpBg2spBg7npBg9lpBgp9pBgjsqBgk9pBgwqqBgl+pBgxmpBg/upOg4mqBg4kqBg500Cgnl6Kg6yuDgilvOg500Cgnl6Kg6yuDgohvOgzkqBg9mpBgslpB?cGFuaWMgb2NjdXJyZWQ6IGF0dGVtcHQgdG8gZGl2aWRlIGJ5IHplcm8gYXQgaW50ZWdyYXRpb24vc3JjL3Bhbmljcy5yczoxMToxMw)

View file

@ -6,4 +6,13 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
okstd = { version = "*", path = ".." }
okstd = { version = "*", path = "..", features = ["unstable"]}
[[bin]]
name = "log"
path = "src/main.rs"
[[bin]]
name = "panics"
path = "src/panics.rs"

View file

@ -5,8 +5,8 @@ async fn main() {
something();
}
#[okstd::log(debug)]
#[okstd::log(info)]
fn something() {
debug!("Hello, world!");
info!("Hello, world!");
println!("Hello, world!");
}

13
integration/src/panics.rs Normal file
View file

@ -0,0 +1,13 @@
use core::panic;
use okstd::prelude::*;
#[okstd::log(info)]
#[okstd::crashdump]
#[okstd::main]
async fn main() {
let a = 0;
let b = 1;
let _c = b / a;
panic!("This is a panic");
}

View file

@ -1,6 +1,6 @@
[package]
name = "ok_macros"
version = "0.1.3"
version = "0.1.4"
edition = "2021"

View file

@ -1,8 +1,6 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::parse::{ParseBuffer, ParseStream};
use syn::{parse_macro_input, punctuated::Punctuated, ItemFn};
use syn::{parse_quote, Attribute, Meta, Token};
pub fn transform_function(
args: proc_macro::TokenStream,
@ -58,14 +56,10 @@ pub fn transform_function(
let orig_ident = item_fn.sig.ident.clone();
// Rename the `test` function to `old_test`
let new_name = format!("__logging_{}", orig_ident.to_string());
let new_name = format!("__logging_{}", orig_ident);
let old_ident = syn::Ident::new(new_name.as_str(), item_fn.sig.ident.span());
item_fn.sig.ident = old_ident.clone();
let parsed = quote!(slog_o!());
if level == Level::Off {
return old_fn;
}
@ -74,24 +68,83 @@ pub fn transform_function(
let level_token = match level {
Level::Off => quote! {},
Level::Critical => quote! {slog::Level::Critical},
Level::Error => quote! {slog::Level::Error},
Level::Warning => quote! {slog::Level::Warning},
Level::Info => quote! {slog::Level::Info},
Level::Debug => quote! {slog::Level::Debug},
Level::Trace => quote! {slog::Level::Trace},
Level::Critical => quote! {LevelFilter::Critical},
Level::Error => quote! {LevelFilter::Error},
Level::Warning => quote! {LevelFilter::Warning},
Level::Info => quote! {LevelFilter::Info},
Level::Debug => quote! {LevelFilter::Debug},
Level::Trace => quote! {LevelFilter::Trace},
};
let body = &item_fn.block;
let result = quote! {
#[allow(unused_must_use, unreachable_code)]
#( #attrs )*
#asyncness fn #fn_name #generics(#inputs) #output
#where_clause {
setup_logging();
scope(&logger().new(o!()),
|| #body
)
setup_logging(#level_token);
return #body
}
};
TokenStream::from(result)
}
/// setup panic hook for crashdu.mp
/// similar to log, we just want to setup the panic hook
/// and keep the function as is
///
/// # Example
///
/// ```rust,notest
/// #[okstd::crashdump]
/// fn does_something() {
/// // do something
/// }
///```
/// to
/// ```rust,notest
/// fn does_something() {
/// setup_panic_hook();
/// // do something
/// }
/// ```
pub fn setup_panic_hook(
_args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let mut item_fn = parse_macro_input!(input as ItemFn);
let fn_name = &item_fn.clone().sig.ident;
let attrs: &Vec<syn::Attribute> = &item_fn.attrs;
let asyncness: &Option<syn::token::Async> = &item_fn.sig.asyncness;
let generics: &syn::Generics = &item_fn.sig.generics;
let inputs: &Punctuated<syn::FnArg, syn::token::Comma> = &item_fn.sig.inputs;
let output: &syn::ReturnType = &item_fn.sig.output;
let where_clause: &Option<syn::WhereClause> = &item_fn.sig.generics.where_clause;
let orig_ident = item_fn.sig.ident.clone();
// Rename the `test` function to `old_test`
let new_name = format!("__panic_hook_{}", orig_ident);
let old_ident = syn::Ident::new(new_name.as_str(), item_fn.sig.ident.span());
item_fn.sig.ident = old_ident.clone();
let body = &item_fn.block;
let result = quote! {
#[allow(unused_must_use)]
#( #attrs )*
#asyncness fn #fn_name #generics(#inputs) #output
#where_clause {
std::panic::set_hook(Box::new(panic_hook));
return #body
}
};

View file

@ -2,18 +2,10 @@
extern crate proc_macro;
extern crate syn;
#[macro_use(slog_o, slog_info, slog_log, slog_record, slog_record_static, slog_b, slog_kv)]
extern crate slog;
use darling::{Error, FromMeta};
use proc_macro::TokenStream;
use quote::{quote, ToTokens};
use quote::quote;
use syn::parse_quote;
use syn::punctuated::Punctuated;
use syn::{
parse_macro_input, spanned::Spanned, token, Expr, ExprAsync, ExprAwait, ExprBlock, ExprCall, ExprClosure,
ExprParen, FnArg, Ident, ItemFn, Meta, Pat, Result, ReturnType, Stmt, Type, TypePath,
};
use syn::{parse_macro_input, ItemFn};
mod func_transformer;
@ -33,8 +25,6 @@ pub fn main(_attr: TokenStream, item: TokenStream) -> TokenStream {
// Generate the new `main` function
let new_main = quote! {
fn main() {
set_hook(Box::new(panic_hook));
setup_logging();
let rt = Runtimes::setup_runtimes().unwrap();
rt.block_on(#old_main_ident())
}
@ -55,7 +45,7 @@ pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(item as ItemFn);
let orig_ident = input.sig.ident.clone();
// Rename the `test` function to `old_test`
let new_name = format!("old_test_{}", orig_ident.to_string());
let new_name = format!("old_test_{}", orig_ident);
let old_test_ident = syn::Ident::new(new_name.as_str(), input.sig.ident.span());
input.sig.ident = old_test_ident.clone();
@ -87,6 +77,10 @@ pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {
output.into()
}
#[proc_macro_attribute]
pub fn crashdump(args: TokenStream, input: TokenStream) -> TokenStream {
func_transformer::setup_panic_hook(args, input)
}
#[proc_macro_attribute]
pub fn log(args: TokenStream, input: TokenStream) -> TokenStream {

View file

@ -2,10 +2,12 @@
pub mod log;
pub mod okasync;
#[cfg(feature = "unstable")]
pub mod notokpanic;
mod e2e_tests;
extern crate slog;
extern crate fern;
pub mod prelude {
pub use crate::okasync::*;
@ -14,24 +16,24 @@ pub mod prelude {
pub use super::main;
// re-export the slog macros
pub use slog_scope::crit;
pub use slog_scope::debug;
pub use slog_scope::error;
pub use slog_scope::info;
pub use slog_scope::trace;
pub use slog_scope::warn;
pub use slog_scope::scope;
pub use slog_scope::logger;
pub use slog::OwnedKV;
pub use slog::o;
pub use fern::*;
pub use log::debug;
pub use log::error;
pub use log::info;
pub use log::trace;
pub use log::warn;
pub use slog_scope::set_global_logger;
pub use log::LevelFilter;
pub use std::panic::set_hook;
#[cfg(feature = "unstable")]
pub use crate::notokpanic::panic_hook;
}
pub use ok_macros::main;
pub use ok_macros::test;
pub use ok_macros::log;
#[cfg(feature = "unstable")]
pub use ok_macros::crashdump;

View file

@ -1,15 +1,13 @@
use std::{io::Write, ops::Add, path::PathBuf};
use colored::*;
use fern::colors::ColoredLevelConfig;
use std::{io, path::PathBuf};
use slog::{slog_o, Drain, Logger};
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};
// get module colour hashes the module name
// and attempts to return a uniqe color as far as ansi colors go
fn get_module_colour(module: &str) -> Color {
// get module color hashes the module name
// and attempts to return a unique color as far as ansi colors go
fn get_module_color(module: &str) -> colored::Color {
// crc16 is a good hash for this
let hash = crc16::State::<crc16::XMODEM>::calculate(module.as_bytes());
let hash = hash.add(5);
let hash = hash + 5;
match hash % 6 {
0 => Color::Red,
1 => Color::Green,
@ -21,57 +19,49 @@ fn get_module_colour(module: &str) -> Color {
}
}
pub fn setup_logging(level: log::LevelFilter) -> Result<(), fern::InitError> {
let colors = ColoredLevelConfig::new()
.error(fern::colors::Color::Red)
.warn(fern::colors::Color::Yellow)
.info(fern::colors::Color::Green)
.debug(fern::colors::Color::Blue)
.trace(fern::colors::Color::Cyan);
pub fn setup_logging() -> Logger {
let x = drain();
slog::Logger::root(x, slog_o!())
}
#[allow(dead_code)]
pub fn drain() -> slog::Fuse<slog_term::FullFormat<slog_term::PlainSyncDecorator<std::io::Stdout>>>
{
let plain = slog_term::PlainSyncDecorator::new(std::io::stdout());
let ff = slog_term::FullFormat::new(plain);
let x = ff
.use_custom_header_print(|_f, _t, r, _x| {
// print format is: dev.branch/{module} {level} {msg}
// module should be cleaned by :: -> /
// level should be colored use termcolor
let module = r.module().replace("::", "/");
let level = match r.level() {
slog::Level::Critical => termcolor::Color::Red,
slog::Level::Error => termcolor::Color::Red,
slog::Level::Warning => termcolor::Color::Yellow,
slog::Level::Info => termcolor::Color::Green,
slog::Level::Debug => termcolor::Color::Blue,
slog::Level::Trace => termcolor::Color::Cyan,
};
let location_buffer = PathBuf::from(r.location().file).canonicalize().unwrap();
fern::Dispatch::new()
.format(move |out, message, record| {
let module = record.target().replace("::", "/");
let module_color = get_module_color(&module);
let location_buffer = PathBuf::from(record.file().unwrap())
.canonicalize()
.unwrap_or(record.file().unwrap().into());
let loc = location_buffer.to_str().unwrap();
let bufwtr = BufferWriter::stderr(ColorChoice::Always);
let mut buffer = bufwtr.buffer();
let module_color = get_module_colour(&module);
buffer.set_color(ColorSpec::new().set_fg(Some(module_color)))?;
let _ = write!(buffer, "dev.branch/software/ok/{} ", module,);
buffer.reset()?;
buffer.set_color(
ColorSpec::new()
.set_dimmed(true)
.set_underline(true)
.set_fg(Some(Color::White)),
)?;
let _ = write!(buffer, "{}:{}", loc, r.location().line);
buffer.reset()?;
buffer.set_color(ColorSpec::new().set_fg(Some(level)).set_intense(true))?;
let _ = write!(buffer, " {}", r.level());
buffer.reset()?;
let _ = write!(buffer, " {}", r.msg());
let _ = bufwtr.print(&buffer);
std::result::Result::Ok(true)
out.finish(format_args!(
"{} {}:{} {} {}",
format!("{}/{}", "ok.software/", module).color(module_color),
loc,
record.line().unwrap(),
colors.color(record.level()),
message
))
})
.build()
.fuse();
x
.level(level)
.chain(io::stdout())
.apply()?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use log::info;
#[test]
fn test_logging() {
setup_logging(log::LevelFilter::Error).unwrap();
for var in std::env::vars() {
info!("{}={}", var.0, var.1);
}
}
}