initial commit
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ib131388c1056b6708b730a35011811026a6a6964
This commit is contained in:
commit
033e253259
33 changed files with 3126 additions and 0 deletions
137
pscand-core/src/logging.rs
Normal file
137
pscand-core/src/logging.rs
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use parking_lot::Mutex;
|
||||
use ringbuf::{
|
||||
storage::Heap,
|
||||
traits::*,
|
||||
wrap::caching::{CachingCons, CachingProd},
|
||||
SharedRb,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::scanner::MetricValue;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LogEntry {
|
||||
pub timestamp: DateTime<Utc>,
|
||||
pub scanner: String,
|
||||
pub metrics: HashMap<String, MetricValue>,
|
||||
}
|
||||
|
||||
impl LogEntry {
|
||||
pub fn new(scanner: impl Into<String>, metrics: HashMap<String, MetricValue>) -> Self {
|
||||
Self {
|
||||
timestamp: Utc::now(),
|
||||
scanner: scanner.into(),
|
||||
metrics,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> String {
|
||||
serde_json::to_string(self).unwrap_or_else(|e| format!("{{\"error\":\"{}\"}}", e))
|
||||
}
|
||||
|
||||
pub fn to_journal(&self) -> String {
|
||||
let metrics_json = serde_json::to_string(&self.metrics).unwrap_or_default();
|
||||
format!(
|
||||
"PSCAND_SCANNER={} PSCAND_METRICS={}",
|
||||
self.scanner, metrics_json
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type RbStorage = Heap<LogEntry>;
|
||||
type SharedRbLog = SharedRb<RbStorage>;
|
||||
|
||||
struct RingBufferHandles {
|
||||
prod: CachingProd<Arc<SharedRbLog>>,
|
||||
cons: CachingCons<Arc<SharedRbLog>>,
|
||||
}
|
||||
|
||||
pub struct RingBufferLogger {
|
||||
buffer: Arc<Mutex<RingBufferHandles>>,
|
||||
file_path: Option<PathBuf>,
|
||||
journal_enabled: bool,
|
||||
file_enabled: bool,
|
||||
}
|
||||
|
||||
impl RingBufferLogger {
|
||||
pub fn new(
|
||||
capacity: usize,
|
||||
file_path: Option<PathBuf>,
|
||||
journal_enabled: bool,
|
||||
file_enabled: bool,
|
||||
) -> Self {
|
||||
let rb = SharedRb::<RbStorage>::new(capacity);
|
||||
let (prod, cons) = rb.split();
|
||||
|
||||
let handles = RingBufferHandles { prod, cons };
|
||||
|
||||
Self {
|
||||
buffer: Arc::new(Mutex::new(handles)),
|
||||
file_path,
|
||||
journal_enabled,
|
||||
file_enabled,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&self, entry: LogEntry) {
|
||||
{
|
||||
let mut handles = self.buffer.lock();
|
||||
if handles.prod.is_full() {
|
||||
let _ = handles.cons.try_pop();
|
||||
}
|
||||
let _ = handles.prod.try_push(entry.clone());
|
||||
}
|
||||
|
||||
if self.journal_enabled {
|
||||
self.write_to_journal(&entry);
|
||||
}
|
||||
if self.file_enabled {
|
||||
self.write_to_file(&entry);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_journal(&self, entry: &LogEntry) {
|
||||
let msg = entry.to_journal();
|
||||
let _ = std::process::Command::new("logger")
|
||||
.arg("-t")
|
||||
.arg("pscand")
|
||||
.arg("-p")
|
||||
.arg("info")
|
||||
.arg(msg)
|
||||
.spawn();
|
||||
}
|
||||
|
||||
fn write_to_file(&self, entry: &LogEntry) {
|
||||
if let Some(ref path) = self.file_path {
|
||||
if let Ok(mut file) = OpenOptions::new().create(true).append(true).open(path) {
|
||||
let _ = writeln!(file, "{}", entry.to_json());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_recent(&self, count: usize) -> Vec<LogEntry> {
|
||||
let handles = self.buffer.lock();
|
||||
handles.cons.iter().rev().take(count).cloned().collect()
|
||||
}
|
||||
|
||||
pub fn flush_to_file(&self, path: &PathBuf) -> std::io::Result<()> {
|
||||
let entries = self.get_recent(usize::MAX);
|
||||
let mut file = fs::File::create(path)?;
|
||||
for entry in entries {
|
||||
writeln!(file, "{}", entry.to_json())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RingBufferLogger {
|
||||
fn default() -> Self {
|
||||
Self::new(60, None, true, false)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue