Skip to content

Commit 10e73a2

Browse files
lnyngfacebook-github-bot
authored andcommitted
Setup log and store dir with systemd (#8241)
Summary: Pull Request resolved: #8241 Logging and storage directory is better setup by systemd. If the log dir is not created, let's just log errors to some temporary file instead. Reviewed By: dschatzberg Differential Revision: D70026615 fbshipit-source-id: 412444c8135af54edc516164a818ecd72ecefb4a
1 parent ba936d0 commit 10e73a2

File tree

5 files changed

+37
-120
lines changed

5 files changed

+37
-120
lines changed

below/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ store = { package = "below-store", version = "0.8.1", path = "store" }
4444
tar = "0.4.43"
4545
tempfile = "3.15"
4646
tokio = { version = "1.41.0", features = ["full", "test-util", "tracing"] }
47-
uzers = "0.11.3"
4847
view = { package = "below-view", version = "0.8.1", path = "view" }
4948

5049
[dev-dependencies]

below/config/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ pub struct BelowConfig {
5656
impl Default for BelowConfig {
5757
fn default() -> Self {
5858
BelowConfig {
59-
log_dir: BELOW_DEFAULT_LOG.into(),
60-
store_dir: BELOW_DEFAULT_STORE.into(),
59+
log_dir: std::env::var_os("LOGS_DIRECTORY")
60+
.map_or(BELOW_DEFAULT_LOG.into(), PathBuf::from),
61+
store_dir: std::env::var_os("LOGS_DIRECTORY").map_or(BELOW_DEFAULT_STORE.into(), |d| {
62+
PathBuf::from(d).join("store")
63+
}),
6164
cgroup_root: cgroupfs::DEFAULT_CG_ROOT.into(),
6265
cgroup_filter_out: String::new(),
6366
enable_gpu_stats: false,

below/src/main.rs

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
use std::cell::RefCell;
2020
use std::fs;
2121
use std::io;
22-
use std::os::unix::fs::PermissionsExt;
2322
use std::path::PathBuf;
2423
use std::process::exit;
2524
use std::rc::Rc;
@@ -54,8 +53,6 @@ use tar::Archive;
5453
use tar::Builder as TarBuilder;
5554
use tempfile::TempDir;
5655
use tokio::runtime::Builder as TB;
57-
use uzers::get_current_uid;
58-
use uzers::get_user_by_uid;
5956

6057
mod exitstat;
6158
#[cfg(test)]
@@ -331,13 +328,6 @@ pub enum Service {
331328
Off,
332329
}
333330

334-
// Whether or not to redirect log to stderr on fs failure
335-
#[derive(PartialEq)]
336-
pub enum RedirectLogOnFail {
337-
On,
338-
Off,
339-
}
340-
341331
fn bump_memlock_rlimit() -> Result<()> {
342332
// TODO(T78976996) remove the fbcode_gate once we can exit stats is
343333
// enabled for opensource
@@ -355,44 +345,6 @@ fn bump_memlock_rlimit() -> Result<()> {
355345
Ok(())
356346
}
357347

358-
fn create_log_dir(path: &PathBuf) -> Result<()> {
359-
if path.exists() && !path.is_dir() {
360-
bail!("{} exists and is not a directory", path.to_string_lossy());
361-
}
362-
363-
if !path.is_dir() {
364-
match fs::create_dir_all(path) {
365-
Ok(()) => {}
366-
Err(e) => {
367-
bail!(
368-
"Failed to create dir {}: {}\nTry sudo.",
369-
path.to_string_lossy(),
370-
e
371-
);
372-
}
373-
}
374-
}
375-
376-
let dir = fs::File::open(path).unwrap();
377-
let mut perm = dir.metadata().unwrap().permissions();
378-
379-
if perm.mode() & 0o777 != 0o777 {
380-
perm.set_mode(0o777);
381-
match dir.set_permissions(perm) {
382-
Ok(()) => {}
383-
Err(e) => {
384-
bail!(
385-
"Failed to set permissions on {}: {}",
386-
path.to_string_lossy(),
387-
e
388-
);
389-
}
390-
}
391-
}
392-
393-
Ok(())
394-
}
395-
396348
// Exitstat runs a bpf program that hooks into process exit events. This allows below to keep
397349
// track of processes whose lifetimes are shorter than polling interval.
398350
fn start_exitstat(
@@ -407,7 +359,7 @@ fn start_exitstat(
407359
.spawn(move || {
408360
match exit_driver.drive() {
409361
Ok(_) => {}
410-
Err(e) => bpf_err_send.send(e).unwrap(),
362+
Err(e) => bpf_err_send.send(e).expect("Failed to send error"),
411363
};
412364
})
413365
.expect("Failed to spawn thread");
@@ -605,24 +557,14 @@ pub fn run<F>(
605557
debug: bool,
606558
below_config: &BelowConfig,
607559
_service: Service,
608-
redirect: RedirectLogOnFail,
609560
command: F,
610561
) -> i32
611562
where
612563
F: FnOnce(init::InitToken, &BelowConfig, slog::Logger, Receiver<Error>) -> Result<()>,
613564
{
614565
let (err_sender, err_receiver) = channel();
615-
let mut log_dir = below_config.log_dir.clone();
616-
let user = get_user_by_uid(get_current_uid()).expect("Failed to get current user for logging");
617-
618-
log_dir.push(format!("error_{}.log", user.name().to_string_lossy()));
619-
620-
if let Err(e) = create_log_dir(&below_config.log_dir) {
621-
eprintln!("{:#}", e);
622-
return 1;
623-
}
624-
625-
let logger = logging::setup(init, log_dir, debug, redirect);
566+
let log_path = below_config.log_dir.join("below.log");
567+
let logger = logging::setup(init, log_path, debug);
626568
setup_log_on_panic(logger.clone());
627569

628570
match Signals::new([signal_hook::consts::SIGINT, signal_hook::consts::SIGTERM]) {
@@ -640,7 +582,9 @@ where
640582
}
641583
term_now = true;
642584
error!(logger, "Stop signal received: {}, exiting.", signal);
643-
err_sender.send(anyhow!(StopSignal { signal })).unwrap();
585+
err_sender
586+
.send(anyhow!(StopSignal { signal }))
587+
.expect("Failed to send stop signal");
644588
}
645589
})
646590
.expect("Failed to spawn thread");
@@ -731,7 +675,6 @@ fn real_main(init: init::InitToken) {
731675
debug,
732676
below_config,
733677
Service::Off,
734-
RedirectLogOnFail::On,
735678
|_, below_config, logger, errs| {
736679
live(
737680
init,
@@ -763,7 +706,6 @@ fn real_main(init: init::InitToken) {
763706
debug,
764707
below_config,
765708
Service::On(*port),
766-
RedirectLogOnFail::Off,
767709
|init, below_config, logger, errs| {
768710
record(
769711
init,
@@ -800,7 +742,6 @@ fn real_main(init: init::InitToken) {
800742
debug,
801743
below_config,
802744
Service::Off,
803-
RedirectLogOnFail::Off,
804745
|_, below_config, logger, errs| {
805746
replay(
806747
logger,
@@ -834,7 +775,6 @@ fn real_main(init: init::InitToken) {
834775
debug,
835776
below_config,
836777
Service::Off,
837-
RedirectLogOnFail::Off,
838778
|_, below_config, logger, _errs| {
839779
snapshot(
840780
logger,
@@ -858,7 +798,6 @@ fn real_main(init: init::InitToken) {
858798
debug,
859799
below_config,
860800
Service::Off,
861-
RedirectLogOnFail::Off,
862801
|_, below_config, logger, _errs| dump_store(logger, time, below_config, json),
863802
)
864803
}
@@ -884,7 +823,6 @@ fn real_main(init: init::InitToken) {
884823
debug,
885824
below_config,
886825
Service::Off,
887-
RedirectLogOnFail::Off,
888826
|_, below_config, logger, _errs| {
889827
convert_store(
890828
logger,
@@ -918,7 +856,6 @@ fn real_main(init: init::InitToken) {
918856
debug,
919857
below_config,
920858
Service::Off,
921-
RedirectLogOnFail::Off,
922859
|_, _below_config, logger, errs| {
923860
dump::run(logger, errs, store_dir, host, port, snapshot, cmd)
924861
},
@@ -961,7 +898,7 @@ fn replay(
961898
tarball.unpack(&snapshot_dir)?;
962899
// Find and append the name of the original snapshot directory
963900
for path in fs::read_dir(&snapshot_dir)? {
964-
snapshot_dir.push(path.unwrap().file_name());
901+
snapshot_dir.push(path?.file_name());
965902
}
966903
new_advance_local(logger.clone(), snapshot_dir, timestamp)
967904
}

below/src/open_source/logging.rs

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,60 +23,37 @@ use slog::Drain;
2323
use crate::init::InitToken;
2424
use crate::logutil::CommandPaletteDrain;
2525
use crate::logutil::CompoundDecorator;
26-
use crate::RedirectLogOnFail;
2726

28-
fn setup_log<T: 'static + std::io::Write + std::marker::Send>(
29-
_init: InitToken,
30-
file: T,
31-
_debug: bool,
32-
error: Option<std::io::Error>,
33-
) -> slog::Logger {
27+
fn setup_log(_init: InitToken, file: std::fs::File, _debug: bool) -> slog::Logger {
3428
let decorator = CompoundDecorator::new(file, std::io::stderr());
3529
let drain = slog_term::FullFormat::new(decorator).build().fuse();
3630
let drain = CommandPaletteDrain::new(drain).fuse();
3731

38-
let logger = slog::Logger::root(drain, o!());
39-
40-
// When we want to redirect the log, also log the open file err to stderr
41-
if let Some(e) = error {
42-
error!(
43-
logger,
44-
"Fail to open log path: {}\n.Redirecting all log to stderr.", e
45-
);
46-
}
47-
48-
logger
32+
slog::Logger::root(drain, o!())
4933
}
5034

51-
pub fn setup(
52-
init: InitToken,
53-
path: PathBuf,
54-
debug: bool,
55-
redirect: RedirectLogOnFail,
56-
) -> slog::Logger {
57-
let file_maybe = OpenOptions::new().create(true).append(true).open(path);
58-
59-
if let Ok(file) = file_maybe.as_ref() {
60-
// We don't need to worry about the permission setting here since
61-
// as long as the FS is writable, user can run with sudo to reset
62-
// file permission.
63-
let mut perms = file
64-
.metadata()
65-
.expect("failed to get file metadata for logfile")
66-
.permissions();
67-
if perms.mode() & 0o777 != 0o666 {
68-
// World readable/writable -- the devil's permissions
69-
perms.set_mode(0o666);
70-
file.set_permissions(perms)
71-
.expect("failed to set permissions on logfile");
35+
pub fn setup(init: InitToken, path: PathBuf, debug: bool) -> slog::Logger {
36+
let file = match OpenOptions::new().create(true).append(true).open(path) {
37+
Ok(f) => f,
38+
Err(_) => {
39+
let temp_log_path = tempfile::Builder::new()
40+
.prefix("below.log.")
41+
.keep(true)
42+
.tempfile()
43+
.expect("Failed to create tempfile")
44+
.path()
45+
.to_path_buf();
46+
eprintln!(
47+
"Log path unavailable. Logging to {}",
48+
temp_log_path.to_string_lossy()
49+
);
50+
OpenOptions::new()
51+
.create(true)
52+
.append(true)
53+
.open(temp_log_path)
54+
.expect("Failed to open tempfile")
7255
}
73-
} else if redirect == RedirectLogOnFail::Off {
74-
// No redirect, let it crash.
75-
file_maybe.as_ref().expect("Failed to open log path");
76-
}
56+
};
7757

78-
match file_maybe {
79-
Ok(f) => setup_log(init, f, debug, None),
80-
Err(e) => setup_log(init, std::io::stderr(), debug, Some(e)),
81-
}
58+
setup_log(init, file, debug)
8259
}

etc/below.service

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Description=below system monitor recording daemon
1717
After=time-sync.target
1818

1919
[Service]
20+
LogsDirectory=below
2021
ExecStart=/usr/bin/below record --retain-for-s 604800 --compress
2122
# Enable backtraces in errors
2223
Environment=RUST_LIB_BACKTRACE=1

0 commit comments

Comments
 (0)