|
| 1 | +//! Logger that forwards `log` records to the Nyx host via `nyx_println`. |
| 2 | +//! |
| 3 | +//! In Nyx mode the guest's stdout/stderr is discarded, so `simple_logger` |
| 4 | +//! output never reaches the host. This logger instead routes each record |
| 5 | +//! through `nyx_println` for debugging. Honors the `RUST_LOG` log level. |
| 6 | +//! |
| 7 | +//! This logger is only installed when the `nyx` feature is active and both |
| 8 | +//! `SMITE_NYX` and `SMITE_NYX_LOG` are set. |
| 9 | +
|
| 10 | +use std::ffi::c_char; |
| 11 | + |
| 12 | +use log::{LevelFilter, Log, Metadata, Record}; |
| 13 | + |
| 14 | +struct NyxLogger { |
| 15 | + level: LevelFilter, |
| 16 | +} |
| 17 | + |
| 18 | +impl Log for NyxLogger { |
| 19 | + fn enabled(&self, metadata: &Metadata) -> bool { |
| 20 | + metadata.level() <= self.level |
| 21 | + } |
| 22 | + |
| 23 | + fn log(&self, record: &Record) { |
| 24 | + if !self.enabled(record.metadata()) { |
| 25 | + return; |
| 26 | + } |
| 27 | + let line = format!( |
| 28 | + "{:<5} [{}] {}", |
| 29 | + record.level(), |
| 30 | + record.target(), |
| 31 | + record.args() |
| 32 | + ); |
| 33 | + // SAFETY: The line.len() bytes at the line pointer are valid for the |
| 34 | + // duration of the call. |
| 35 | + unsafe { |
| 36 | + smite_nyx_sys::nyx_println(line.as_ptr().cast::<c_char>(), line.len()); |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + fn flush(&self) {} |
| 41 | +} |
| 42 | + |
| 43 | +/// Reads the desired level from `RUST_LOG` (default `info`). |
| 44 | +fn level_from_env() -> LevelFilter { |
| 45 | + std::env::var("RUST_LOG") |
| 46 | + .ok() |
| 47 | + .and_then(|v| v.trim().parse().ok()) |
| 48 | + .unwrap_or(LevelFilter::Info) |
| 49 | +} |
| 50 | + |
| 51 | +/// Installs the Nyx logger as the global `log` logger. |
| 52 | +/// |
| 53 | +/// # Panics |
| 54 | +/// |
| 55 | +/// Panics if a global logger has already been set. |
| 56 | +pub fn init() { |
| 57 | + let level = level_from_env(); |
| 58 | + log::set_boxed_logger(Box::new(NyxLogger { level })).expect("logger not already set"); |
| 59 | + log::set_max_level(level); |
| 60 | +} |
0 commit comments