1use napi::Error;
2use napi::bindgen_prelude::{BigInt, Buffer};
3use napi_derive::napi;
4use tracing::Level;
5
6#[napi]
7pub struct Logger {
8 inner: acta::Logger,
9 output: acta::BufferedWriter,
10}
11
12#[napi]
13impl Logger {
14 #[napi(constructor)]
15 pub fn new(config: Option<serde_json::Value>, capacity: Option<u32>) -> napi::Result<Self> {
16 let output = acta::BufferedWriter::new(capacity.unwrap_or(64 * 1024) as usize);
17 let config = config
18 .unwrap_or_else(|| serde_json::Value::Object(serde_json::Map::new()))
19 .to_string();
20 let config = acta::Config::from_json_with_writer(&config, output.clone())
21 .map_err(|error| Error::from_reason(error.to_string()))?;
22 let inner =
23 acta::Logger::new(config).map_err(|error| Error::from_reason(error.to_string()))?;
24 Ok(Self { inner, output })
25 }
26
27 #[napi]
28 pub fn log(&self, level: u32, message: String) -> napi::Result<()> {
29 let level = match level {
30 0 => Level::ERROR,
31 1 => Level::WARN,
32 2 => Level::INFO,
33 3 => Level::DEBUG,
34 4 => Level::TRACE,
35 _ => return Err(Error::from_reason(format!("invalid log level: {level}"))),
36 };
37 self.inner.log(level, &message);
38 Ok(())
39 }
40
41 #[napi]
42 pub fn drain(&self, max_bytes: u32) -> Buffer {
43 Buffer::from(self.output.drain(max_bytes as usize))
44 }
45
46 #[napi]
47 pub fn event(&self, event: serde_json::Value) -> napi::Result<()> {
48 let event = serde_json::from_value::<acta::Event>(event)
49 .map_err(|error| Error::from_reason(error.to_string()))?;
50 self.inner
51 .event(&event)
52 .map_err(|error| Error::from_reason(error.to_string()))
53 }
54
55 #[napi]
56 pub fn create_span(&self, event: serde_json::Value) -> napi::Result<u32> {
57 let event = serde_json::from_value::<acta::Event>(event)
58 .map_err(|error| Error::from_reason(error.to_string()))?;
59 self.inner
60 .create_span(&event)
61 .map_err(|error| Error::from_reason(error.to_string()))
62 }
63
64 #[napi]
65 pub fn record_span(&self, id: u32, fields: serde_json::Value) -> napi::Result<()> {
66 let fields = fields
67 .as_object()
68 .ok_or_else(|| Error::from_reason("fields must be an object"))?;
69 self.inner
70 .record_span(id, fields)
71 .map_err(|error| Error::from_reason(error.to_string()))
72 }
73
74 #[napi]
75 pub fn close_span(&self, id: u32) -> napi::Result<()> {
76 self.inner
77 .close_span(id)
78 .map_err(|error| Error::from_reason(error.to_string()))
79 }
80
81 #[napi]
82 pub fn dropped(&self) -> BigInt {
83 BigInt {
84 sign_bit: false,
85 words: vec![self.output.dropped()],
86 }
87 }
88
89 #[napi]
90 pub fn set_filter(&self, filter: String) -> napi::Result<()> {
91 self.inner
92 .set_filter(
93 filter
94 .parse()
95 .map_err(|_| Error::from_reason("invalid filter"))?,
96 )
97 .map_err(|error| Error::from_reason(error.to_string()))
98 }
99}