mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 18:18:55 +00:00
feat(gui-client): send Linux GUI logs to journald (#8236)
This configures the GUI client to log to journald in addition to files as well. For better or worse, this logs all events such that structured information is preserved, e.g. all additional fields next to the message are also saved as fields in the journal. By default, when viewing the logs via `journalctl`, those fields are not displayed. This makes the default output of `journalctl` for the FIrezone GUI not as useful as it could be. Fixing that is left to a later stage. Related: #8173
This commit is contained in:
12
rust/Cargo.lock
generated
12
rust/Cargo.lock
generated
@@ -2120,6 +2120,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"tracing-journald",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
@@ -7321,6 +7322,17 @@ dependencies = [
|
||||
"valuable",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-journald"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0b4143302cf1022dac868d521e36e8b27691f72c84b3311750d5188ebba657"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tracing-core",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.2.0"
|
||||
|
||||
@@ -140,6 +140,7 @@ tracing-log = "0.2.0"
|
||||
tracing-macros = { git = "https://github.com/tokio-rs/tracing", branch = "v0.1.x" } # Contains `dbg!` but for `tracing`.
|
||||
tracing-opentelemetry = "0.27.0"
|
||||
tracing-stackdriver = "0.11.0"
|
||||
tracing-journald = "0.3.1"
|
||||
tracing-subscriber = { version = "0.3.19", features = ["parking_lot"] }
|
||||
trackable = "1.3.0"
|
||||
url = "2.5.2"
|
||||
|
||||
@@ -42,6 +42,7 @@ zip = { workspace = true, features = ["deflate", "time"] }
|
||||
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
dirs = { workspace = true }
|
||||
tracing-journald = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
winreg = { workspace = true }
|
||||
|
||||
@@ -53,34 +53,53 @@ pub fn setup(directives: &str) -> Result<Handles> {
|
||||
}
|
||||
|
||||
let log_path = known_dirs::logs().context("Can't compute app log dir")?;
|
||||
std::fs::create_dir_all(&log_path).map_err(Error::CreateDirAll)?;
|
||||
|
||||
// Logfilter for stdout cannot be reloaded. This is okay because we are using it only for local dev and debugging anyway.
|
||||
// Having multiple reload handles makes their type-signature quite complex so we don't bother with that.
|
||||
let (stdout_filter, stdout_reloader) = firezone_logging::try_filter(directives)?;
|
||||
|
||||
let stdout = tracing_subscriber::fmt::layer()
|
||||
let stdout_layer = tracing_subscriber::fmt::layer()
|
||||
.with_ansi(firezone_logging::stdout_supports_ansi())
|
||||
.event_format(firezone_logging::Format::new())
|
||||
.with_filter(stdout_filter);
|
||||
.event_format(firezone_logging::Format::new());
|
||||
|
||||
let (system_filter, system_reloader) = firezone_logging::try_filter(directives)?;
|
||||
let system_layer = system_layer().context("Failed to init system logger")?;
|
||||
#[cfg(target_os = "linux")]
|
||||
let syslog_identifier = Some(system_layer.syslog_identifier().to_owned());
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let syslog_identifier = Option::<String>::None;
|
||||
|
||||
std::fs::create_dir_all(&log_path).map_err(Error::CreateDirAll)?;
|
||||
let (file_layer, logger) = firezone_logging::file::layer(&log_path, "gui-client");
|
||||
let (file_filter, file_reloader) = firezone_logging::try_filter(directives)?;
|
||||
|
||||
let subscriber = Registry::default()
|
||||
.with(file_layer.with_filter(file_filter))
|
||||
.with(stdout)
|
||||
.with(stdout_layer.with_filter(stdout_filter))
|
||||
.with(system_layer.with_filter(system_filter))
|
||||
.with(firezone_logging::sentry_layer());
|
||||
firezone_logging::init(subscriber)?;
|
||||
|
||||
tracing::debug!(log_path = %log_path.display(), "Log path");
|
||||
tracing::debug!(log_path = %log_path.display(), syslog_identifier = syslog_identifier.map(tracing::field::display));
|
||||
|
||||
Ok(Handles {
|
||||
logger,
|
||||
reloader: stdout_reloader.merge(file_reloader),
|
||||
reloader: stdout_reloader.merge(file_reloader).merge(system_reloader),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn system_layer() -> Result<tracing_journald::Layer> {
|
||||
let layer = tracing_journald::layer()?;
|
||||
|
||||
Ok(layer)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[expect(clippy::unnecessary_wraps, reason = "Linux signature needs `Result`")]
|
||||
fn system_layer() -> Result<tracing_subscriber::layer::Identity> {
|
||||
Ok(tracing_subscriber::layer::Identity::new())
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize)]
|
||||
pub struct FileCount {
|
||||
bytes: u64,
|
||||
|
||||
@@ -158,7 +158,14 @@ captured by systemd and sent to journald. To view the logs of the IPC service,
|
||||
use:
|
||||
|
||||
```bash
|
||||
journalctl -efu firezone-client-ipc.service
|
||||
journalctl --pager-end --follow --unit firezone-client-ipc.service
|
||||
```
|
||||
|
||||
The GUI client logs to journald directly as well with the syslog identifier
|
||||
`firezone-client-gui`. To view the logs via `journalctl`, use:
|
||||
|
||||
```bash
|
||||
journalctl --pager-end --follow --identifier firezone-client-gui
|
||||
```
|
||||
|
||||
## Uninstalling
|
||||
|
||||
Reference in New Issue
Block a user