1#![deny(unsafe_code)]
2
3#[cfg(target_arch = "wasm32")]
4use acta::Logger as NativeLogger;
5#[cfg(target_arch = "wasm32")]
6use tracing::Level;
7#[cfg(target_arch = "wasm32")]
8use wasm_bindgen::prelude::*;
9
10#[cfg(target_arch = "wasm32")]
11#[wasm_bindgen]
12pub struct Logger {
13 inner: Option<NativeLogger>,
14 output: acta::BufferedWriter,
15}
16
17#[cfg(target_arch = "wasm32")]
18#[wasm_bindgen]
19impl Logger {
20 #[wasm_bindgen(constructor)]
21 pub fn new(config_json: &str, capacity: u32) -> Result<Logger, JsValue> {
22 let output = acta::BufferedWriter::new(capacity as usize);
23 let config = acta::Config::from_json_with_writer(config_json, output.clone())
24 .map_err(|error| JsValue::from_str(&error.to_string()))?;
25 let inner =
26 NativeLogger::new(config).map_err(|error| JsValue::from_str(&error.to_string()))?;
27 Ok(Self {
28 inner: Some(inner),
29 output,
30 })
31 }
32
33 pub fn log(&self, level: u32, message: &str) -> Result<(), JsValue> {
34 let level = match level {
35 0 => Level::ERROR,
36 1 => Level::WARN,
37 2 => Level::INFO,
38 3 => Level::DEBUG,
39 4 => Level::TRACE,
40 _ => return Err(JsValue::from_str(&format!("invalid log level: {level}"))),
41 };
42 self.logger()?.log(level, message);
43 Ok(())
44 }
45
46 pub fn drain(&self, max_bytes: u32) -> Result<Vec<u8>, JsValue> {
47 self.logger()?;
48 Ok(self.output.drain(max_bytes as usize))
49 }
50
51 pub fn event(&self, event_json: &str) -> Result<(), JsValue> {
52 let logger = self.logger()?;
53 let event = serde_json::from_str(event_json)
54 .map_err(|error| JsValue::from_str(&error.to_string()))?;
55 logger
56 .event(&event)
57 .map_err(|error| JsValue::from_str(&error.to_string()))
58 }
59
60 #[wasm_bindgen(js_name = createSpan)]
61 pub fn create_span(&self, event_json: &str) -> Result<u32, JsValue> {
62 let logger = self.logger()?;
63 let event = serde_json::from_str(event_json)
64 .map_err(|error| JsValue::from_str(&error.to_string()))?;
65 logger
66 .create_span(&event)
67 .map_err(|error| JsValue::from_str(&error.to_string()))
68 }
69
70 #[wasm_bindgen(js_name = recordSpan)]
71 pub fn record_span(&self, id: u32, fields_json: &str) -> Result<(), JsValue> {
72 let logger = self.logger()?;
73 let fields =
74 serde_json::from_str::<serde_json::Map<String, serde_json::Value>>(fields_json)
75 .map_err(|error| JsValue::from_str(&error.to_string()))?;
76 logger
77 .record_span(id, &fields)
78 .map_err(|error| JsValue::from_str(&error.to_string()))
79 }
80
81 #[wasm_bindgen(js_name = closeSpan)]
82 pub fn close_span(&self, id: u32) -> Result<(), JsValue> {
83 self.logger()?
84 .close_span(id)
85 .map_err(|error| JsValue::from_str(&error.to_string()))
86 }
87
88 pub fn dropped(&self) -> Result<u64, JsValue> {
89 self.logger()?;
90 Ok(self.output.dropped())
91 }
92
93 #[wasm_bindgen(js_name = setFilter)]
94 pub fn set_filter(&self, filter: &str) -> Result<(), JsValue> {
95 self.logger()?
96 .set_filter(
97 filter
98 .parse()
99 .map_err(|_| JsValue::from_str("invalid filter"))?,
100 )
101 .map_err(|error| JsValue::from_str(&error.to_string()))
102 }
103
104 pub fn close(&mut self) {
105 self.inner.take();
106 }
107}
108
109#[cfg(target_arch = "wasm32")]
110impl Logger {
111 fn logger(&self) -> Result<&NativeLogger, JsValue> {
112 self.inner
113 .as_ref()
114 .ok_or_else(|| JsValue::from_str("Logger is closed"))
115 }
116}