(&self, event: &Event<'_>, _ctx: Context<'_, S>)
| 41 | |
| 42 | impl<S: Subscriber> Layer<S> for LogPushLayer { |
| 43 | fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) { |
| 44 | let meta = event.metadata(); |
| 45 | |
| 46 | // Filter by configured max level (default: info). |
| 47 | if *meta.level() > self.max_level { |
| 48 | return; |
| 49 | } |
| 50 | |
| 51 | // OCSF events carry their payload in a thread-local; extract the |
| 52 | // shorthand representation for the push message. Non-OCSF events |
| 53 | // use the original visitor-based extraction. |
| 54 | let (msg, fields) = if meta.target() == openshell_ocsf::OCSF_TARGET { |
| 55 | if let Some(ocsf_event) = openshell_ocsf::clone_current_event() { |
| 56 | ( |
| 57 | ocsf_event.format_shorthand(), |
| 58 | std::collections::HashMap::new(), |
| 59 | ) |
| 60 | } else { |
| 61 | return; |
| 62 | } |
| 63 | } else { |
| 64 | let mut visitor = LogVisitor::default(); |
| 65 | event.record(&mut visitor); |
| 66 | visitor.into_parts(meta.name()) |
| 67 | }; |
| 68 | |
| 69 | let ts = openshell_core::time::now_ms(); |
| 70 | |
| 71 | let is_ocsf = meta.target() == openshell_ocsf::OCSF_TARGET; |
| 72 | |
| 73 | let log = SandboxLogLine { |
| 74 | sandbox_id: self.sandbox_id.clone(), |
| 75 | timestamp_ms: ts, |
| 76 | level: if is_ocsf { |
| 77 | "OCSF".to_string() |
| 78 | } else { |
| 79 | meta.level().to_string() |
| 80 | }, |
| 81 | target: meta.target().to_string(), |
| 82 | message: msg, |
| 83 | source: "sandbox".to_string(), |
| 84 | fields, |
| 85 | }; |
| 86 | |
| 87 | // Best-effort: drop if the channel is full (don't block tracing). |
| 88 | let _ = self.tx.try_send(log); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | /// Spawn a background task that batches and pushes log lines to the server. |
nothing calls this directly
no test coverage detected