add systemd unit logging mode
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
fda8b36809
commit
62d80b97e6
4 changed files with 78 additions and 12 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use std::{env, io, sync::LazyLock};
|
||||||
|
|
||||||
use tracing::{
|
use tracing::{
|
||||||
field::{Field, Visit},
|
field::{Field, Visit},
|
||||||
Event, Level, Subscriber,
|
Event, Level, Subscriber,
|
||||||
|
@ -7,12 +9,59 @@ use tracing_subscriber::{
|
||||||
fmt,
|
fmt,
|
||||||
fmt::{
|
fmt::{
|
||||||
format::{Compact, DefaultVisitor, Format, Full, Pretty, Writer},
|
format::{Compact, DefaultVisitor, Format, Full, Pretty, Writer},
|
||||||
FmtContext, FormatEvent, FormatFields,
|
FmtContext, FormatEvent, FormatFields, MakeWriter,
|
||||||
},
|
},
|
||||||
registry::LookupSpan,
|
registry::LookupSpan,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{Config, Result};
|
use crate::{apply, Config, Result};
|
||||||
|
|
||||||
|
static SYSTEMD_MODE: LazyLock<bool> =
|
||||||
|
LazyLock::new(|| env::var("SYSTEMD_EXEC_PID").is_ok() && env::var("JOURNAL_STREAM").is_ok());
|
||||||
|
|
||||||
|
pub struct ConsoleWriter {
|
||||||
|
stdout: io::Stdout,
|
||||||
|
stderr: io::Stderr,
|
||||||
|
_journal_stream: [u64; 2],
|
||||||
|
use_stderr: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConsoleWriter {
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(_config: &Config) -> Self {
|
||||||
|
let journal_stream = get_journal_stream();
|
||||||
|
Self {
|
||||||
|
stdout: io::stdout(),
|
||||||
|
stderr: io::stderr(),
|
||||||
|
_journal_stream: journal_stream.into(),
|
||||||
|
use_stderr: journal_stream.0 != 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> MakeWriter<'a> for ConsoleWriter {
|
||||||
|
type Writer = &'a Self;
|
||||||
|
|
||||||
|
fn make_writer(&'a self) -> Self::Writer { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for &'_ ConsoleWriter {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
if self.use_stderr {
|
||||||
|
self.stderr.lock().write(buf)
|
||||||
|
} else {
|
||||||
|
self.stdout.lock().write(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
if self.use_stderr {
|
||||||
|
self.stderr.lock().flush()
|
||||||
|
} else {
|
||||||
|
self.stdout.lock().flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ConsoleFormat {
|
pub struct ConsoleFormat {
|
||||||
_compact: Format<Compact>,
|
_compact: Format<Compact>,
|
||||||
|
@ -20,10 +69,6 @@ pub struct ConsoleFormat {
|
||||||
pretty: Format<Pretty>,
|
pretty: Format<Pretty>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ConsoleVisitor<'a> {
|
|
||||||
visitor: DefaultVisitor<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConsoleFormat {
|
impl ConsoleFormat {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(config: &Config) -> Self {
|
pub fn new(config: &Config) -> Self {
|
||||||
|
@ -68,6 +113,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ConsoleVisitor<'a> {
|
||||||
|
visitor: DefaultVisitor<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'writer> FormatFields<'writer> for ConsoleFormat {
|
impl<'writer> FormatFields<'writer> for ConsoleFormat {
|
||||||
fn format_fields<R>(&self, writer: Writer<'writer>, fields: R) -> Result<(), std::fmt::Error>
|
fn format_fields<R>(&self, writer: Writer<'writer>, fields: R) -> Result<(), std::fmt::Error>
|
||||||
where
|
where
|
||||||
|
@ -92,3 +141,19 @@ impl Visit for ConsoleVisitor<'_> {
|
||||||
self.visitor.record_debug(field, value);
|
self.visitor.record_debug(field, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
fn get_journal_stream() -> (u64, u64) {
|
||||||
|
is_systemd_mode()
|
||||||
|
.then(|| env::var("JOURNAL_STREAM").ok())
|
||||||
|
.flatten()
|
||||||
|
.as_deref()
|
||||||
|
.and_then(|s| s.split_once(':'))
|
||||||
|
.map(apply!(2, str::parse))
|
||||||
|
.map(apply!(2, Result::unwrap_or_default))
|
||||||
|
.unwrap_or((0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use]
|
||||||
|
pub fn is_systemd_mode() -> bool { *SYSTEMD_MODE }
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
pub mod capture;
|
pub mod capture;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
mod console;
|
pub mod console;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
pub mod fmt_span;
|
pub mod fmt_span;
|
||||||
mod reload;
|
mod reload;
|
||||||
mod suppress;
|
mod suppress;
|
||||||
|
|
||||||
pub use capture::Capture;
|
pub use capture::Capture;
|
||||||
pub use console::ConsoleFormat;
|
pub use console::{is_systemd_mode, ConsoleFormat, ConsoleWriter};
|
||||||
pub use reload::{LogLevelReloadHandles, ReloadHandle};
|
pub use reload::{LogLevelReloadHandles, ReloadHandle};
|
||||||
pub use suppress::Suppress;
|
pub use suppress::Suppress;
|
||||||
pub use tracing::Level;
|
pub use tracing::Level;
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
config::Config,
|
config::Config,
|
||||||
debug_warn, err,
|
debug_warn, err,
|
||||||
log::{capture, fmt_span, ConsoleFormat, LogLevelReloadHandles},
|
log::{capture, fmt_span, ConsoleFormat, ConsoleWriter, LogLevelReloadHandles},
|
||||||
result::UnwrapOrErr,
|
result::UnwrapOrErr,
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ pub(crate) fn init(
|
||||||
.with_span_events(console_span_events)
|
.with_span_events(console_span_events)
|
||||||
.event_format(ConsoleFormat::new(config))
|
.event_format(ConsoleFormat::new(config))
|
||||||
.fmt_fields(ConsoleFormat::new(config))
|
.fmt_fields(ConsoleFormat::new(config))
|
||||||
.map_writer(|w| w);
|
.with_writer(ConsoleWriter::new(config));
|
||||||
|
|
||||||
let (console_reload_filter, console_reload_handle) =
|
let (console_reload_filter, console_reload_handle) =
|
||||||
reload::Layer::new(console_filter.clone());
|
reload::Layer::new(console_filter.clone());
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
#![cfg(feature = "console")]
|
#![cfg(feature = "console")]
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use conduwuit::{debug, defer, error, log, Server};
|
use conduwuit::{debug, defer, error, log, log::is_systemd_mode, Server};
|
||||||
use futures::future::{AbortHandle, Abortable};
|
use futures::future::{AbortHandle, Abortable};
|
||||||
use ruma::events::room::message::RoomMessageEventContent;
|
use ruma::events::room::message::RoomMessageEventContent;
|
||||||
use rustyline_async::{Readline, ReadlineError, ReadlineEvent};
|
use rustyline_async::{Readline, ReadlineError, ReadlineEvent};
|
||||||
|
@ -123,7 +124,7 @@ impl Console {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn readline(self: &Arc<Self>) -> Result<ReadlineEvent, ReadlineError> {
|
async fn readline(self: &Arc<Self>) -> Result<ReadlineEvent, ReadlineError> {
|
||||||
let _suppression = log::Suppress::new(&self.server);
|
let _suppression = (!is_systemd_mode()).then(|| log::Suppress::new(&self.server));
|
||||||
|
|
||||||
let (mut readline, _writer) = Readline::new(PROMPT.to_owned())?;
|
let (mut readline, _writer) = Readline::new(PROMPT.to_owned())?;
|
||||||
let self_ = Arc::clone(self);
|
let self_ = Arc::clone(self);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue