Skip to content

Commit eff4440

Browse files
committed
chore: Use tracing instead of log and simplelog
Structured logging from `tracing` meets our needs better, especially in the parts of bpf-linker which sanitize the debug info. Fixes #177
1 parent c9bcf78 commit eff4440

File tree

5 files changed

+73
-82
lines changed

5 files changed

+73
-82
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ edition = "2021"
1818
[dependencies]
1919
# cli deps
2020
clap = { version = "4.5.0", features = ["derive"] }
21-
simplelog = { version = "0.12.1" }
21+
tracing-appender = "0.2"
22+
tracing-subscriber = { version = "0.3", features = ["env-filter", "registry"] }
23+
tracing-tree = "0.3"
2224

2325
# lib deps
2426
ar = { version = "0.9.0" }
@@ -28,6 +30,7 @@ libc = { version = "0.2.153" }
2830
llvm-sys = { features = ["disable-alltargets-init"], version = "180.0.0-rc2" }
2931
log = { version = "0.4.20" }
3032
thiserror = { version = "1.0.57" }
33+
tracing = "0.1"
3134

3235
[dev-dependencies]
3336
compiletest_rs = { version = "0.10.1" }

src/bin/bpf-linker.rs

Lines changed: 50 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,15 @@
33
#[cfg(feature = "rust-llvm")]
44
extern crate aya_rustc_llvm_proxy;
55

6-
use std::{
7-
env,
8-
fs::{self, OpenOptions},
9-
os::fd::AsRawFd,
10-
path::PathBuf,
11-
str::FromStr,
12-
};
6+
use std::{env, fs, io, path::PathBuf, str::FromStr};
137

148
use bpf_linker::{Cpu, Linker, LinkerOptions, OptLevel, OutputType};
159
use clap::Parser;
16-
use libc::dup2;
17-
use log::info;
18-
use simplelog::{
19-
ColorChoice, Config, LevelFilter, SimpleLogger, TermLogger, TerminalMode, WriteLogger,
20-
};
2110
use thiserror::Error;
11+
use tracing::{info, Level, Subscriber};
12+
use tracing_appender::non_blocking::WorkerGuard;
13+
use tracing_subscriber::{fmt::MakeWriter, prelude::*, EnvFilter};
14+
use tracing_tree::HierarchicalLayer;
2215

2316
#[derive(Debug, Error)]
2417
enum CliError {
@@ -65,6 +58,7 @@ impl FromStr for CliOutputType {
6558
}))
6659
}
6760
}
61+
6862
#[derive(Debug, Parser)]
6963
struct CommandLine {
7064
/// LLVM target triple. When not provided, the target is inferred from the inputs
@@ -109,9 +103,10 @@ struct CommandLine {
109103
#[clap(long, value_name = "path")]
110104
log_file: Option<PathBuf>,
111105

112-
/// Set the log level. Can be one of `off`, `info`, `warn`, `debug`, `trace`.
106+
/// Set the log level. If not specified, no logging is used. Can be one of
107+
/// `error`, `warn`, `info`, `debug`, `trace`.
113108
#[clap(long, value_name = "level")]
114-
log_level: Option<LevelFilter>,
109+
log_level: Option<Level>,
115110

116111
/// Try hard to unroll loops. Useful when targeting kernels that don't support loops
117112
#[clap(long)]
@@ -155,6 +150,18 @@ struct CommandLine {
155150
_debug: bool,
156151
}
157152

153+
/// Returns a [`HierarchicalLayer`](tracing_tree::HierarchicalLayer) for the
154+
/// given `writer`.
155+
fn tracing_layer<W>(writer: W) -> HierarchicalLayer<W>
156+
where
157+
W: for<'writer> MakeWriter<'writer> + 'static,
158+
{
159+
const TRACING_IDENT: usize = 2;
160+
HierarchicalLayer::new(TRACING_IDENT)
161+
.with_indent_lines(true)
162+
.with_writer(writer)
163+
}
164+
158165
fn main() {
159166
let args = env::args().map(|arg| {
160167
if arg == "-flavor" {
@@ -191,51 +198,38 @@ fn main() {
191198
error("no input files", clap::error::ErrorKind::TooFewValues);
192199
}
193200

194-
let env_log_level = match env::var("RUST_LOG") {
195-
Ok(s) if !s.is_empty() => match s.parse::<LevelFilter>() {
196-
Ok(l) => Some(l),
197-
Err(e) => error(
198-
&format!("invalid RUST_LOG value: {e}"),
199-
clap::error::ErrorKind::InvalidValue,
200-
),
201-
},
202-
_ => None,
203-
};
204-
let log_level = log_level.or(env_log_level).unwrap_or(LevelFilter::Warn);
205-
if let Some(log_file) = log_file {
206-
let log_file = match OpenOptions::new().create(true).append(true).open(log_file) {
207-
Ok(f) => {
208-
// Use dup2 to duplicate stderr fd to the log file fd
209-
let result = unsafe { dup2(f.as_raw_fd(), std::io::stderr().as_raw_fd()) };
210-
211-
if result == -1 {
212-
error(
213-
&format!(
214-
"failed to duplicate stderr: {}",
215-
std::io::Error::last_os_error()
216-
),
217-
clap::error::ErrorKind::Io,
218-
)
219-
}
220-
f
221-
}
222-
Err(e) => {
223-
error(
224-
&format!("failed to open log file: {e:?}"),
225-
clap::error::ErrorKind::Io,
201+
// Configure tracing.
202+
if let Some(log_level) = log_level {
203+
let subscriber_registry = tracing_subscriber::registry()
204+
.with(EnvFilter::from_default_env().add_directive(log_level.into()));
205+
let (subscriber, _guard): (
206+
Box<dyn Subscriber + Send + Sync + 'static>,
207+
Option<WorkerGuard>,
208+
) = match log_file {
209+
Some(log_file) => {
210+
let file_appender = tracing_appender::rolling::never(
211+
log_file.parent().unwrap_or_else(|| {
212+
error("invalid log_file", clap::error::ErrorKind::InvalidValue)
213+
}),
214+
log_file.file_name().unwrap_or_else(|| {
215+
error("invalid log_file", clap::error::ErrorKind::InvalidValue)
216+
}),
226217
);
218+
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
219+
let subscriber = subscriber_registry
220+
.with(tracing_layer(io::stdout))
221+
.with(tracing_layer(non_blocking));
222+
223+
(Box::new(subscriber), Some(_guard))
224+
}
225+
None => {
226+
let subscriber = subscriber_registry.with(tracing_layer(io::stderr));
227+
(Box::new(subscriber), None)
227228
}
228229
};
229-
WriteLogger::init(log_level, Config::default(), log_file).unwrap();
230-
} else if TermLogger::init(
231-
log_level,
232-
Config::default(),
233-
TerminalMode::Mixed,
234-
ColorChoice::Auto,
235-
)
236-
.is_err()
237-
{
238-
SimpleLogger::init(log_level, Config::default()).unwrap();
230+
if let Err(e) = tracing::subscriber::set_global_default(subscriber) {
231+
error(&e.to_string(), clap::error::ErrorKind::Format);
232+
}
239233
}
240234

241235
info!(

src/linker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use llvm_sys::{
2222
prelude::{LLVMContextRef, LLVMModuleRef},
2323
target_machine::{LLVMCodeGenFileType, LLVMDisposeTargetMachine, LLVMTargetMachineRef},
2424
};
25-
use log::{debug, error, info, warn};
2625
use thiserror::Error;
26+
use tracing::{debug, error, info, warn};
2727

2828
use crate::llvm;
2929

src/llvm/di.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88

99
use gimli::{DW_TAG_pointer_type, DW_TAG_structure_type, DW_TAG_variant_part};
1010
use llvm_sys::{core::*, debuginfo::*, prelude::*};
11-
use log::{trace, warn};
11+
use tracing::{span, trace, warn, Level};
1212

1313
use super::types::{
1414
di::DIType,
@@ -204,16 +204,13 @@ impl DISanitizer {
204204
}
205205

206206
// navigate the tree of LLVMValueRefs (DFS-pre-order)
207-
fn visit_item(&mut self, mut item: Item, depth: usize) {
207+
fn visit_item(&mut self, mut item: Item) {
208208
let value_ref = item.value_ref();
209209
let value_id = item.value_id();
210210

211-
let log_prefix = "";
212-
let log_depth = depth * 4;
213-
trace!(
214-
"{log_prefix:log_depth$}visiting item: {item:?} id: {} value: {value_ref:?}",
215-
item.value_id(),
216-
);
211+
let item_span = span!(Level::TRACE, "item", value_id);
212+
let _enter = item_span.enter();
213+
trace!(?item, value = ?value_ref, "visiting item");
217214

218215
let value = match (value_ref, &item) {
219216
// An operand with no value is valid and means that the operand is
@@ -235,7 +232,7 @@ impl DISanitizer {
235232

236233
let first_visit = self.visited_nodes.insert(value_id);
237234
if !first_visit {
238-
trace!("{log_prefix:log_depth$}already visited");
235+
trace!("already visited");
239236
return;
240237
}
241238

@@ -247,34 +244,31 @@ impl DISanitizer {
247244

248245
if let Some(operands) = value.operands() {
249246
for (index, operand) in operands.enumerate() {
250-
self.visit_item(
251-
Item::Operand(Operand {
252-
parent: value_ref,
253-
value: operand,
254-
index: index as u32,
255-
}),
256-
depth + 1,
257-
)
247+
self.visit_item(Item::Operand(Operand {
248+
parent: value_ref,
249+
value: operand,
250+
index: index as u32,
251+
}))
258252
}
259253
}
260254

261255
if let Some(entries) = value.metadata_entries() {
262256
for (index, (metadata, kind)) in entries.iter().enumerate() {
263257
let metadata_value = unsafe { LLVMMetadataAsValue(self.context, metadata) };
264-
self.visit_item(Item::MetadataEntry(metadata_value, kind, index), depth + 1);
258+
self.visit_item(Item::MetadataEntry(metadata_value, kind, index));
265259
}
266260
}
267261

268262
// If an item has sub items that are not operands nor metadata entries, we need to visit
269263
// those too.
270264
if let Value::Function(fun) = value {
271265
for param in fun.params() {
272-
self.visit_item(Item::FunctionParam(param), depth + 1);
266+
self.visit_item(Item::FunctionParam(param));
273267
}
274268

275269
for basic_block in fun.basic_blocks() {
276270
for instruction in basic_block.instructions_iter() {
277-
self.visit_item(Item::Instruction(instruction), depth + 1);
271+
self.visit_item(Item::Instruction(instruction));
278272
}
279273
}
280274
}
@@ -288,14 +282,14 @@ impl DISanitizer {
288282
self.replace_operands = self.fix_subprogram_linkage(exported_symbols);
289283

290284
for value in module.globals_iter() {
291-
self.visit_item(Item::GlobalVariable(value), 0);
285+
self.visit_item(Item::GlobalVariable(value));
292286
}
293287
for value in module.global_aliases_iter() {
294-
self.visit_item(Item::GlobalAlias(value), 0);
288+
self.visit_item(Item::GlobalAlias(value));
295289
}
296290

297291
for function in module.functions_iter() {
298-
self.visit_item(Item::Function(function), 0);
292+
self.visit_item(Item::Function(function));
299293
}
300294

301295
unsafe { LLVMDisposeDIBuilder(self.builder) };

src/llvm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use llvm_sys::{
4848
},
4949
LLVMAttributeFunctionIndex, LLVMLinkage, LLVMVisibility,
5050
};
51-
use log::{debug, error};
51+
use tracing::{debug, error};
5252

5353
use crate::OptLevel;
5454

0 commit comments

Comments
 (0)