Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,364 changes: 736 additions & 628 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=1.0.0"
bitwarden-fido = { path = "crates/bitwarden-fido", version = "=1.0.0" }
bitwarden-generators = { path = "crates/bitwarden-generators", version = "=1.0.0" }
bitwarden-ipc = { path = "crates/bitwarden-ipc", version = "=1.0.0" }
bitwarden-logging = { path = "crates/bitwarden-logging", version = "=1.0.0" }
bitwarden-pm = { path = "crates/bitwarden-pm", version = "=1.0.0" }
bitwarden-send = { path = "crates/bitwarden-send", version = "=1.0.0" }
bitwarden-sm = { path = "bitwarden_license/bitwarden-sm", version = "=1.0.0" }
Expand Down Expand Up @@ -80,6 +81,7 @@ syn = ">=2.0.87, <3"
thiserror = ">=1.0.40, <3"
tokio = { version = "1.36.0", features = ["macros"] }
tracing = { version = "0.1.41" }
tracing-core = { version = ">=0.1.35, <0.2" }
tracing-subscriber = { version = "0.3.20", features = [
"fmt",
"env-filter",
Expand Down
36 changes: 36 additions & 0 deletions crates/bitwarden-logging/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "bitwarden-logging"
description = """
Internal crate for the bitwarden crate. Do not use.
"""

version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
readme.workspace = true
homepage.workspace = true
repository.workspace = true
license-file.workspace = true
keywords.workspace = true

[features]
wasm = [
"dep:js-sys",
"dep:tsify",
"dep:wasm-bindgen",
"dep:wasm-bindgen-futures",
]

[dependencies]
js-sys = { workspace = true, optional = true }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-core = { workspace = true }
once_cell = "1.21.3"
tsify = { workspace = true, optional = true }
wasm-bindgen = { workspace = true, optional = true }
wasm-bindgen-futures = { workspace = true, optional = true }

[lints]
workspace = true
1 change: 1 addition & 0 deletions crates/bitwarden-logging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Bitwarden Logging
16 changes: 16 additions & 0 deletions crates/bitwarden-logging/src/dynamic_tracing/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
The code in this folder contains a modified version of code from the `tracing_dynamic`
project, licensed under the the following Apache License:

Copyright [2023] [Bryn Cooke]

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.
262 changes: 262 additions & 0 deletions crates/bitwarden-logging/src/dynamic_tracing/event_factory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
use std::collections::BTreeMap;

use tracing::{
Metadata,
field::{Field, Value},
};

use super::factory::{Builder, Factory};

/// Event factory allows creating events with attributes defined at runtime.
/// It leaks memory to do this, so create event factories once and reuse them.
pub type EventFactory<'a> = Factory<EventBuilder<'a>>;

pub enum EventBuilder<'a> {
Enabled {
metadata: &'static Metadata<'static>,
fields: &'static BTreeMap<&'static str, Field>,
values: Vec<(&'static Field, Option<&'a dyn Value>)>,
parent: Option<tracing::Id>,
},
Disabled,
}

impl Builder for EventBuilder<'_> {
fn create_enabled(
metadata: &'static Metadata<'static>,
fields: &'static BTreeMap<&'static str, Field>,
) -> Self {
EventBuilder::Enabled {
metadata,
fields,
values: Vec::new(),
parent: None,
}
}
fn create_disabled(_metadata: &'static Metadata<'static>) -> Self {
EventBuilder::Disabled
}
}

impl<'a> EventBuilder<'a> {
#[inline]
pub fn with(&mut self, name: &str, value: &'a dyn Value) -> &mut Self {
if let EventBuilder::Enabled { values, fields, .. } = self {
if let Some(field) = fields.get(name) {
values.push((field, Some(value)));
}
}
self
}

pub fn with_span_id(&mut self, parent: Option<tracing::Id>) -> &mut Self {
if let EventBuilder::Enabled { parent: p, .. } = self {
*p = parent;
}
self
}

#[inline]
pub fn build(&self) {
if let EventBuilder::Enabled {
parent,
metadata,
values,
..
} = self
{
macro_rules! finish {
($n:literal) => {
if $n == values.len() {
let values: [(&'static Field, Option<&'a (dyn Value)>); $n] =
values.as_slice().try_into().unwrap();
let value_set = metadata.fields().value_set(&values);
::tracing::Event::child_of(parent.clone(), metadata, &value_set);
return;
}
};
}
if values.len() < 10 {
finish!(0);
finish!(1);
finish!(2);
finish!(3);
finish!(4);
finish!(5);
finish!(6);
finish!(7);
finish!(8);
finish!(9);
}
if values.len() < 20 {
finish!(10);
finish!(11);
finish!(12);
finish!(13);
finish!(14);
finish!(15);
finish!(16);
finish!(17);
finish!(18);
finish!(19);
}
if values.len() < 30 {
finish!(20);
finish!(21);
finish!(22);
finish!(23);
finish!(24);
finish!(25);
finish!(26);
finish!(27);
finish!(28);
finish!(29);
}
if values.len() < 40 {
finish!(30);
finish!(31);
finish!(32);
finish!(33);
finish!(34);
finish!(35);
finish!(36);
finish!(37);
finish!(38);
finish!(39);
}
if values.len() < 50 {
finish!(40);
finish!(41);
finish!(42);
finish!(43);
finish!(44);
finish!(45);
finish!(46);
finish!(47);
finish!(48);
finish!(49);
}
if values.len() < 60 {
finish!(50);
finish!(51);
finish!(52);
finish!(53);
finish!(54);
finish!(55);
finish!(56);
finish!(57);
finish!(58);
finish!(59);
}
if values.len() < 70 {
finish!(60);
finish!(61);
finish!(62);
finish!(63);
finish!(64);
finish!(65);
finish!(66);
finish!(67);
finish!(68);
finish!(69);
}
if values.len() < 80 {
finish!(70);
finish!(71);
finish!(72);
finish!(73);
finish!(74);
finish!(75);
finish!(76);
finish!(77);
finish!(78);
finish!(79);
}
if values.len() < 90 {
finish!(90);
finish!(91);
finish!(92);
finish!(93);
finish!(94);
finish!(95);
finish!(96);
finish!(97);
finish!(98);
finish!(99);
}
if values.len() < 110 {
finish!(100);
}
panic!("too many attributes, up to 100 are supported")
}
}
}

// #[cfg(test)]
// mod test {
// use std::sync::{Arc, Mutex};

// use tracing_core::Level;

// use crate::event_factory::EventFactory;

// #[derive(Clone, Default)]
// struct TestWriter {
// buffer: Arc<Mutex<Vec<u8>>>,
// }

// impl std::io::Write for TestWriter {
// fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
// let buf_len = buf.len();
// self.buffer.lock().unwrap().append(&mut buf.to_vec());
// Ok(buf_len)
// }

// fn flush(&mut self) -> std::io::Result<()> {
// Ok(())
// }
// }
// #[test]
// fn test_unfiltered() {
// test(Level::INFO)
// }
// #[test]
// fn test_filtered() {
// test(Level::ERROR)
// }

// fn test(subscriber_level: Level) {
// let test_writer = TestWriter::default();
// let attrs = vec!["dyn_attr_1", "dyn_attr_2"];
// let event_factory = EventFactory::new(
// "event_name",
// "event_target",
// Level::INFO,
// None,
// None,
// None,
// &attrs,
// );
// let subscriber = tracing_subscriber::fmt()
// .json()
// .without_time()
// .with_file(false)
// .with_line_number(false)
// .with_max_level(subscriber_level)
// .with_writer(Mutex::new(test_writer.clone()))
// .finish();

// tracing::subscriber::with_default(subscriber, || {
// let mut event = event_factory.create();
// event.with("dyn_attr_1", &"dyn_attr_1");
// event.with("dyn_attr_2", &"dyn_attr_2");
// event.with("dyn_attr_4", &"dyn_attr_4");
// event.build();
// });

// insta::assert_snapshot!(
// subscriber_level.to_string(),
// String::from_utf8(test_writer.buffer.lock().unwrap().to_vec()).unwrap()
// );
// }
// }
Loading
Loading