feat: wip
This commit is contained in:
parent
29c5832ed0
commit
b3a0187c84
64
.gitignore
vendored
64
.gitignore
vendored
@ -45,3 +45,67 @@ Thumbs.db
|
||||
|
||||
.nx/cache
|
||||
.nx/workspace-data
|
||||
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/yarn,rust,rust-analyzer,visualstudiocode
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=yarn,rust,rust-analyzer,visualstudiocode
|
||||
|
||||
### Rust ###
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
### rust-analyzer ###
|
||||
# Can be generated by other build systems other than cargo (ex: bazelbuild/rust_rules)
|
||||
rust-project.json
|
||||
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
### yarn ###
|
||||
# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
|
||||
|
||||
.yarn/*
|
||||
!.yarn/releases
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
# if you are NOT using Zero-installs, then:
|
||||
# comment the following lines
|
||||
!.yarn/cache
|
||||
|
||||
# and uncomment the following lines
|
||||
# .pnp.*
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/yarn,rust,rust-analyzer,visualstudiocode
|
||||
*.node
|
25
.vscode/extensions.json
vendored
25
.vscode/extensions.json
vendored
@ -1,7 +1,26 @@
|
||||
{
|
||||
"recommendations": [
|
||||
|
||||
"nrwl.angular-console",
|
||||
"esbenp.prettier-vscode"
|
||||
"esbenp.prettier-vscode",
|
||||
"rust-lang.rust-analyzer",
|
||||
"github.copilot",
|
||||
"mitchdenny.ecdc",
|
||||
"aaron-bond.better-comments",
|
||||
"bierner.markdown-mermaid",
|
||||
"hristian-kohler.path-intellisense",
|
||||
"helixquar.randomeverything",
|
||||
"shardulm94.trailing-spaces",
|
||||
"tamasfe.even-better-toml",
|
||||
"edwinkofler.vscode-hyperupcall-pack-markdown",
|
||||
"proxzima.sweetdracula",
|
||||
"wdhongtw.gpg-indicator",
|
||||
"vadimcn.vscode-lldb",
|
||||
"naumovs.color-highlight",
|
||||
"formulahendry.auto-rename-tag",
|
||||
"PKief.material-icon-theme",
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"streetsidesoftware.code-spell-checker-french",
|
||||
"usernamehw.errorlens",
|
||||
"eamodio.gitlens",
|
||||
"oderwat.indent-rainbow"
|
||||
]
|
||||
}
|
||||
|
13
.vscode/settings.json
vendored
Normal file
13
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.fontFamily": "'FiraCode Nerd Font', 'FiraCode NF','Droid Sans Mono', 'monospace', monospace",
|
||||
"editor.fontLigatures": true,
|
||||
"rust-analyzer.linkedProjects": ["./Cargo.toml"],
|
||||
"editor.tabSize": 2,
|
||||
"editor.detectIndentation": false,
|
||||
"workbench.preferredDarkColorTheme": "Sweet Dracula",
|
||||
"workbench.iconTheme": "material-icon-theme",
|
||||
"cSpell.language": "en,fr",
|
||||
"gitlens.plusFeatures.enabled": false,
|
||||
"editor.guides.bracketPairs": true,
|
||||
}
|
909
Cargo.lock
generated
909
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
19
Cargo.toml
@ -1,13 +1,18 @@
|
||||
|
||||
[workspace]
|
||||
resolver = '2'
|
||||
members = [
|
||||
'apps/bot',
|
||||
]
|
||||
members = ['apps/bot', 'libs/tool_tracing']
|
||||
|
||||
[workspace.dependencies]
|
||||
poise = '0.6.1'
|
||||
tokio = { version = '1.45.0', features = [
|
||||
'macros',
|
||||
'rt-multi-thread',
|
||||
'io-std',
|
||||
] }
|
||||
serde = '1.0'
|
||||
tracing = '0.1'
|
||||
serde_json = "1.0"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
[workspace.dependencies]
|
||||
poise = "0.6.1"
|
||||
tokio = {version = "1.45.0", features = ["rt-multi-thread"]}
|
||||
|
@ -7,5 +7,7 @@ edition = "2021"
|
||||
[dependencies]
|
||||
poise = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
tool_tracing = { path = "../../libs/tool_tracing" }
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
28
apps/bot/src/config.rs
Normal file
28
apps/bot/src/config.rs
Normal file
@ -0,0 +1,28 @@
|
||||
use poise::serenity_prelude::prelude::TypeMapKey;
|
||||
use serde::Deserialize;
|
||||
use tool_tracing::tracing_kind::Tracing;
|
||||
|
||||
pub struct ConfigGlobal;
|
||||
|
||||
impl TypeMapKey for ConfigGlobal {
|
||||
type Value = Config;
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
pub bot_name: String,
|
||||
pub env: String,
|
||||
pub port: u16,
|
||||
pub token: String,
|
||||
pub prefix: String,
|
||||
pub tracing: Vec<Tracing>,
|
||||
}
|
||||
|
||||
// Clickhouse https://github.com/ranger-finance/clickhouse-pool/blob/master/examples/simple-clickhouse/src/main.rs
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct PersistenceConfig {
|
||||
pub url: String,
|
||||
pub user: String,
|
||||
pub password: String,
|
||||
pub database: String,
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use poise::serenity_prelude as serenity;
|
||||
|
||||
pub mod config;
|
||||
pub mod dotenv;
|
||||
|
||||
struct Data {} // User data, which is stored and accessible in all command invocations
|
||||
@ -42,4 +43,4 @@ async fn main() {
|
||||
.framework(framework)
|
||||
.await;
|
||||
client.unwrap().start().await.unwrap();
|
||||
}
|
||||
}
|
||||
|
30
libs/tool_tracing/Cargo.toml
Normal file
30
libs/tool_tracing/Cargo.toml
Normal file
@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "tool_tracing"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_repr = "0.1"
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { version = "0.3", features = [
|
||||
"registry",
|
||||
"env-filter",
|
||||
"time",
|
||||
] }
|
||||
time = "0.3"
|
||||
tracing-bunyan-formatter = "0.3"
|
||||
opentelemetry = "0.29"
|
||||
opentelemetry_sdk = { version = "0.29", features = ["rt-tokio"] }
|
||||
opentelemetry-otlp = { version = "0.29", features = ["grpc-tonic"] }
|
||||
tracing-opentelemetry = "0.30"
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tonic = { version = "0.12" }
|
||||
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = [
|
||||
'cfg(coverage,coverage_nightly)',
|
||||
] }
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
43
libs/tool_tracing/project.json
Normal file
43
libs/tool_tracing/project.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "tool_tracing",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "library",
|
||||
"sourceRoot": "libs/tool_tracing/src",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@monodon/rust:check",
|
||||
"outputs": [
|
||||
"{options.target-dir}"
|
||||
],
|
||||
"options": {
|
||||
"target-dir": "dist/target/tool_tracing"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"cache": true,
|
||||
"executor": "@monodon/rust:test",
|
||||
"outputs": [
|
||||
"{options.target-dir}"
|
||||
],
|
||||
"options": {
|
||||
"target-dir": "dist/target/tool_tracing"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"release": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"cache": true,
|
||||
"executor": "@monodon/rust:lint",
|
||||
"outputs": [
|
||||
"{options.target-dir}"
|
||||
],
|
||||
"options": {
|
||||
"target-dir": "dist/target/tool_tracing"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
160
libs/tool_tracing/src/init.rs
Normal file
160
libs/tool_tracing/src/init.rs
Normal file
@ -0,0 +1,160 @@
|
||||
#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
|
||||
use super::tracing_kind::{Tracing, TracingKind};
|
||||
use opentelemetry::trace::TracerProvider;
|
||||
use opentelemetry::KeyValue;
|
||||
use opentelemetry_otlp::{WithExportConfig, WithTonicConfig};
|
||||
use opentelemetry_sdk::trace;
|
||||
use opentelemetry_sdk::Resource;
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
use std::{fs::File, sync::Arc, vec};
|
||||
use time::format_description;
|
||||
use tonic::metadata::{MetadataMap, MetadataValue};
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing::subscriber;
|
||||
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
|
||||
use tracing_subscriber::filter::Directive;
|
||||
use tracing_subscriber::fmt::time::UtcTime;
|
||||
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
|
||||
use tracing_subscriber::{fmt, EnvFilter, Layer, Registry};
|
||||
|
||||
#[cfg_attr(coverage_nightly, coverage(off))]
|
||||
pub fn init_tracing(tracing_config: Vec<Tracing>, name: String) {
|
||||
let mut layers = vec![];
|
||||
for config in tracing_config {
|
||||
match config.kind {
|
||||
TracingKind::File => {
|
||||
let file = File::options()
|
||||
.create(true)
|
||||
.truncate(false)
|
||||
.append(true)
|
||||
.open("trace.log")
|
||||
.expect("Failed to create trace.log");
|
||||
let formating_layer =
|
||||
BunyanFormattingLayer::new(name.clone(), Arc::new(file)).boxed();
|
||||
layers.push(JsonStorageLayer.boxed());
|
||||
layers.push(formating_layer);
|
||||
}
|
||||
TracingKind::Console => {
|
||||
let time_format = format_description::parse("[hour]:[minute]:[second]")
|
||||
.expect("format string should be valid!");
|
||||
let timer = UtcTime::new(time_format);
|
||||
let env_filter = EnvFilter::builder()
|
||||
.with_default_directive(LevelFilter::from(config.level).into())
|
||||
.from_env()
|
||||
.unwrap()
|
||||
.add_directive("serenity=error".parse().unwrap());
|
||||
let terminal_out = fmt::layer()
|
||||
.with_thread_names(true)
|
||||
.with_timer(timer)
|
||||
.with_target(false)
|
||||
.with_filter(env_filter)
|
||||
.boxed();
|
||||
layers.push(terminal_out);
|
||||
}
|
||||
TracingKind::Otel => {
|
||||
let endpoint = match config.additional.get("endpoint") {
|
||||
Some(endpoint) => endpoint.to_string(),
|
||||
None => "http://localhost:4317".to_string(),
|
||||
};
|
||||
let endpoint_from_env = env::var(format!(
|
||||
"{}_OTEL_EXPORTER_OTLP_ENDPOINT",
|
||||
config.name.to_uppercase()
|
||||
))
|
||||
.unwrap_or(endpoint);
|
||||
let pod_name =
|
||||
std::env::var("POD_NAME").unwrap_or_else(|_| "not_a_pod".to_string());
|
||||
println!(
|
||||
"Connecting to endpoint: {} with ENV {}_OTEL_EXPORTER_OTLP_ENDPOINT",
|
||||
endpoint_from_env.clone(),
|
||||
config.name.to_uppercase()
|
||||
);
|
||||
|
||||
let mut metadata = MetadataMap::new();
|
||||
|
||||
metadata.insert(
|
||||
"service.name",
|
||||
MetadataValue::from_str(&name.clone()).unwrap(),
|
||||
);
|
||||
metadata.insert("service.pod", MetadataValue::from_str(&pod_name).unwrap());
|
||||
|
||||
let exporter = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.with_endpoint(endpoint_from_env)
|
||||
.with_metadata(metadata)
|
||||
.build()
|
||||
.expect("Failed to build exporter");
|
||||
|
||||
let trace_provider = trace::SdkTracerProvider::builder()
|
||||
.with_batch_exporter(exporter)
|
||||
.with_resource(
|
||||
Resource::builder()
|
||||
.with_service_name(name.clone())
|
||||
.with_attribute(KeyValue::new("service.pod", pod_name.clone()))
|
||||
.build(),
|
||||
)
|
||||
.build();
|
||||
|
||||
let env_filter = EnvFilter::builder()
|
||||
.with_default_directive(LevelFilter::from(config.level).into())
|
||||
.from_env()
|
||||
.unwrap()
|
||||
.add_directive(Directive::from_str("serenity=error").unwrap());
|
||||
|
||||
let telemetry = tracing_opentelemetry::layer()
|
||||
.with_tracer(trace_provider.tracer(name.clone()))
|
||||
.with_filter(env_filter);
|
||||
layers.push(telemetry.boxed());
|
||||
}
|
||||
}
|
||||
}
|
||||
subscriber::set_global_default(Registry::default().with(layers))
|
||||
.expect("setting default subscriber failed");
|
||||
}
|
||||
|
||||
#[cfg_attr(coverage_nightly, coverage(off))]
|
||||
pub fn stop_tracing(tracing_config: Vec<Tracing>, _name: String) {
|
||||
if tracing_config.iter().any(|x| x.kind == TracingKind::Otel) {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::level::VerboseLevel;
|
||||
|
||||
use super::*;
|
||||
use std::fs::remove_file;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_init_tracing() {
|
||||
let mut tracing_config = vec![
|
||||
Tracing {
|
||||
kind: TracingKind::File,
|
||||
level: VerboseLevel::DEBUG,
|
||||
additional: Default::default(),
|
||||
name: "test1".to_string(),
|
||||
},
|
||||
Tracing {
|
||||
kind: TracingKind::Console,
|
||||
level: VerboseLevel::INFO,
|
||||
additional: Default::default(),
|
||||
name: "test2".to_string(),
|
||||
},
|
||||
Tracing {
|
||||
kind: TracingKind::Otel,
|
||||
level: VerboseLevel::DEBUG,
|
||||
additional: Default::default(),
|
||||
name: "test3".to_string(),
|
||||
},
|
||||
];
|
||||
tracing_config[2]
|
||||
.additional
|
||||
.insert("endpoint".to_string(), "http://localhost:4317".to_string());
|
||||
init_tracing(tracing_config.clone(), "test".to_string());
|
||||
tracing::info!("test part of test_init_tracing");
|
||||
tracing::error!("test part of test_init_tracing");
|
||||
tokio::spawn(async {
|
||||
stop_tracing(tracing_config, "test".to_string());
|
||||
});
|
||||
remove_file("trace.log").unwrap();
|
||||
}
|
||||
}
|
149
libs/tool_tracing/src/level.rs
Normal file
149
libs/tool_tracing/src/level.rs
Normal file
@ -0,0 +1,149 @@
|
||||
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||
use std::fmt::{Debug, Display};
|
||||
use tracing::Level;
|
||||
|
||||
#[derive(Serialize_repr, Deserialize_repr, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[repr(u8)]
|
||||
pub enum VerboseLevel {
|
||||
ERROR = 4,
|
||||
WARN = 3,
|
||||
INFO = 2,
|
||||
DEBUG = 1,
|
||||
TRACE = 0,
|
||||
}
|
||||
|
||||
impl From<VerboseLevel> for Level {
|
||||
fn from(level: VerboseLevel) -> Self {
|
||||
match level {
|
||||
VerboseLevel::ERROR => Level::ERROR,
|
||||
VerboseLevel::WARN => Level::WARN,
|
||||
VerboseLevel::INFO => Level::INFO,
|
||||
VerboseLevel::DEBUG => Level::DEBUG,
|
||||
VerboseLevel::TRACE => Level::TRACE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VerboseLevel> for tracing_subscriber::filter::LevelFilter {
|
||||
fn from(level: VerboseLevel) -> Self {
|
||||
match level {
|
||||
VerboseLevel::ERROR => tracing_subscriber::filter::LevelFilter::ERROR,
|
||||
VerboseLevel::WARN => tracing_subscriber::filter::LevelFilter::WARN,
|
||||
VerboseLevel::INFO => tracing_subscriber::filter::LevelFilter::INFO,
|
||||
VerboseLevel::DEBUG => tracing_subscriber::filter::LevelFilter::DEBUG,
|
||||
VerboseLevel::TRACE => tracing_subscriber::filter::LevelFilter::TRACE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for VerboseLevel {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ERROR => write!(f, "ERROR"),
|
||||
Self::WARN => write!(f, "WARN"),
|
||||
Self::INFO => write!(f, "INFO"),
|
||||
Self::DEBUG => write!(f, "DEBUG"),
|
||||
Self::TRACE => write!(f, "TRACE"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for VerboseLevel {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::ERROR => write!(f, "ERROR"),
|
||||
Self::WARN => write!(f, "WARN"),
|
||||
Self::INFO => write!(f, "INFO"),
|
||||
Self::DEBUG => write!(f, "DEBUG"),
|
||||
Self::TRACE => write!(f, "TRACE"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_verbose_level() {
|
||||
let level = VerboseLevel::ERROR;
|
||||
let serialized = serde_json::to_string(&level).unwrap();
|
||||
let deserialized: VerboseLevel = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(level, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verbose_level_conversion() {
|
||||
let level = VerboseLevel::ERROR;
|
||||
let tracing_level: Level = level.into();
|
||||
let level_filter: tracing_subscriber::filter::LevelFilter = level.into();
|
||||
|
||||
assert_eq!(tracing_level, Level::ERROR);
|
||||
assert_eq!(level_filter, tracing_subscriber::filter::LevelFilter::ERROR);
|
||||
|
||||
let level = VerboseLevel::WARN;
|
||||
let tracing_level: Level = level.into();
|
||||
let level_filter: tracing_subscriber::filter::LevelFilter = level.into();
|
||||
|
||||
assert_eq!(tracing_level, Level::WARN);
|
||||
assert_eq!(level_filter, tracing_subscriber::filter::LevelFilter::WARN);
|
||||
|
||||
let level = VerboseLevel::INFO;
|
||||
let tracing_level: Level = level.into();
|
||||
let level_filter: tracing_subscriber::filter::LevelFilter = level.into();
|
||||
|
||||
assert_eq!(tracing_level, Level::INFO);
|
||||
assert_eq!(level_filter, tracing_subscriber::filter::LevelFilter::INFO);
|
||||
|
||||
let level = VerboseLevel::DEBUG;
|
||||
let tracing_level: Level = level.into();
|
||||
let level_filter: tracing_subscriber::filter::LevelFilter = level.into();
|
||||
|
||||
assert_eq!(tracing_level, Level::DEBUG);
|
||||
assert_eq!(level_filter, tracing_subscriber::filter::LevelFilter::DEBUG);
|
||||
|
||||
let level = VerboseLevel::TRACE;
|
||||
let tracing_level: Level = level.into();
|
||||
let level_filter: tracing_subscriber::filter::LevelFilter = level.into();
|
||||
|
||||
assert_eq!(tracing_level, Level::TRACE);
|
||||
assert_eq!(level_filter, tracing_subscriber::filter::LevelFilter::TRACE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verbose_level_debug() {
|
||||
let level = VerboseLevel::ERROR;
|
||||
assert_eq!(format!("{:?}", level), "ERROR");
|
||||
|
||||
let level = VerboseLevel::WARN;
|
||||
assert_eq!(format!("{:?}", level), "WARN");
|
||||
|
||||
let level = VerboseLevel::INFO;
|
||||
assert_eq!(format!("{:?}", level), "INFO");
|
||||
|
||||
let level = VerboseLevel::DEBUG;
|
||||
assert_eq!(format!("{:?}", level), "DEBUG");
|
||||
|
||||
let level = VerboseLevel::TRACE;
|
||||
assert_eq!(format!("{:?}", level), "TRACE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verbose_level_display() {
|
||||
let level = VerboseLevel::ERROR;
|
||||
assert_eq!(format!("{}", level), "ERROR");
|
||||
|
||||
let level = VerboseLevel::WARN;
|
||||
assert_eq!(format!("{}", level), "WARN");
|
||||
|
||||
let level = VerboseLevel::INFO;
|
||||
assert_eq!(format!("{}", level), "INFO");
|
||||
|
||||
let level = VerboseLevel::DEBUG;
|
||||
assert_eq!(format!("{}", level), "DEBUG");
|
||||
|
||||
let level = VerboseLevel::TRACE;
|
||||
assert_eq!(format!("{}", level), "TRACE");
|
||||
}
|
||||
}
|
3
libs/tool_tracing/src/lib.rs
Normal file
3
libs/tool_tracing/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod init;
|
||||
pub mod level;
|
||||
pub mod tracing_kind;
|
56
libs/tool_tracing/src/tracing_kind.rs
Normal file
56
libs/tool_tracing/src/tracing_kind.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::level::VerboseLevel;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub enum TracingKind {
|
||||
File,
|
||||
Console,
|
||||
Otel,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||
pub struct Tracing {
|
||||
pub kind: TracingKind,
|
||||
pub name: String,
|
||||
pub level: VerboseLevel,
|
||||
#[serde(default)]
|
||||
pub additional: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_tracing_kind() {
|
||||
let tracing = Tracing {
|
||||
kind: TracingKind::File,
|
||||
name: "file".to_string(),
|
||||
level: VerboseLevel::DEBUG,
|
||||
additional: HashMap::new(),
|
||||
};
|
||||
|
||||
let serialized = serde_json::to_string(&tracing).unwrap();
|
||||
let deserialized: Tracing = serde_json::from_str(&serialized).unwrap();
|
||||
|
||||
assert_eq!(tracing, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tracing_kind_debug() {
|
||||
let tracing = Tracing {
|
||||
kind: TracingKind::File,
|
||||
name: "file".to_string(),
|
||||
level: VerboseLevel::DEBUG,
|
||||
additional: HashMap::new(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
format!("{:?}", tracing),
|
||||
"Tracing { kind: File, name: \"file\", level: DEBUG, additional: {} }"
|
||||
);
|
||||
}
|
||||
}
|
@ -10,7 +10,10 @@
|
||||
"@monodon/rust": "2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@napi-rs/cli": "3.0.0-alpha.63",
|
||||
"@napi-rs/wasm-runtime": "^0.2.4",
|
||||
"@nx/workspace": "21.0.3",
|
||||
"emnapi": "^1.1.0",
|
||||
"nx": "21.0.3"
|
||||
},
|
||||
"packageManager": "yarn@4.9.1"
|
||||
|
Loading…
Reference in New Issue
Block a user