54a33a7a15
The service_logs declaration hunk was targeting line 48 instead of 49, causing patch to insert it inside the let persistent_log chain instead of inside the thread spawn closure.
129 lines
4.8 KiB
Diff
129 lines
4.8 KiB
Diff
diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs
|
|
index 070de3d6..4ea5365d 100644
|
|
--- a/logd/src/scheme.rs
|
|
+++ b/logd/src/scheme.rs
|
|
@@ -1,2 +1,2 @@
|
|
-use std::collections::{BTreeMap, VecDeque};
|
|
-use std::fs::{File, OpenOptions};
|
|
+use std::collections::{BTreeMap, HashMap, VecDeque};
|
|
+use std::fs::{File, OpenOptions, rename};
|
|
@@ -5,0 +6 @@ use std::os::fd::{FromRawFd, RawFd};
|
|
+use std::path::PathBuf;
|
|
@@ -13,0 +15,5 @@ use syscall::schemev2::NewFdFlags;
|
|
+const LOG_DIR: &str = "/var/log";
|
|
+const MAX_LOG_SIZE: u64 = 10 * 1024 * 1024;
|
|
+const MAX_ROTATED_FILES: u32 = 5;
|
|
+const MEMORY_LOG_LIMIT: usize = 1000;
|
|
+
|
|
@@ -31 +37 @@ enum OutputCmd {
|
|
- Log(Vec<u8>),
|
|
+ Log { context: String, line: Vec<u8> },
|
|
@@ -34,0 +41,52 @@ enum OutputCmd {
|
|
+struct LogFile {
|
|
+ file: File,
|
|
+ path: PathBuf,
|
|
+ bytes_written: u64,
|
|
+}
|
|
+
|
|
+impl LogFile {
|
|
+ fn open(path: PathBuf) -> std::io::Result<Self> {
|
|
+ let file = OpenOptions::new()
|
|
+ .create(true)
|
|
+ .append(true)
|
|
+ .open(&path)?;
|
|
+ let metadata = file.metadata()?;
|
|
+ Ok(LogFile {
|
|
+ file,
|
|
+ path,
|
|
+ bytes_written: metadata.len(),
|
|
+ })
|
|
+ }
|
|
+
|
|
+ fn write(&mut self, data: &[u8]) -> std::io::Result<()> {
|
|
+ self.file.write_all(data)?;
|
|
+ self.file.flush()?;
|
|
+ self.bytes_written += data.len() as u64;
|
|
+ Ok(())
|
|
+ }
|
|
+
|
|
+ fn maybe_rotate(&mut self) -> std::io::Result<()> {
|
|
+ if self.bytes_written < MAX_LOG_SIZE {
|
|
+ return Ok(());
|
|
+ }
|
|
+
|
|
+ drop(std::mem::replace(&mut self.file, unsafe { File::from_raw_fd(-1) }));
|
|
+
|
|
+ for i in (1..MAX_ROTATED_FILES).rev() {
|
|
+ let old_path = self.path.with_extension(format!("log.{}", i));
|
|
+ let new_path = self.path.with_extension(format!("log.{}", i + 1));
|
|
+ let _ = rename(&old_path, &new_path);
|
|
+ }
|
|
+
|
|
+ let backup_path = self.path.with_extension("log.1");
|
|
+ let _ = rename(&self.path, &backup_path);
|
|
+
|
|
+ self.file = OpenOptions::new()
|
|
+ .create(true)
|
|
+ .append(true)
|
|
+ .open(&self.path)?;
|
|
+ self.bytes_written = 0;
|
|
+ Ok(())
|
|
+ }
|
|
+}
|
|
+
|
|
@@ -49,0 +109,4 @@ impl<'sock> LogScheme<'sock> {
|
|
+ let mut service_logs: HashMap<String, LogFile> = HashMap::new();
|
|
+
|
|
+ let _ = std::fs::create_dir_all(LOG_DIR);
|
|
+
|
|
@@ -52 +114 @@ impl<'sock> LogScheme<'sock> {
|
|
- OutputCmd::Log(line) => {
|
|
+ OutputCmd::Log { context, line } => {
|
|
@@ -55,0 +118,22 @@ impl<'sock> LogScheme<'sock> {
|
|
+
|
|
+ let service_name = context.split(':').next().unwrap_or("unknown");
|
|
+ if !service_name.is_empty() {
|
|
+ let log_path = PathBuf::from(LOG_DIR).join(format!("{}.log", service_name));
|
|
+ let entry = service_logs.entry(service_name.to_string()).or_insert_with(|| {
|
|
+ LogFile::open(log_path).unwrap_or_else(|_| {
|
|
+ LogFile::open(PathBuf::from("/dev/null")).unwrap()
|
|
+ })
|
|
+ });
|
|
+ let _ = entry.write(&line);
|
|
+ let _ = entry.maybe_rotate();
|
|
+ }
|
|
+
|
|
+ let system_path = PathBuf::from(LOG_DIR).join("system.log");
|
|
+ let system_entry = service_logs.entry("system".to_string()).or_insert_with(|| {
|
|
+ LogFile::open(system_path).unwrap_or_else(|_| {
|
|
+ LogFile::open(PathBuf::from("/dev/null")).unwrap()
|
|
+ })
|
|
+ });
|
|
+ let _ = system_entry.write(&line);
|
|
+ let _ = system_entry.maybe_rotate();
|
|
+
|
|
@@ -57,2 +141 @@ impl<'sock> LogScheme<'sock> {
|
|
- // Keep a limited amount of logs for backfilling to bound memory usage
|
|
- while logs.len() > 1000 {
|
|
+ while logs.len() > MEMORY_LOG_LIMIT {
|
|
@@ -68 +150,0 @@ impl<'sock> LogScheme<'sock> {
|
|
-
|
|
@@ -83 +164,0 @@ impl<'sock> LogScheme<'sock> {
|
|
- // FIXME currently possible as /scheme/log/kernel presents a snapshot of the log queue
|
|
@@ -118 +198,0 @@ impl<'sock> LogScheme<'sock> {
|
|
- // Writing to the kernel debug log never blocks
|
|
@@ -124 +204,4 @@ impl<'sock> LogScheme<'sock> {
|
|
- .send(OutputCmd::Log(mem::take(handle_buf)))
|
|
+ .send(OutputCmd::Log {
|
|
+ context: context.to_string(),
|
|
+ line: mem::take(handle_buf),
|
|
+ })
|
|
@@ -173,3 +255,0 @@ impl<'sock> SchemeSync for LogScheme<'sock> {
|
|
-
|
|
- // TODO
|
|
-
|
|
@@ -244,3 +323,0 @@ impl<'sock> SchemeSync for LogScheme<'sock> {
|
|
-
|
|
- //TODO: flush remaining data?
|
|
-
|