generated from PlexSheep/baserepo
Compare commits
No commits in common. "ed0b363a99808f7c3aa38930fb5dcc7fe973074f" and "b374aa7e43143f0132b40fbdce64d89496607cec" have entirely different histories.
ed0b363a99
...
b374aa7e43
13 changed files with 23 additions and 483 deletions
|
@ -21,8 +21,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
rustup component add clippy
|
rustup component add clippy
|
||||||
- name: install python
|
|
||||||
run: apt update && apt install libpython3-dev -y
|
|
||||||
- name: config custom registry
|
- name: config custom registry
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.cargo/
|
mkdir -p ~/.cargo/
|
||||||
|
@ -38,8 +36,10 @@ jobs:
|
||||||
run: cargo clippy --fix --all-features --all-targets --workspace
|
run: cargo clippy --fix --all-features --all-targets --workspace
|
||||||
- name: cargo fmt
|
- name: cargo fmt
|
||||||
run: cargo fmt --all
|
run: cargo fmt --all
|
||||||
|
- name: install python
|
||||||
|
run: apt update && apt install libpython3-dev -y
|
||||||
- name: cargo test
|
- name: cargo test
|
||||||
run: cargo test --all-features --all-targets --workspace && cargo test --all-features --workspace --doc
|
run: cargo test --all-features --all-targets --workspace
|
||||||
- name: commit back to repository
|
- name: commit back to repository
|
||||||
uses: https://github.com/stefanzweifel/git-auto-commit-action@v5
|
uses: https://github.com/stefanzweifel/git-auto-commit-action@v5
|
||||||
with:
|
with:
|
||||||
|
|
10
.github/workflows/cargo.yaml
vendored
10
.github/workflows/cargo.yaml
vendored
|
@ -22,10 +22,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
rustup component add rustfmt
|
rustup component add rustfmt
|
||||||
rustup component add clippy
|
rustup component add clippy
|
||||||
- name: install python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
- name: config custom registry
|
- name: config custom registry
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.cargo/
|
mkdir -p ~/.cargo/
|
||||||
|
@ -41,8 +37,12 @@ jobs:
|
||||||
run: cargo clippy --fix --all-features --all-targets --workspace
|
run: cargo clippy --fix --all-features --all-targets --workspace
|
||||||
- name: cargo fmt
|
- name: cargo fmt
|
||||||
run: cargo fmt --all
|
run: cargo fmt --all
|
||||||
|
- name: install python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.11'
|
||||||
- name: cargo test
|
- name: cargo test
|
||||||
run: cargo test --all-features --all-targets --workspace && cargo test --all-features --workspace --doc
|
run: cargo test --all-features --all-targets --workspace
|
||||||
- name: commit back to repository
|
- name: commit back to repository
|
||||||
uses: stefanzweifel/git-auto-commit-action@v5
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -10,7 +10,7 @@ default-members = [".", "members/libpt-core"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
publish = true
|
publish = true
|
||||||
version = "0.5.0"
|
version = "0.4.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
authors = ["Christoph J. Scherr <software@cscherr.de>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -29,8 +29,8 @@ categories = [
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
thiserror = "1.0.56"
|
thiserror = "1.0.56"
|
||||||
libpt-core = { version = "0.4.0", path = "members/libpt-core" }
|
libpt-core = { version = "0.4.0", path = "members/libpt-core" }
|
||||||
libpt-bintols = { version = "0.5.0", path = "members/libpt-bintols" }
|
libpt-bintols = { version = "0.4.0", path = "members/libpt-bintols" }
|
||||||
libpt-log = { version = "0.4.2", path = "members/libpt-log" }
|
libpt-log = { version = "0.4.1", path = "members/libpt-log" }
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "libpt"
|
name = "libpt"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "libpt-bintols"
|
name = "libpt-bintols"
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
version = "0.5.0"
|
version = "0.4.0"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -25,4 +25,3 @@ pub const YOBI: u128 = 2u128.pow(80);
|
||||||
// use libpt_core;
|
// use libpt_core;
|
||||||
pub mod datalayout;
|
pub mod datalayout;
|
||||||
pub mod display;
|
pub mod display;
|
||||||
pub mod split;
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
//! # Split numbers into bits and bytes
|
|
||||||
//!
|
|
||||||
//! Sometimes, you need a large integer in the form of many bytes, so split into [u8].
|
|
||||||
//! Rust provides
|
|
||||||
|
|
||||||
/// Split unsigned integers into a [Vec] of [u8]s
|
|
||||||
///
|
|
||||||
/// Say you have the [u32] 1717 (binary: `00000000 00000000 00000110 10110101 `). This number would
|
|
||||||
/// be splitted to `vec![0b00000110, 0b10110101]`.
|
|
||||||
///
|
|
||||||
/// The 0 bytes of the numbers will be discarded (unless the number is 0, then the Vec contains a
|
|
||||||
/// single Null byte.) and the remaining parts of the numbers are inserted into a Vec as [u8].
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use libpt_bintols::split::*;
|
|
||||||
///
|
|
||||||
/// let x: u32 = 1717;
|
|
||||||
///
|
|
||||||
/// assert_eq!(unsigned_to_vec(x), vec![0b00000110, 0b10110101]);
|
|
||||||
/// ```
|
|
||||||
pub fn unsigned_to_vec<T>(num: T) -> Vec<u8>
|
|
||||||
where
|
|
||||||
u128: std::convert::From<T>,
|
|
||||||
{
|
|
||||||
let mut num: u128 = num.into();
|
|
||||||
if num == 0 {
|
|
||||||
return vec![0];
|
|
||||||
}
|
|
||||||
let mut buf: Vec<u8> = Vec::new();
|
|
||||||
while num > 0 {
|
|
||||||
buf.push(num as u8);
|
|
||||||
num >>= 8;
|
|
||||||
}
|
|
||||||
buf.reverse();
|
|
||||||
buf
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
use libpt_bintols::split::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn split_u128() {
|
|
||||||
let source = [
|
|
||||||
16,
|
|
||||||
255,
|
|
||||||
256,
|
|
||||||
0,
|
|
||||||
u128::MAX,
|
|
||||||
u64::MAX as u128,
|
|
||||||
u64::MAX as u128 + 1,
|
|
||||||
];
|
|
||||||
let correct = [
|
|
||||||
vec![16],
|
|
||||||
vec![255],
|
|
||||||
vec![1, 0],
|
|
||||||
vec![0],
|
|
||||||
vec![
|
|
||||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
||||||
],
|
|
||||||
vec![255, 255, 255, 255, 255, 255, 255, 255],
|
|
||||||
vec![1, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
||||||
];
|
|
||||||
for (i, n) in source.iter().enumerate() {
|
|
||||||
assert_eq!(unsigned_to_vec(*n), correct[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn split_u64() {
|
|
||||||
let source = [
|
|
||||||
16,
|
|
||||||
255,
|
|
||||||
256,
|
|
||||||
0,
|
|
||||||
u64::MAX,
|
|
||||||
u32::MAX as u64,
|
|
||||||
0b1_00000001,
|
|
||||||
0b10011011_10110101_11110000_00110011,
|
|
||||||
];
|
|
||||||
let correct = [
|
|
||||||
vec![16],
|
|
||||||
vec![255],
|
|
||||||
vec![1, 0],
|
|
||||||
vec![0],
|
|
||||||
vec![255, 255, 255, 255, 255, 255, 255, 255],
|
|
||||||
vec![255, 255, 255, 255],
|
|
||||||
vec![1, 1],
|
|
||||||
vec![0b10011011, 0b10110101, 0b11110000, 0b00110011],
|
|
||||||
];
|
|
||||||
for (i, n) in source.iter().enumerate() {
|
|
||||||
assert_eq!(unsigned_to_vec(*n), correct[i]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "libpt-log"
|
name = "libpt-log"
|
||||||
publish.workspace = true
|
publish.workspace = true
|
||||||
version = "0.4.2"
|
version = "0.4.1"
|
||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
authors.workspace = true
|
authors.workspace = true
|
||||||
license.workspace = true
|
license.workspace = true
|
||||||
|
|
|
@ -37,346 +37,20 @@ pub const DEFAULT_LOG_DIR: &str = "/dev/null";
|
||||||
|
|
||||||
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
static INITIALIZED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
/// Builder for a well configured [Logger]
|
/// ## Logger for [`pt`](../libpt/index.html)
|
||||||
///
|
///
|
||||||
/// This struct helps configure a global logger that can be used with either macros or methods, see
|
/// This struct exists mainly for the python module, so that we can use the same logger with both
|
||||||
/// [Logger].
|
/// python and rust.
|
||||||
///
|
|
||||||
/// ## Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use libpt_log::{Logger, info};
|
|
||||||
/// # fn main() {
|
|
||||||
/// Logger::builder()
|
|
||||||
/// .uptime(true)
|
|
||||||
/// .build();
|
|
||||||
/// info!("hello world");
|
|
||||||
/// # }
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
|
||||||
pub struct LoggerBuilder {
|
|
||||||
/// create and log to logfiles
|
|
||||||
log_to_file: bool,
|
|
||||||
/// logfiles would be created here
|
|
||||||
log_dir: PathBuf,
|
|
||||||
/// use ANSI control sequences
|
|
||||||
ansi: bool,
|
|
||||||
/// show which source file produces a log
|
|
||||||
display_filename: bool,
|
|
||||||
/// show the log level of the message
|
|
||||||
display_level: bool,
|
|
||||||
/// show target context
|
|
||||||
display_target: bool,
|
|
||||||
/// sets the maximum verbosity level.
|
|
||||||
///
|
|
||||||
/// For example, if set to [Error](Level::ERROR), logs at [Info](Level::INFO) will not be
|
|
||||||
/// printed. If set to [Debug](Level::DEBUG), logs at [Info](Level::INFO) will be printed.
|
|
||||||
max_level: Level,
|
|
||||||
/// show the id of the thread that created this message
|
|
||||||
display_thread_ids: bool,
|
|
||||||
/// show the name of the thread that created this message
|
|
||||||
display_thread_names: bool,
|
|
||||||
/// show which line in the source file produces a log
|
|
||||||
display_line_number: bool,
|
|
||||||
/// splits a log over multiple lines, looks like a python traceback
|
|
||||||
pretty: bool,
|
|
||||||
/// show when the log was created
|
|
||||||
show_time: bool,
|
|
||||||
/// show timestamps as uptime (duration since the logger was initialized)
|
|
||||||
uptime: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LoggerBuilder {
|
|
||||||
/// use the configured settings to build and initialize a new global [Logger]
|
|
||||||
///
|
|
||||||
/// This will build a functional [Logger]. You don't need to use the [Logger] struct, it's
|
|
||||||
/// better to use the macros:
|
|
||||||
///
|
|
||||||
/// * `error!`
|
|
||||||
/// * `warn!`
|
|
||||||
/// * `info!`
|
|
||||||
/// * `debug!`
|
|
||||||
/// * `trace!`
|
|
||||||
///
|
|
||||||
/// instead of the methods of the [Logger] struct. You can however use the [Logger] struct in
|
|
||||||
/// cases where usage of a macro is bad or you are somehow working with multiple loggers.
|
|
||||||
///
|
|
||||||
/// ## Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use libpt_log::{Logger, info};
|
|
||||||
/// # fn main() {
|
|
||||||
/// Logger::builder()
|
|
||||||
/// .uptime(true)
|
|
||||||
/// .build();
|
|
||||||
/// info!("hello world");
|
|
||||||
/// # }
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// This function will return an error if a global Logger was aready initialized. This module
|
|
||||||
/// uses the [tracing] crate for logging, so if a [tracing] logger is initialized elsewhere,
|
|
||||||
/// this method will error.
|
|
||||||
pub fn build(self) -> Result<Logger> {
|
|
||||||
// only init if no init has been performed yet
|
|
||||||
if INITIALIZED.load(Ordering::Relaxed) {
|
|
||||||
warn!("trying to reinitialize the logger, ignoring");
|
|
||||||
bail!(Error::Usage("logging is already initialized".to_string()));
|
|
||||||
}
|
|
||||||
let subscriber = tracing_subscriber::fmt::Subscriber::builder()
|
|
||||||
.with_level(self.display_level)
|
|
||||||
.with_max_level(self.max_level)
|
|
||||||
.with_ansi(self.ansi)
|
|
||||||
.with_target(self.display_target)
|
|
||||||
.with_file(self.display_filename)
|
|
||||||
.with_thread_ids(self.display_thread_ids)
|
|
||||||
.with_line_number(self.display_line_number)
|
|
||||||
.with_thread_names(self.display_thread_names)
|
|
||||||
.with_span_events(FmtSpan::FULL);
|
|
||||||
// I know this is hacky, but I couldn't get it any other way. I couldn't even find a
|
|
||||||
// project that could do it any other way. You can't apply one after another, because the
|
|
||||||
// type is changed every time. When using `Box<dyn Whatever>`, some methods complain about
|
|
||||||
// not being in trait bounds.
|
|
||||||
// TODO: somehow find a better solution for this
|
|
||||||
match (self.log_to_file, self.show_time, self.pretty, self.uptime) {
|
|
||||||
(true, true, true, true) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(self.log_dir))
|
|
||||||
.with_timer(time::uptime())
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, true, false) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(self.log_dir))
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, false, true, _) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(self.log_dir))
|
|
||||||
.without_time()
|
|
||||||
.pretty()
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, false, true) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(self.log_dir))
|
|
||||||
.with_timer(time::uptime())
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, true, false, false) => {
|
|
||||||
let subscriber = subscriber
|
|
||||||
.with_writer(new_file_appender(self.log_dir))
|
|
||||||
.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(true, false, false, _) => {
|
|
||||||
let file_appender = tracing_appender::rolling::daily(self.log_dir.clone(), "log");
|
|
||||||
let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
|
|
||||||
let subscriber = subscriber.with_writer(file_writer).without_time().finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, true, true) => {
|
|
||||||
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, true, false) => {
|
|
||||||
let subscriber = subscriber.pretty().with_timer(time::uptime()).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, false, true, _) => {
|
|
||||||
let subscriber = subscriber.without_time().pretty().finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, false, true) => {
|
|
||||||
let subscriber = subscriber.with_timer(time::uptime()).finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, true, false, false) => {
|
|
||||||
let subscriber = subscriber.finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
(false, false, false, _) => {
|
|
||||||
let subscriber = subscriber.without_time().finish();
|
|
||||||
tracing::subscriber::set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
INITIALIZED.store(true, Ordering::Relaxed);
|
|
||||||
Ok(Logger {})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// enable or disable logging to and creating of logfiles
|
|
||||||
pub fn log_to_file(mut self, log_to_file: bool) -> Self {
|
|
||||||
self.log_to_file = log_to_file;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// set a directory where logfiles would be created in
|
|
||||||
///
|
|
||||||
/// Enable or disable creation and logging to logfiles with [log_to_file](Self::log_to_file).
|
|
||||||
///
|
|
||||||
/// The default logdir is [DEFAULT_LOG_DIR].
|
|
||||||
pub fn log_dir(mut self, log_dir: PathBuf) -> Self {
|
|
||||||
self.log_dir = log_dir;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// enable or disable ANSI control sequences
|
|
||||||
///
|
|
||||||
/// Disabling ANSI control sequences might improve compatibility and readability when the logs
|
|
||||||
/// are displayed by a program that does not interpret them.
|
|
||||||
///
|
|
||||||
/// Keeping ANSI control sequences enabled has the disadvantage of added colors for the logs.
|
|
||||||
pub fn ansi(mut self, ansi: bool) -> Self {
|
|
||||||
self.ansi = ansi;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// when making a log, display the source file in which a log was crated in
|
|
||||||
pub fn display_filename(mut self, display_filename: bool) -> Self {
|
|
||||||
self.display_filename = display_filename;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// when making a log, display the log level of the message
|
|
||||||
pub fn display_level(mut self, display_level: bool) -> Self {
|
|
||||||
self.display_level = display_level;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show target context
|
|
||||||
pub fn display_target(mut self, display_target: bool) -> Self {
|
|
||||||
self.display_target = display_target;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// set the maximum verbosity level.
|
|
||||||
pub fn max_level(mut self, max_level: Level) -> Self {
|
|
||||||
self.max_level = max_level;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show the id of the thread that created this message
|
|
||||||
pub fn display_thread_ids(mut self, display_thread_ids: bool) -> Self {
|
|
||||||
self.display_thread_ids = display_thread_ids;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show the name of the thread that created this message
|
|
||||||
pub fn display_thread_names(mut self, display_thread_names: bool) -> Self {
|
|
||||||
self.display_thread_names = display_thread_names;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show which line in the source file produces a log
|
|
||||||
pub fn display_line_number(mut self, display_line_number: bool) -> Self {
|
|
||||||
self.display_line_number = display_line_number;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// splits a log over multiple lines, looks like a python traceback
|
|
||||||
pub fn pretty(mut self, pretty: bool) -> Self {
|
|
||||||
self.pretty = pretty;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show a timestamp describing when the log was created
|
|
||||||
pub fn show_time(mut self, show_time: bool) -> Self {
|
|
||||||
self.show_time = show_time;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// show timestamps as uptime (duration since the logger was initialized)
|
|
||||||
pub fn uptime(mut self, uptime: bool) -> Self {
|
|
||||||
self.uptime = uptime;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for LoggerBuilder {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
log_to_file: false,
|
|
||||||
log_dir: PathBuf::from(DEFAULT_LOG_DIR),
|
|
||||||
ansi: true,
|
|
||||||
display_filename: false,
|
|
||||||
display_level: true,
|
|
||||||
display_target: false,
|
|
||||||
max_level: DEFAULT_LOG_LEVEL,
|
|
||||||
display_thread_ids: false,
|
|
||||||
display_thread_names: false,
|
|
||||||
display_line_number: false,
|
|
||||||
pretty: false,
|
|
||||||
show_time: true,
|
|
||||||
uptime: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ## Logger for [`pt`](libpt)
|
|
||||||
///
|
|
||||||
/// A logger is generally a functionality that let's you write information from your library or
|
|
||||||
/// application in a more structured manner than if you just wrote all information to `stdout` or
|
|
||||||
/// `stderr` with the likes of `println!` or `eprintln!`.
|
|
||||||
///
|
|
||||||
/// It offers writing to multiple targets, such as both the terminal and a log file, and allows
|
|
||||||
/// users to choose the verbosity of the information that gets printed by selecting a
|
|
||||||
/// [Loglevel](Level).
|
|
||||||
///
|
|
||||||
/// ## Levels
|
|
||||||
///
|
|
||||||
/// TODO: add levels desc and ascii art
|
|
||||||
///
|
|
||||||
/// ## Usage
|
|
||||||
///
|
|
||||||
/// You don't need to use the [Logger] struct, it's better to use the macros instead:
|
|
||||||
///
|
|
||||||
/// * `error!`
|
|
||||||
/// * `warn!`
|
|
||||||
/// * `info!`
|
|
||||||
/// * `debug!`
|
|
||||||
/// * `trace!`
|
|
||||||
///
|
|
||||||
/// You can however use the [Logger] struct in cases where usage of a macro is bad or
|
|
||||||
/// you are somehow working with multiple loggers. The macros offer additional functionalities,
|
|
||||||
/// suck as full `format!` support and context, see [`tracing`], which we use as backend.
|
|
||||||
///
|
|
||||||
/// ## Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use libpt_log::{Logger, info};
|
|
||||||
/// # fn main() {
|
|
||||||
/// Logger::builder()
|
|
||||||
/// .uptime(true)
|
|
||||||
/// .build();
|
|
||||||
/// info!("hello world");
|
|
||||||
/// # }
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
pub struct Logger;
|
pub struct Logger;
|
||||||
|
|
||||||
/// ## Main implementation
|
/// ## Main implementation
|
||||||
impl Logger {
|
impl Logger {
|
||||||
/// Get a new [LoggerBuilder]
|
|
||||||
pub fn builder() -> LoggerBuilder {
|
|
||||||
LoggerBuilder::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ## initializes the logger
|
/// ## initializes the logger
|
||||||
///
|
///
|
||||||
/// Will enable the logger to be used.
|
/// Will enable the logger to be used.
|
||||||
///
|
///
|
||||||
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
||||||
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
|
|
||||||
pub fn build(log_dir: Option<PathBuf>, max_level: Option<Level>, uptime: bool) -> Result<Self> {
|
pub fn build(log_dir: Option<PathBuf>, max_level: Option<Level>, uptime: bool) -> Result<Self> {
|
||||||
#[allow(deprecated)]
|
|
||||||
Self::build_customized(
|
Self::build_customized(
|
||||||
log_dir.is_some(),
|
log_dir.is_some(),
|
||||||
log_dir.unwrap_or(PathBuf::from(DEFAULT_LOG_DIR)),
|
log_dir.unwrap_or(PathBuf::from(DEFAULT_LOG_DIR)),
|
||||||
|
@ -400,9 +74,7 @@ impl Logger {
|
||||||
/// useful in cases with only one sender to the logging framework.
|
/// useful in cases with only one sender to the logging framework.
|
||||||
///
|
///
|
||||||
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
/// Assumes some defaults, use [`init_customized`](Self::init_customized) for more control
|
||||||
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
|
|
||||||
pub fn build_mini(max_level: Option<Level>) -> Result<Self> {
|
pub fn build_mini(max_level: Option<Level>) -> Result<Self> {
|
||||||
#[allow(deprecated)]
|
|
||||||
Self::build_customized(
|
Self::build_customized(
|
||||||
false,
|
false,
|
||||||
PathBuf::from(DEFAULT_LOG_DIR),
|
PathBuf::from(DEFAULT_LOG_DIR),
|
||||||
|
@ -420,11 +92,11 @@ impl Logger {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: make the args a struct for easy access
|
||||||
|
//
|
||||||
/// ## initializes the logger
|
/// ## initializes the logger
|
||||||
///
|
///
|
||||||
/// Will enable the logger to be used.
|
/// Will enable the logger to be used.
|
||||||
#[deprecated(since = "0.4.1", note = "use Logger::builder() instead")]
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn build_customized(
|
pub fn build_customized(
|
||||||
log_to_file: bool,
|
log_to_file: bool,
|
||||||
log_dir: PathBuf,
|
log_dir: PathBuf,
|
||||||
|
@ -578,14 +250,6 @@ impl fmt::Debug for Logger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Logger {
|
|
||||||
fn default() -> Self {
|
|
||||||
LoggerBuilder::default()
|
|
||||||
.build()
|
|
||||||
.expect("building a Logger failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_file_appender(log_dir: PathBuf) -> NonBlocking {
|
fn new_file_appender(log_dir: PathBuf) -> NonBlocking {
|
||||||
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
|
let file_appender = tracing_appender::rolling::daily(log_dir.clone(), "log");
|
||||||
tracing_appender::non_blocking(file_appender).0
|
tracing_appender::non_blocking(file_appender).0
|
||||||
|
|
|
@ -19,7 +19,7 @@ name = "libpt"
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libpt = { version = "0.5.0", path = "../.." }
|
libpt = { version = "0.4.2", path = "../.." }
|
||||||
pyo3 = { version = "0.19.0", features = ["full"] }
|
pyo3 = { version = "0.19.0", features = ["full"] }
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
|
|
||||||
|
|
|
@ -2,30 +2,11 @@ use pyo3::prelude::*;
|
||||||
|
|
||||||
use libpt::bintols as origin;
|
use libpt::bintols as origin;
|
||||||
|
|
||||||
mod split {
|
|
||||||
use libpt::bintols::split as origin;
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
#[pyfunction]
|
|
||||||
pub fn split_int(data: u128) -> Vec<u8> {
|
|
||||||
origin::unsigned_to_vec(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// implement a python module in Rust
|
|
||||||
pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
|
|
||||||
let module = PyModule::new(py, "split")?;
|
|
||||||
|
|
||||||
module.add_function(wrap_pyfunction!(split_int, module)?)?;
|
|
||||||
|
|
||||||
parent.add_submodule(module)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod display {
|
mod display {
|
||||||
use libpt::bintols::display as origin;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
|
use libpt::bintols::display as origin;
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
pub fn bytes_to_bin(data: &[u8]) -> String {
|
pub fn bytes_to_bin(data: &[u8]) -> String {
|
||||||
origin::bytes_to_bin(data)
|
origin::bytes_to_bin(data)
|
||||||
|
@ -69,7 +50,6 @@ pub fn submodule(py: Python, parent: &PyModule) -> PyResult<()> {
|
||||||
module.add("YOBI", origin::YOBI)?;
|
module.add("YOBI", origin::YOBI)?;
|
||||||
|
|
||||||
display::submodule(py, module)?;
|
display::submodule(py, module)?;
|
||||||
split::submodule(py, module)?;
|
|
||||||
|
|
||||||
parent.add_submodule(module)?;
|
parent.add_submodule(module)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -47,17 +47,7 @@ impl Logger {
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
// concert our wrapper type
|
// concert our wrapper type
|
||||||
let max_level = max_level.map(origin::Level::from);
|
let max_level = max_level.map(origin::Level::from);
|
||||||
let mut builder = origin::Logger::builder();
|
Ok(origin::Logger::build(log_dir, max_level, uptime.unwrap_or(false))?.into())
|
||||||
if log_dir.is_some() {
|
|
||||||
builder = builder.log_dir(log_dir.unwrap());
|
|
||||||
}
|
|
||||||
if max_level.is_some() {
|
|
||||||
builder = builder.max_level(max_level.unwrap());
|
|
||||||
}
|
|
||||||
if uptime.is_some() {
|
|
||||||
builder = builder.uptime(uptime.unwrap());
|
|
||||||
}
|
|
||||||
Ok(builder.build()?.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## logging at [`Level::ERROR`]
|
/// ## logging at [`Level::ERROR`]
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//!
|
//!
|
||||||
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
//! `pt` is a project consisting of multiple smaller crates, all bundled together in this
|
||||||
//! "main crate". Most crates will only show up if you activate their feature.
|
//! "main crate". Most crates will only show up if you activate their feature.
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
|
||||||
#[cfg(feature = "bintols")]
|
#[cfg(feature = "bintols")]
|
||||||
pub use libpt_bintols as bintols;
|
pub use libpt_bintols as bintols;
|
||||||
#[cfg(feature = "core")]
|
#[cfg(feature = "core")]
|
||||||
|
|
Reference in a new issue