refactor(rust): stringify errors early (#8033)

As it turns out, the effort in #7104 was not a good idea. By logging
errors as values, most of our Sentry reports all have the same title and
thus cannot be differentiated from within the overview at all. To fix
this, we stringify errors with all their sources whenever they got
logged. This ensures log messages are unique and all Sentry issues will
have a useful title.
This commit is contained in:
Thomas Eizinger
2025-02-06 14:18:35 +00:00
committed by GitHub
parent 945d40e7f9
commit d2e9b09874
38 changed files with 117 additions and 197 deletions

View File

@@ -64,7 +64,6 @@
use crate::platform::DnsControlMethod;
use anyhow::{anyhow, Context as _, Result};
use firezone_logging::anyhow_dyn_err;
use std::thread;
use tokio::sync::{
mpsc::{self, error::TrySendError},
@@ -118,7 +117,7 @@ pub struct Worker {
impl Drop for Worker {
fn drop(&mut self) {
if let Err(e) = self.close() {
tracing::error!(error = anyhow_dyn_err(&e), "Failed to close worker thread")
tracing::error!("Failed to close worker thread: {e:#}")
}
}
}
@@ -260,10 +259,7 @@ impl Drop for Listener<'_> {
// and drop the DNS listeners
fn drop(&mut self) {
if let Err(e) = self.close_dont_drop() {
tracing::error!(
error = anyhow_dyn_err(&e),
"Failed to close `Listener` gracefully"
);
tracing::error!("Failed to close `Listener` gracefully: {e:#}");
}
}
}
@@ -381,7 +377,6 @@ impl Drop for Callback {
mod async_dns {
use anyhow::{Context as _, Result};
use firezone_logging::anyhow_dyn_err;
use futures::FutureExt as _;
use std::{ffi::c_void, ops::Deref, path::Path, pin::pin};
use tokio::{
@@ -454,16 +449,10 @@ mod async_dns {
}
if let Err(e) = listener_4.close() {
tracing::error!(
error = anyhow_dyn_err(&e),
"Error while closing IPv4 DNS listener"
);
tracing::error!("Error while closing IPv4 DNS listener: {e:#}");
}
if let Err(e) = listener_6.close() {
tracing::error!(
error = anyhow_dyn_err(&e),
"Error while closing IPv6 DNS listener"
);
tracing::error!("Error while closing IPv6 DNS listener: {e:#}");
}
Ok(())

View File

@@ -2,7 +2,7 @@
use crate::FIREZONE_MARK;
use anyhow::{anyhow, Context as _, Result};
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use futures::{SinkExt, TryStreamExt};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use ip_packet::{IpPacket, IpPacketBuf};
@@ -263,7 +263,7 @@ async fn add_route(route: &IpNetwork, idx: u32, handle: &Handle) {
return;
}
tracing::warn!(error = std_dyn_err(&err), %route, "Failed to add route");
tracing::warn!(%route, "Failed to add route: {}", err_with_src(&err));
}
async fn remove_route(route: &IpNetwork, idx: u32, handle: &Handle) {
@@ -291,7 +291,7 @@ async fn remove_route(route: &IpNetwork, idx: u32, handle: &Handle) {
return;
}
tracing::warn!(error = std_dyn_err(&err), %route, "Failed to remove route");
tracing::warn!(%route, "Failed to remove route: {}", err_with_src(&err));
}
#[derive(Debug)]
@@ -317,7 +317,7 @@ impl Tun {
.spawn(move || {
firezone_logging::unwrap_or_warn!(
tun::unix::send_recv_tun(fd, inbound_tx, outbound_rx, read, write),
"Failed to send / recv from TUN device"
"Failed to send / recv from TUN device: {}"
)
})
.map_err(io::Error::other)?;

View File

@@ -1,7 +1,7 @@
use crate::windows::TUNNEL_UUID;
use crate::TUNNEL_NAME;
use anyhow::{Context as _, Result};
use firezone_logging::{anyhow_dyn_err, std_dyn_err};
use firezone_logging::err_with_src;
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use ip_packet::{IpPacket, IpPacketBuf};
use ring::digest;
@@ -137,7 +137,7 @@ fn add_route(route: IpNetwork, iface_idx: u32) {
return;
}
tracing::warn!(error = std_dyn_err(&e), %route, "Failed to add route");
tracing::warn!( %route, "Failed to add route: {}", err_with_src(&e));
}
// It's okay if this blocks until the route is removed in the OS.
@@ -157,7 +157,7 @@ fn remove_route(route: IpNetwork, iface_idx: u32) {
return;
}
tracing::warn!(error = std_dyn_err(&e), %route, "Failed to remove route")
tracing::warn!(%route, "Failed to remove route: {}", err_with_src(&e))
}
fn forward_entry(route: IpNetwork, iface_idx: u32) -> MIB_IPFORWARD_ROW2 {
@@ -202,7 +202,7 @@ impl Drop for Tun {
);
self.inbound_rx.close(); // This avoids a deadlock when we join the worker thread, see PR 5571
if let Err(error) = self.session.shutdown() {
tracing::error!(error = std_dyn_err(&error), "wintun::Session::shutdown");
tracing::error!("wintun::Session::shutdown: {error:#}");
}
if let Err(error) = self
.recv_thread
@@ -390,7 +390,7 @@ fn try_set_mtu(luid: NET_LUID_LH, family: ADDRESS_FAMILY, mtu: u32) -> Result<()
if family == AF_INET6 && error.code() == windows_core::HRESULT::from_win32(0x80070490) {
tracing::debug!(?family, "Couldn't set MTU, maybe IPv6 is disabled.");
} else {
tracing::warn!(?family, error = std_dyn_err(&error), "Couldn't set MTU");
tracing::warn!(?family, "Couldn't set MTU: {}", err_with_src(&error));
}
return Ok(());
}
@@ -476,9 +476,8 @@ fn dll_already_exists(path: &Path, dll_bytes: &DllBytes) -> bool {
let actual_len = match file_length(&f) {
Err(e) => {
tracing::warn!(
error = anyhow_dyn_err(&e),
path = %path.display(),
"Failed to get file length"
"Failed to get file length: {e:#}"
);
return false;

View File

@@ -1,6 +1,6 @@
use crate::TUNNEL_NAME;
use anyhow::{Context as _, Result};
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use known_folders::{get_known_folder_path, KnownFolder};
use socket_factory::{TcpSocket, UdpSocket};
use std::{
@@ -139,7 +139,7 @@ fn delete_all_routing_entries_matching(addr: IpAddr) -> io::Result<()> {
// Safety: The `entry` is initialised.
if let Err(e) = unsafe { DeleteIpForwardEntry2(entry) }.ok() {
tracing::warn!(error = std_dyn_err(&e), "Failed to remove routing entry");
tracing::warn!("Failed to remove routing entry: {}", err_with_src(&e));
continue;
};
@@ -212,7 +212,7 @@ impl Drop for RoutingTableEntry {
return;
}
tracing::warn!(error = std_dyn_err(&e), "Failed to delete routing entry");
tracing::warn!("Failed to delete routing entry: {}", err_with_src(&e));
}
}

View File

@@ -8,7 +8,7 @@ use anyhow::{Context as _, Result};
use backoff::ExponentialBackoffBuilder;
use connlib_client_shared::{Callbacks, DisconnectError, Session, V4RouteList, V6RouteList};
use connlib_model::ResourceView;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use firezone_telemetry::{Telemetry, ANDROID_DSN};
use ip_network::{Ipv4Network, Ipv6Network};
use jni::{
@@ -267,7 +267,7 @@ impl Callbacks for CallbackHandler {
fn throw(env: &mut JNIEnv, class: &str, msg: impl Into<JNIString>) {
if let Err(err) = env.throw_new(class, msg) {
// We can't panic, since unwinding across the FFI boundary is UB...
tracing::error!(error = std_dyn_err(&err), "failed to throw Java exception");
tracing::error!("failed to throw Java exception: {}", err_with_src(&err));
}
}

View File

@@ -71,7 +71,7 @@ impl Tun {
read,
write,
),
"Failed to send / recv from TUN device"
"Failed to send / recv from TUN device: {}"
)
})
.map_err(io::Error::other)?;

View File

@@ -9,8 +9,7 @@ use anyhow::Result;
use backoff::ExponentialBackoffBuilder;
use connlib_client_shared::{Callbacks, DisconnectError, Session, V4RouteList, V6RouteList};
use connlib_model::ResourceView;
use firezone_logging::anyhow_dyn_err;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use firezone_telemetry::Telemetry;
use firezone_telemetry::APPLE_DSN;
use ip_network::{Ipv4Network, Ipv6Network};
@@ -146,7 +145,7 @@ impl Callbacks for CallbackHandler {
);
}
(Err(e), _, _) | (_, Err(e), _) | (_, _, Err(e)) => {
tracing::error!(error = std_dyn_err(&e), "Failed to serialize to JSON");
tracing::error!("Failed to serialize to JSON: {}", err_with_src(&e));
}
}
}
@@ -155,7 +154,7 @@ impl Callbacks for CallbackHandler {
let resource_list = match serde_json::to_string(&resource_list) {
Ok(resource_list) => resource_list,
Err(e) => {
tracing::error!(error = std_dyn_err(&e), "Failed to serialize resource list");
tracing::error!("Failed to serialize resource list: {}", err_with_src(&e));
return;
}
};
@@ -320,7 +319,7 @@ impl WrappedSession {
fn err_to_string(result: Result<WrappedSession>) -> Result<WrappedSession, String> {
result.map_err(|e| {
tracing::error!(error = anyhow_dyn_err(&e), "Failed to create session");
tracing::error!("Failed to create session: {e:#}");
format!("{e:#}")
})

View File

@@ -35,7 +35,7 @@ impl Tun {
read,
write,
),
"Failed to send / recv from TUN device"
"Failed to send / recv from TUN device: {}"
)
})
.map_err(io::Error::other)?;

View File

@@ -1,7 +1,7 @@
use crate::{callbacks::Callbacks, PHOENIX_TOPIC};
use anyhow::Result;
use connlib_model::{PublicKey, ResourceId};
use firezone_logging::{anyhow_dyn_err, err_with_src, telemetry_event};
use firezone_logging::{err_with_src, telemetry_event};
use firezone_tunnel::messages::client::{
EgressMessages, FailReason, FlowCreated, FlowCreationFailed, GatewayIceCandidates,
GatewaysIceCandidates, IngressMessages, InitClient,
@@ -283,10 +283,7 @@ where
.connect(PublicKeyParam(self.tunnel.public_key().to_bytes()));
}
Err(e) => {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to request new connection"
);
tracing::warn!("Failed to request new connection: {e:#}");
}
};
}

View File

@@ -3,7 +3,7 @@ use crate::{
node::{SessionId, Transmit},
};
use bytecodec::{DecodeExt as _, EncodeExt as _};
use firezone_logging::{err_with_src, std_dyn_err};
use firezone_logging::err_with_src;
use hex_display::HexDisplayExt as _;
use rand::random;
use ringbuffer::{AllocRingBuffer, RingBuffer as _};
@@ -1278,8 +1278,8 @@ fn srflx_candidate(local: SocketAddr, attr: &Attribute) -> Option<Candidate> {
Ok(c) => c,
Err(e) => {
tracing::debug!(
error = std_dyn_err(&e),
"Observed address is not a valid candidate"
"Observed address is not a valid candidate: {}",
err_with_src(&e)
);
return None;
}
@@ -1305,8 +1305,8 @@ fn relay_candidate(
Ok(c) => c,
Err(e) => {
tracing::debug!(
error = std_dyn_err(&e),
"Acquired allocation is not a valid candidate"
"Acquired allocation is not a valid candidate: {}",
err_with_src(&e)
);
return None;
}

View File

@@ -16,9 +16,7 @@ use connlib_model::{
DomainName, GatewayId, PublicKey, RelayId, ResourceId, ResourceStatus, ResourceView,
};
use connlib_model::{Site, SiteId};
use firezone_logging::{
anyhow_dyn_err, err_with_src, telemetry_event, unwrap_or_debug, unwrap_or_warn,
};
use firezone_logging::{err_with_src, telemetry_event, unwrap_or_debug, unwrap_or_warn};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use ip_network_table::IpNetworkTable;
use ip_packet::{IpPacket, UdpSlice, MAX_UDP_PAYLOAD};
@@ -415,10 +413,7 @@ impl ClientState {
) {
Ok(packet) => packet,
Err(e) => {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to create IP packet for `AssignedIp`s event"
);
tracing::warn!("Failed to create IP packet for `AssignedIp`s event: {e:#}");
continue;
}
};
@@ -584,7 +579,7 @@ impl ClientState {
unwrap_or_warn!(
self.try_queue_udp_dns_response(server, source, message),
"Failed to queue UDP DNS response"
"Failed to queue UDP DNS response: {}"
);
}
(dns::Transport::Tcp { source }, result) => {
@@ -600,7 +595,7 @@ impl ClientState {
unwrap_or_warn!(
self.tcp_dns_server.send_message(source, message),
"Failed to send TCP DNS response"
"Failed to send TCP DNS response: {}"
);
}
}
@@ -887,10 +882,7 @@ impl ClientState {
.collect();
if let Err(e) = self.tcp_dns_client.set_resolvers(upstream_resolvers) {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to connect to upstream DNS resolvers over TCP"
);
tracing::warn!("Failed to connect to upstream DNS resolvers over TCP: {e:#}");
}
}
@@ -1130,11 +1122,7 @@ impl ClientState {
let message = match parse_udp_dns_message(&datagram) {
Ok(message) => message,
Err(e) => {
tracing::warn!(
error = anyhow_dyn_err(&e),
?packet,
"Failed to parse DNS query"
);
tracing::warn!(?packet, "Failed to parse DNS query: {e:#}");
return ControlFlow::Break(());
}
};
@@ -1203,10 +1191,7 @@ impl ClientState {
match self.tcp_dns_client.send_query(server, message.clone()) {
Ok(()) => {}
Err(e) => {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to send recursive TCP DNS query"
);
tracing::warn!("Failed to send recursive TCP DNS query: {e:#}");
unwrap_or_debug!(
self.tcp_dns_server.send_message(

View File

@@ -10,7 +10,7 @@ use domain::{
},
dep::octseq::OctetsInto,
};
use firezone_logging::{anyhow_dyn_err, std_dyn_err, telemetry_span};
use firezone_logging::{err_with_src, telemetry_span};
use itertools::Itertools;
use pattern::{Candidate, Pattern};
use std::io;
@@ -138,7 +138,7 @@ impl StubResolver {
let parsed_pattern = match Pattern::new(&pattern) {
Ok(p) => p,
Err(e) => {
tracing::warn!(error = std_dyn_err(&e), %pattern, "Domain pattern is not valid");
tracing::warn!(%pattern, "Domain pattern is not valid: {}", err_with_src(&e));
return false;
}
};
@@ -231,7 +231,7 @@ impl StubResolver {
match self.try_handle(message) {
Ok(s) => s,
Err(e) => {
tracing::warn!(error = anyhow_dyn_err(&e), "Failed to handle DNS query");
tracing::warn!("Failed to handle DNS query: {e:#}");
ResolveStrategy::LocalResponse(servfail(message))
}
@@ -342,7 +342,7 @@ pub fn is_subdomain(name: &DomainName, resource: &str) -> bool {
let pattern = match Pattern::new(resource) {
Ok(p) => p,
Err(e) => {
tracing::warn!(error = std_dyn_err(&e), %resource, "Unable to parse pattern");
tracing::warn!(%resource, "Unable to parse pattern: {}", err_with_src(&e));
return false;
}
};

View File

@@ -7,7 +7,6 @@ use anyhow::{Context, Result};
use boringtun::x25519::PublicKey;
use chrono::{DateTime, Utc};
use connlib_model::{ClientId, DomainName, RelayId, ResourceId};
use firezone_logging::anyhow_dyn_err;
use ip_network::{Ipv4Network, Ipv6Network};
use ip_packet::{FzP2pControlSlice, IpPacket};
use secrecy::{ExposeSecret as _, Secret};
@@ -308,10 +307,7 @@ impl GatewayState {
Ok(dns_resource_nat::NatStatus::Active)
})
.unwrap_or_else(|e| {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to setup DNS resource NAT"
);
tracing::warn!("Failed to setup DNS resource NAT: {e:#}");
dns_resource_nat::NatStatus::Inactive
});
@@ -453,12 +449,7 @@ fn handle_p2p_control_packet(
req.domain,
dns_resource_nat::NatStatus::Inactive,
)
.inspect_err(|e| {
tracing::warn!(
error = anyhow_dyn_err(e),
"Failed to create `DomainStatus` packet"
)
})
.inspect_err(|e| tracing::warn!("Failed to create `DomainStatus` packet: {e:#}"))
.ok()?;
return Some(packet);

View File

@@ -19,7 +19,6 @@ use crate::{dns, messages::Interface, ClientEvent, GatewayEvent};
use connlib_model::{ClientId, GatewayId, PublicKey, RelayId};
use domain::base::iana::{Class, Rcode};
use domain::base::{Message, MessageBuilder, Record, RecordData, ToName as _, Ttl};
use firezone_logging::anyhow_dyn_err;
use rand::distributions::DistString;
use rand::SeedableRng;
use sha2::Digest;
@@ -549,7 +548,7 @@ impl TunnelTest {
c.handle_dns_response(message.for_slice())
}
Err(e) => {
tracing::error!(error = anyhow_dyn_err(&e), "TCP DNS query failed");
tracing::error!("TCP DNS query failed: {e:#}");
}
}
}

View File

@@ -1,6 +1,5 @@
use std::collections::VecDeque;
use firezone_logging::anyhow_dyn_err;
use ip_packet::{IpPacket, IpPacketBuf};
/// A in-memory device for [`smoltcp`] that is entirely backed by buffers.
@@ -77,7 +76,7 @@ impl smoltcp::phy::TxToken for SmolTxToken<'_> {
let mut ip_packet = match IpPacket::new(ip_packet_buf, len) {
Ok(p) => p,
Err(e) => {
tracing::warn!(error = anyhow_dyn_err(&e), "Received invalid IP packet");
tracing::warn!("Received invalid IP packet: {e:#}");
return result;
}
};

View File

@@ -4,7 +4,7 @@ use connlib_model::DomainName;
#[cfg(not(target_os = "windows"))]
use dns_lookup::{AddrInfoHints, AddrInfoIter, LookupError};
use firezone_bin_shared::TunDeviceManager;
use firezone_logging::{anyhow_dyn_err, telemetry_event, telemetry_span};
use firezone_logging::{telemetry_event, telemetry_span};
use firezone_tunnel::messages::gateway::{
AllowAccess, ClientIceCandidates, ClientsIceCandidates, ConnectionReady, EgressMessages,
IngressMessages, RejectAccess, RequestConnection,
@@ -137,10 +137,7 @@ impl Eventloop {
result,
Instant::now(),
) {
tracing::warn!(
error = anyhow_dyn_err(&e),
"Failed to set DNS resource NAT"
);
tracing::warn!("Failed to set DNS resource NAT: {e:#}");
};
continue;
@@ -462,7 +459,7 @@ impl Eventloop {
req.resource,
req.payload.map(|r| DnsResourceNatEntry::new(r, addresses)),
) {
tracing::warn!(error = anyhow_dyn_err(&e), client = %req.client_id, "Allow access request failed");
tracing::warn!(client = %req.client_id, "Allow access request failed: {e:#}");
};
}
}

View File

@@ -8,7 +8,7 @@ use firezone_bin_shared::{
linux::{tcp_socket_factory, udp_socket_factory},
TunDeviceManager,
};
use firezone_logging::anyhow_dyn_err;
use firezone_telemetry::Telemetry;
use firezone_tunnel::GatewayTunnel;
use phoenix_channel::get_user_agent;
@@ -75,7 +75,7 @@ fn main() -> ExitCode {
ExitCode::FAILURE
}
Err(e) => {
tracing::error!(error = anyhow_dyn_err(&e));
tracing::error!("{e:#}");
runtime.block_on(telemetry.stop_on_crash());
ExitCode::FAILURE

View File

@@ -2,7 +2,7 @@
use anyhow::Result;
use firezone_headless_client::known_dirs;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use rand::{thread_rng, RngCore};
use secrecy::{ExposeSecret, SecretString};
use serde::{Deserialize, Serialize};
@@ -110,8 +110,8 @@ impl Auth {
match this.get_token_from_disk() {
Err(error) => tracing::error!(
error = std_dyn_err(&error),
"Failed to load token from disk. Will start in signed-out state"
"Failed to load token from disk. Will start in signed-out state: {}",
err_with_src(&error)
),
Ok(Some(SessionAndToken { session, token: _ })) => {
this.state = State::SignedIn(session);
@@ -139,8 +139,8 @@ impl Auth {
Ok(()) | Err(keyring::Error::NoEntry) => {}
Err(error) => {
tracing::warn!(
error = std_dyn_err(&error),
"Couldn't delete token while signing out"
"Couldn't delete token while signing out: {}",
err_with_src(&error)
);
}
}

View File

@@ -13,7 +13,7 @@ use firezone_headless_client::{
IpcClientMsg::{self, SetDisabledResources},
IpcServerMsg, IpcServiceError, LogFilterReloader,
};
use firezone_logging::{anyhow_dyn_err, std_dyn_err};
use firezone_telemetry::Telemetry;
use futures::{
stream::{self, BoxStream},
@@ -307,7 +307,7 @@ impl<I: GuiIntegration> Controller<'_, I> {
tracing::debug!("Closing...");
if let Err(error) = self.ipc_client.disconnect_from_ipc().await {
tracing::error!(error = anyhow_dyn_err(&error), "ipc_client");
tracing::error!("ipc_client: {error:#}");
}
// Don't close telemetry here, `run` will close it.
@@ -410,7 +410,7 @@ impl<I: GuiIntegration> Controller<'_, I> {
tracing::error!("Can't clear logs, we're already waiting on another log-clearing operation");
}
if let Err(error) = logging::clear_gui_logs().await {
tracing::error!(error = anyhow_dyn_err(&error), "Failed to clear GUI logs");
tracing::error!("Failed to clear GUI logs: {error:#}");
}
self.ipc_client.send_msg(&IpcClientMsg::ClearLogs).await?;
self.clear_logs_callback = Some(completion_tx);
@@ -435,7 +435,7 @@ impl<I: GuiIntegration> Controller<'_, I> {
tracing::debug!("Ignoring deep-link; no local state");
}
Err(error) => {
tracing::error!(error = std_dyn_err(&error), "`handle_deep_link` failed");
tracing::error!("`handle_deep_link` failed: {error:#}");
}
}
}

View File

@@ -4,7 +4,7 @@
use super::{CantListen, FZ_SCHEME};
use anyhow::{Context, Result};
use firezone_bin_shared::BUNDLE_ID;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use secrecy::Secret;
use std::{
io,
@@ -71,8 +71,8 @@ async fn bind_to_pipe(pipe_path: &str) -> Result<named_pipe::NamedPipeServer> {
Ok(server) => return Ok(server),
Err(e) => {
tracing::debug!(
error = std_dyn_err(&e),
"`create_pipe_server` failed, sleeping... (attempt {i}/{NUM_ITERS})"
"`create_pipe_server` failed {}; sleeping... (attempt {i}/{NUM_ITERS})",
err_with_src(&e)
);
tokio::time::sleep(Duration::from_secs(1)).await;
}

View File

@@ -2,7 +2,7 @@
use anyhow::{bail, Context as _, Result};
use firezone_headless_client::{known_dirs, LogFilterReloader};
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use serde::Serialize;
use std::{
fs,
@@ -69,8 +69,8 @@ pub fn setup(directives: &str) -> Result<Handles> {
if let Err(error) = output_vt100::try_init() {
tracing::debug!(
error = std_dyn_err(&error),
"Failed to init vt100 terminal colors (expected in release builds and in CI)"
"Failed to init vt100 terminal colors (expected in release builds and in CI): {}",
err_with_src(&error)
);
}

View File

@@ -3,7 +3,6 @@ use clap::{Args, Parser};
use firezone_gui_client_common::{
self as common, controller::Failure, deep_link, settings::AdvancedSettings,
};
use firezone_logging::anyhow_dyn_err;
use firezone_telemetry as telemetry;
use tracing::instrument;
use tracing_subscriber::EnvFilter;
@@ -54,7 +53,7 @@ pub(crate) fn run() -> Result<()> {
Some(Cmd::OpenDeepLink(deep_link)) => {
let rt = tokio::runtime::Runtime::new()?;
if let Err(error) = rt.block_on(deep_link::open(&deep_link.url)) {
tracing::error!(error = anyhow_dyn_err(&error), "Error in `OpenDeepLink`");
tracing::error!("Error in `OpenDeepLink`: {error:#}");
}
Ok(())
}
@@ -79,7 +78,7 @@ pub(crate) fn run() -> Result<()> {
// Because of <https://github.com/firezone/firezone/issues/3567>,
// errors returned from `gui::run` may not be logged correctly
tracing::error!(error = anyhow_dyn_err(error));
tracing::error!("{error:#}");
}
Ok(result?)
}
@@ -131,7 +130,7 @@ fn run_gui(cli: Cli) -> Result<()> {
}
common::errors::show_error_dialog(anyhow.to_string())?;
tracing::error!(error = anyhow_dyn_err(&anyhow), "GUI failed");
tracing::error!("GUI failed: {anyhow:#}");
Err(anyhow)
}

View File

@@ -17,7 +17,7 @@ use firezone_gui_client_common::{
updates,
};
use firezone_headless_client::LogFilterReloader;
use firezone_logging::{anyhow_dyn_err, std_dyn_err};
use firezone_logging::err_with_src;
use firezone_telemetry as telemetry;
use futures::FutureExt;
use secrecy::{ExposeSecret as _, SecretString};
@@ -149,7 +149,7 @@ pub(crate) fn run(
// Closing the window fully seems to deallocate it or something.
if let Err(e) = window.hide() {
tracing::warn!(error = std_dyn_err(&e), "Failed to hide window")
tracing::warn!("Failed to hide window: {}", err_with_src(&e))
};
api.prevent_close();
}
@@ -174,7 +174,7 @@ pub(crate) fn run(
tokio::spawn(async move {
if let Err(error) = updates::checker_task(updates_tx, cli.debug_update_check).await
{
tracing::error!(error = anyhow_dyn_err(&error), "Error in updates::checker_task");
tracing::error!("Error in updates::checker_task: {error:#}");
}
});
@@ -182,7 +182,7 @@ pub(crate) fn run(
let ctlr_tx = ctlr_tx.clone();
tokio::spawn(async move {
if let Err(error) = smoke_test(ctlr_tx).await {
tracing::error!(error = anyhow_dyn_err(&error), "Error during smoke test, crashing on purpose so a dev can see our stacktraces");
tracing::error!("Error during smoke test, crashing on purpose so a dev can see our stacktraces: {error:#}");
unsafe { sadness_generator::raise_segfault() }
}
});
@@ -261,9 +261,9 @@ pub(crate) fn run(
1
}
Ok(Err(error)) => {
tracing::error!(error = std_dyn_err(&error), "run_controller returned an error");
tracing::error!("run_controller returned an error: {}", err_with_src(&error));
if let Err(e) = errors::show_error_dialog(error.user_friendly_msg()) {
tracing::error!(error = anyhow_dyn_err(&e), "Failed to show error dialog");
tracing::error!("Failed to show error dialog: {e:#}");
}
telemetry.stop_on_crash().await;
1
@@ -399,7 +399,7 @@ async fn accept_deep_links(mut server: deep_link::Server, ctlr_tx: CtlrTx) -> Re
tracing::debug!("Accepted deep-link but read 0 bytes, trying again ...");
}
Err(error) => {
tracing::warn!(error = anyhow_dyn_err(&error), "Failed to accept deep link")
tracing::warn!("Failed to accept deep link: {error:#}")
}
}
// We re-create the named pipe server every time we get a link, because of an oddity in the Windows API.

View File

@@ -1,7 +1,7 @@
use super::{ControllerRequest, CtlrTx};
use anyhow::{Context, Result};
use firezone_bin_shared::BUNDLE_ID;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use tauri::AppHandle;
pub(crate) async fn set_autostart(_enabled: bool) -> Result<()> {
@@ -77,8 +77,8 @@ pub(crate) fn show_clickable_notification(
if let Some(req) = req.take() {
if let Err(error) = tx.blocking_send(req) {
tracing::error!(
error = std_dyn_err(&error),
"User clicked on notification, but we couldn't tell `Controller`"
"User clicked on notification, but we couldn't tell `Controller`: {}",
err_with_src(&error)
);
}
}

View File

@@ -4,7 +4,7 @@ use firezone_gui_client_common::{
controller::{ControllerRequest, CtlrTx},
logging as common,
};
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use std::path::PathBuf;
use tauri_plugin_dialog::DialogExt as _;
@@ -14,15 +14,15 @@ pub(crate) async fn clear_logs(managed: tauri::State<'_, Managed>) -> Result<(),
if let Err(error) = managed.ctlr_tx.send(ControllerRequest::ClearLogs(tx)).await {
// Tauri will only log errors to the JS console for us, so log this ourselves.
tracing::error!(
error = std_dyn_err(&error),
"Error while asking `Controller` to clear logs"
"Error while asking `Controller` to clear logs: {}",
err_with_src(&error)
);
return Err(error.to_string());
}
if let Err(error) = rx.await {
tracing::error!(
error = std_dyn_err(&error),
"Error while awaiting log-clearing operation"
"Error while awaiting log-clearing operation: {}",
err_with_src(&error)
);
return Err(error.to_string());
}
@@ -63,7 +63,7 @@ fn show_export_dialog(app: &tauri::AppHandle, ctlr_tx: CtlrTx) -> Result<()> {
let path = match file_path.clone().into_path() {
Ok(path) => path,
Err(e) => {
tracing::warn!(error = std_dyn_err(&e), %file_path, "Invalid file path");
tracing::warn!(%file_path, "Invalid file path: {}", err_with_src(&e));
return;
}
};

View File

@@ -7,7 +7,6 @@
use anyhow::Result;
use firezone_bin_shared::platform::DnsControlMethod;
use firezone_logging::anyhow_dyn_err;
use std::net::IpAddr;
#[cfg(target_os = "linux")]
@@ -34,10 +33,7 @@ pub struct DnsController {
impl Drop for DnsController {
fn drop(&mut self) {
if let Err(error) = self.deactivate() {
tracing::error!(
error = anyhow_dyn_err(&error),
"Failed to deactivate DNS control"
);
tracing::error!("Failed to deactivate DNS control: {error:#}");
}
}
}

View File

@@ -16,7 +16,6 @@
use super::DnsController;
use anyhow::{Context as _, Result};
use firezone_bin_shared::platform::{DnsControlMethod, CREATE_NO_WINDOW, TUNNEL_UUID};
use firezone_logging::{anyhow_dyn_err, std_dyn_err};
use std::{io, net::IpAddr, os::windows::process::CommandExt, path::Path, process::Command};
use windows::Win32::System::GroupPolicy::{RefreshPolicyEx, RP_FORCE};
@@ -32,10 +31,10 @@ impl DnsController {
let hklm = winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
if let Err(error) = delete_subkey(&hklm, local_nrpt_path().join(NRPT_REG_KEY)) {
tracing::error!(error = std_dyn_err(&error), "Failed to delete local NRPT");
tracing::error!("Failed to delete local NRPT: {error:#}");
}
if let Err(error) = delete_subkey(&hklm, group_nrpt_path().join(NRPT_REG_KEY)) {
tracing::error!(error = std_dyn_err(&error), "Failed to delete group NRPT");
tracing::error!("Failed to delete group NRPT: {error:#}");
}
refresh_group_policy()?;
@@ -126,7 +125,7 @@ fn activate(dns_config: &[IpAddr]) -> Result<()> {
let hklm = winreg::RegKey::predef(winreg::enums::HKEY_LOCAL_MACHINE);
if let Err(e) = set_nameservers_on_interface(dns_config) {
tracing::warn!(error = anyhow_dyn_err(&e), "Failed to explicitly set nameservers on tunnel interface; DNS resources in WSL may not work");
tracing::warn!( "Failed to explicitly set nameservers on tunnel interface; DNS resources in WSL may not work: {e:#}");
}
// e.g. [100.100.111.1, 100.100.111.2] -> "100.100.111.1;100.100.111.2"

View File

@@ -10,7 +10,7 @@ use firezone_bin_shared::{
platform::{tcp_socket_factory, udp_socket_factory, DnsControlMethod},
TunDeviceManager, TOKEN_ENV_KEY,
};
use firezone_logging::{anyhow_dyn_err, sentry_layer, std_dyn_err, telemetry_span};
use firezone_logging::{err_with_src, sentry_layer, telemetry_span};
use firezone_telemetry::Telemetry;
use futures::{
future::poll_fn,
@@ -191,7 +191,7 @@ fn run_debug_ipc_service(cli: Cli) -> Result<()> {
))
.inspect(|_| rt.block_on(telemetry.stop()))
.inspect_err(|e| {
tracing::error!(error = anyhow_dyn_err(e), "IPC service failed");
tracing::error!("IPC service failed: {e:#}");
rt.block_on(telemetry.stop_on_crash())
})
@@ -361,10 +361,7 @@ impl<'a> Handler<'a> {
match poll_fn(|cx| self.next_event(cx, signals)).await {
Event::Callback(x) => {
if let Err(error) = self.handle_connlib_cb(x).await {
tracing::error!(
error = anyhow_dyn_err(&error),
"Error while handling connlib callback"
);
tracing::error!("Error while handling connlib callback: {error:#}");
continue;
}
}
@@ -378,10 +375,7 @@ impl<'a> Handler<'a> {
let _entered =
tracing::error_span!("handle_ipc_msg", msg = %msg_variant).entered();
if let Err(error) = self.handle_ipc_msg(msg).await {
tracing::error!(
error = anyhow_dyn_err(&error),
"Error while handling IPC message from client"
);
tracing::error!("Error while handling IPC message from client: {error:#}");
continue;
}
}
@@ -390,10 +384,7 @@ impl<'a> Handler<'a> {
break HandlerOk::ClientDisconnected;
}
Event::IpcError(error) => {
tracing::error!(
error = anyhow_dyn_err(&error),
"Error while deserializing IPC message"
);
tracing::error!("Error while deserializing IPC message: {error:#}");
continue;
}
Event::Terminate => {
@@ -531,7 +522,7 @@ impl<'a> Handler<'a> {
if let Err(e) = AtomicFile::new(&path, OverwriteBehavior::AllowOverwrite)
.write(|f| f.write_all(directives.as_bytes()))
{
tracing::warn!(path = %path.display(), %directives, error = std_dyn_err(&e), "Failed to write new log directives");
tracing::warn!(path = %path.display(), %directives, "Failed to write new log directives: {}", err_with_src(&e));
}
}
ClientMsg::Reset => {

View File

@@ -167,7 +167,6 @@ impl platform::Server {
mod tests {
use super::{platform::Server, *};
use anyhow::{bail, ensure, Result};
use firezone_logging::anyhow_dyn_err;
use futures::{SinkExt, StreamExt};
use std::time::Duration;
use tokio::{task::JoinHandle, time::timeout};
@@ -238,14 +237,14 @@ mod tests {
if let Err(panic) = &client_result {
tracing::error!(?panic, "Client panic");
} else if let Ok(Err(error)) = &client_result {
tracing::error!(error = anyhow_dyn_err(error), "Client error");
tracing::error!("Client error: {error:#}");
}
let server_result = server_task.await;
if let Err(panic) = &server_result {
tracing::error!(?panic, "Server panic");
} else if let Ok(Err(error)) = &server_result {
tracing::error!(error = anyhow_dyn_err(error), "Server error");
tracing::error!("Server error: {error:#}");
}
if client_result.is_err() || server_result.is_err() {

View File

@@ -1,7 +1,7 @@
use super::CliCommon;
use crate::signals;
use anyhow::{bail, Result};
use firezone_logging::anyhow_dyn_err;
use firezone_telemetry::Telemetry;
/// Cross-platform entry point for systemd / Windows services
@@ -27,7 +27,7 @@ pub(crate) fn run_ipc_service(cli: CliCommon) -> Result<()> {
))
.inspect(|_| rt.block_on(telemetry.stop()))
.inspect_err(|e| {
tracing::error!(error = anyhow_dyn_err(e), "IPC service failed");
tracing::error!("IPC service failed: {e:#}");
rt.block_on(telemetry.stop_on_crash())
})

View File

@@ -1,7 +1,6 @@
use crate::CliCommon;
use anyhow::{bail, Context as _, Result};
use firezone_bin_shared::platform::DnsControlMethod;
use firezone_logging::anyhow_dyn_err;
use firezone_telemetry::Telemetry;
use futures::future::{self, Either};
use std::{
@@ -197,10 +196,7 @@ fn service_run(arguments: Vec<OsString>) {
let (handle, log_filter_reloader) =
super::setup_logging(None).expect("Should be able to set up logging");
if let Err(error) = fallible_service_run(arguments, handle, log_filter_reloader) {
tracing::error!(
error = anyhow_dyn_err(&error),
"`fallible_windows_service_run` returned an error"
);
tracing::error!("`fallible_windows_service_run` returned an error: {error:#}");
}
}
@@ -286,7 +282,7 @@ fn fallible_service_run(
))
.inspect(|_| rt.block_on(telemetry.stop()))
.inspect_err(|e| {
tracing::error!(error = anyhow_dyn_err(e), "IPC service failed");
tracing::error!("IPC service failed: {e:#}");
rt.block_on(telemetry.stop_on_crash())
});

View File

@@ -1,9 +0,0 @@
use std::error::Error;
pub fn std_dyn_err(e: &(impl Error + 'static)) -> &(dyn Error + 'static) {
e as &(dyn Error + 'static)
}
pub fn anyhow_dyn_err(e: &anyhow::Error) -> &(dyn Error + 'static) {
e.as_ref()
}

View File

@@ -1,6 +1,5 @@
#![cfg_attr(test, allow(clippy::unwrap_used))]
mod dyn_err;
pub mod file;
mod format;
#[macro_use]
@@ -16,7 +15,6 @@ use tracing_subscriber::{
util::SubscriberInitExt, EnvFilter, Layer, Registry,
};
pub use dyn_err::{anyhow_dyn_err, std_dyn_err};
pub use err_with_sources::{err_with_src, ErrorWithSources};
pub use format::Format;

View File

@@ -9,7 +9,7 @@ macro_rules! unwrap_or_warn {
Err(e) => {
let error: &dyn ::std::error::Error = e.as_ref();
::tracing::warn!(error, $($arg)*)
::tracing::debug!($($arg)*, $crate::err_with_src(error))
}
}
};

View File

@@ -15,7 +15,7 @@ use std::{io, mem};
use backoff::backoff::Backoff;
use backoff::ExponentialBackoff;
use base64::Engine;
use firezone_logging::{err_with_src, std_dyn_err, telemetry_span};
use firezone_logging::{err_with_src, telemetry_span};
use futures::future::BoxFuture;
use futures::{FutureExt, SinkExt, StreamExt};
use heartbeat::{Heartbeat, MissedLastHeartbeat};
@@ -384,7 +384,7 @@ where
return Poll::Ready(Ok(Event::Closed));
}
Poll::Ready(Err(e)) => {
tracing::warn!(error = std_dyn_err(&e), "Error while closing websocket");
tracing::warn!("Error while closing websocket: {}", err_with_src(&e));
return Poll::Ready(Ok(Event::Closed));
}
@@ -510,10 +510,7 @@ where
continue;
}
Err(e) => {
tracing::warn!(
error = std_dyn_err(&e),
"Failed to deserialize message"
);
tracing::warn!("Failed to deserialize message: {}", err_with_src(&e));
continue;
}
};

View File

@@ -4,7 +4,7 @@ use anyhow::{bail, Context, Result};
use backoff::ExponentialBackoffBuilder;
use clap::Parser;
use firezone_bin_shared::http_health_check;
use firezone_logging::{anyhow_dyn_err, sentry_layer, std_dyn_err};
use firezone_logging::{err_with_src, sentry_layer};
use firezone_relay::sockets::Sockets;
use firezone_relay::{
sockets, AddressFamily, AllocationPort, ChannelData, ClientSocket, Command, IpStack,
@@ -120,7 +120,7 @@ fn main() {
match runtime.block_on(try_main(args)) {
Ok(()) => runtime.block_on(telemetry.stop()),
Err(e) => {
tracing::error!(error = anyhow_dyn_err(&e));
tracing::error!("{e:#}");
runtime.block_on(telemetry.stop_on_crash());
std::process::exit(1);
@@ -407,7 +407,7 @@ where
recipient.into_socket(),
Cow::Owned(payload),
) {
tracing::warn!(target: "relay", error = std_dyn_err(&e), %recipient, "Failed to send message");
tracing::warn!(target: "relay", %recipient, "Failed to send message: {}", err_with_src(&e));
}
}
Command::CreateAllocation { port, family } => {
@@ -478,7 +478,7 @@ where
peer.into_socket(),
Cow::Borrowed(payload),
) {
tracing::warn!(target: "relay", error = std_dyn_err(&e), %peer, "Failed to relay data to peer");
tracing::warn!(target: "relay", %peer, "Failed to relay data to peer: {}", err_with_src(&e));
}
};
continue;
@@ -504,13 +504,13 @@ where
client.into_socket(),
Cow::Borrowed(&self.buffer[..total_length]),
) {
tracing::warn!(target: "relay", error = std_dyn_err(&e), %client, "Failed to relay data to client");
tracing::warn!(target: "relay", %client, "Failed to relay data to client: {}", err_with_src(&e));
};
};
continue;
}
Poll::Ready(Err(sockets::Error::Io(e))) => {
tracing::warn!(target: "relay", error = std_dyn_err(&e), "Error while receiving message");
tracing::warn!(target: "relay", "Error while receiving message: {}", err_with_src(&e));
continue;
}
Poll::Ready(Err(sockets::Error::MioTaskCrashed(e))) => return Poll::Ready(Err(e)), // Fail the event-loop. We can't operate without the `mio` worker-task.

View File

@@ -12,7 +12,7 @@ use crate::{ClientSocket, IpStack, PeerSocket};
use anyhow::Result;
use bytecodec::EncodeExt;
use core::fmt;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use hex_display::HexDisplayExt as _;
use opentelemetry::metrics::{Counter, UpDownCounter};
use opentelemetry::KeyValue;
@@ -338,7 +338,7 @@ where
{
Ok(message) => message,
Err(e) => {
tracing::warn!(target: "relay", error = std_dyn_err(&e), "Failed to create error response");
tracing::warn!(target: "relay", "Failed to create error response: {}", err_with_src(&e));
return None;
}
}
@@ -947,7 +947,7 @@ where
Ok(message) => message,
Err(e) => {
let (error_response, msg) = make_error_response(ServerError, request);
tracing::warn!(target: "relay", error = std_dyn_err(&e), "{msg}: Failed to authenticate message");
tracing::warn!(target: "relay", "{msg}: Failed to authenticate message: {}", err_with_src(&e));
AuthenticatedMessage::new_dangerous_unauthenticated(error_response)
}

View File

@@ -1,5 +1,5 @@
use bytes::Buf as _;
use firezone_logging::std_dyn_err;
use firezone_logging::err_with_src;
use quinn_udp::Transmit;
use std::collections::HashMap;
use std::fmt;
@@ -380,9 +380,8 @@ impl UdpSocket {
Ok(src_ip) => src_ip,
Err(e) => {
tracing::trace!(
error = std_dyn_err(&e),
dst = %dst.ip(),
"No available interface for packet"
"No available interface for packet: {}", err_with_src(&e)
);
return Ok(None); // Not an error because we log it above already.
}