This commit is contained in:
Mateusz Gruszczyński committed 2026-10-05 22:29:54 +02:00
1 parent b9d137eee1
commit 32e6875980
51 files changed
+1255 -452

No files matched your search

+143 -91
View File
@@ -1,100 +1,152 @@
#[test]
fn stored_log_inventory_keeps_existing_files_visible_when_writer_is_disabled() {
use std::io::Write;
#[test]
fn stored_log_inventory_keeps_existing_files_visible_when_writer_is_disabled() {
use std::io::Write;
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("access.jsonl");
let mut file = std::fs::File::create(&path).unwrap();
writeln!(file, r#"{{"event":"request","status":200}}"#).unwrap();
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("access.jsonl");
let mut file = std::fs::File::create(&path).unwrap();
writeln!(file, r#"{{"event":"request","status":200}}"#).unwrap();
let mut config = Config::default();
config.logging.file.enabled = false;
config.logging.file.per_vhost = false;
config.logging.file.path = path.to_string_lossy().into_owned();
let sources = configured_file_log_sources(&config);
let access = sources.iter().find(|source| source.id == "access").unwrap();
assert!(!access.enabled);
assert!(access.exists);
assert!(access.size > 0);
assert_eq!(access.path, path);
let mut config = Config::default();
config.logging.file.enabled = false;
config.logging.file.per_vhost = false;
config.logging.file.path = path.to_string_lossy().into_owned();
let sources = configured_file_log_sources(&config);
let access = sources.iter().find(|source| source.id == "access").unwrap();
assert!(!access.enabled);
assert!(access.exists);
assert!(access.size > 0);
assert_eq!(access.path, path);
}
#[test]
fn stored_log_tail_enforces_line_budget() {
use std::io::Write;
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("access.jsonl");
let mut file = std::fs::File::create(&path).unwrap();
for id in 0..10 {
writeln!(file, r#"{{"time_ms":{id},"event":"request"}}"#).unwrap();
}
drop(file);
#[test]
fn stored_log_tail_enforces_line_budget() {
use std::io::Write;
let source = source_from_path(
"access".into(),
"Access log".into(),
"access",
path,
false,
"JSONL",
);
let (lines, _bytes, truncated) = read_tail(&source, 1024 * 1024, 3).unwrap();
assert_eq!(lines.len(), 3);
assert!(lines[0].contains(r#""time_ms":9"#));
assert!(lines[2].contains(r#""time_ms":7"#));
assert!(truncated);
}
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("access.jsonl");
let mut file = std::fs::File::create(&path).unwrap();
for id in 0..10 {
writeln!(file, r#"{{"time_ms":{id},"event":"request"}}"#).unwrap();
}
drop(file);
#[test]
fn stored_log_query_rejects_oversized_source_identifier() {
let query = FileLogQuery {
source: Some("x".repeat(193)),
..FileLogQuery::default()
};
assert!(validate_file_log_query(&query).is_err());
}
let source = source_from_path(
"access".into(),
"Access log".into(),
"access",
path,
false,
"JSONL",
#[test]
fn stored_log_normalizes_mapped_client_ip_and_searches_diagnostics() {
let dir = tempfile::tempdir().unwrap();
let source = source_from_path(
"vhost:app".into(),
"app.jsonl".into(),
"access",
dir.path().join("app.jsonl"),
true,
"JSONL",
);
let mut format = crate::logging::JsonFormat::default();
format.fields.remove("client_ip");
format
.fields
.insert("remote_addr".into(), "client_ip".into());
let record = normalized_record(
&source,
r#"{"event":"protocol_error","remote_addr":"192.0.2.10","reason":"tls_handshake_error","error":"HTTP parser error","sni":"app.example.test","matched_by":"sni","vhost":"app"}"#,
&format,
);
assert_eq!(record["client_ip"], "192.0.2.10");
assert_eq!(record["sni"], "app.example.test");
let query = FileLogQuery::default();
assert!(record_matches(
&record,
&query,
&parse_file_log_search("error").unwrap()
));
assert!(record_matches(
&record,
&query,
&parse_file_log_search(r#"error:"HTTP parser""#).unwrap()
));
assert!(record_matches(
&record,
&query,
&parse_file_log_search("sni:app.example.test AND !country:Poland").unwrap()
));
assert!(!record_matches(
&record,
&query,
&parse_file_log_search("sni:missing").unwrap()
));
}
#[test]
fn stored_log_search_supports_field_aliases_negation_and_numeric_filters() {
let record = json!({
"method":"GET",
"country":"Germany",
"status":503,
"path":"/api/users"
});
assert!(record_matches_search(
&record,
&parse_file_log_search("req: GET AND !country: Poland AND status:>=500").unwrap()
));
assert!(record_matches_search(
&record,
&parse_file_log_search("status:5xx path:/api/*").unwrap()
));
assert!(!record_matches_search(
&record,
&parse_file_log_search("country:Poland").unwrap()
));
}
#[test]
fn stored_log_raw_error_parser_extracts_basic_fields() {
let record = parse_raw_error_record(
"2026-10-05T19:00:00.000Z ERROR rust_proxy::http upstream failed client_ip=192.0.2.10 status=502 error=connection reset",
);
let (lines, _bytes, truncated) = read_tail(&source, 1024 * 1024, 3).unwrap();
assert_eq!(lines.len(), 3);
assert!(lines[0].contains(r#""time_ms":9"#));
assert!(lines[2].contains(r#""time_ms":7"#));
assert!(truncated);
}
assert_eq!(record["timestamp"], "2026-10-05T19:00:00.000Z");
assert_eq!(record["level"], "ERROR");
assert_eq!(record["target"], "rust_proxy::http");
assert_eq!(record["message"], "upstream failed");
assert_eq!(record["client_ip"], "192.0.2.10");
assert_eq!(record["status"], "502");
assert_eq!(record["error"], "connection reset");
}
#[test]
fn stored_log_query_rejects_oversized_source_identifier() {
let query = FileLogQuery {
source: Some("x".repeat(193)),
..FileLogQuery::default()
};
assert!(validate_file_log_query(&query).is_err());
}
#[cfg(unix)]
#[test]
fn stored_log_reader_refuses_symlink_targets() {
use std::os::unix::fs::symlink;
#[test]
fn stored_log_normalizes_mapped_client_ip_and_searches_diagnostics() {
let dir = tempfile::tempdir().unwrap();
let source = source_from_path(
"vhost:app".into(),
"app.jsonl".into(),
"access",
dir.path().join("app.jsonl"),
true,
"JSONL",
);
let mut format = crate::logging::JsonFormat::default();
format.fields.remove("client_ip");
format
.fields
.insert("remote_addr".into(), "client_ip".into());
let record = normalized_record(
&source,
r#"{"event":"protocol_error","remote_addr":"192.0.2.10","reason":"tls_handshake_error","error":"HTTP parser error","sni":"app.example.test","matched_by":"sni","vhost":"app"}"#,
&format,
);
assert_eq!(record["client_ip"], "192.0.2.10");
assert_eq!(record["sni"], "app.example.test");
let query = FileLogQuery::default();
assert!(record_matches(&record, &query, "error"));
assert!(record_matches(&record, &query, "http parser"));
assert!(record_matches(&record, &query, "app.example.test"));
assert!(!record_matches(&record, &query, "missing"));
}
#[cfg(unix)]
#[test]
fn stored_log_reader_refuses_symlink_targets() {
use std::os::unix::fs::symlink;
let dir = tempfile::tempdir().unwrap();
let real = dir.path().join("real.jsonl");
let link = dir.path().join("link.jsonl");
std::fs::write(&real, b"{}\n").unwrap();
symlink(&real, &link).unwrap();
assert!(open_file_log(&link).is_err());
}
let dir = tempfile::tempdir().unwrap();
let real = dir.path().join("real.jsonl");
let link = dir.path().join("link.jsonl");
std::fs::write(&real, b"{}\n").unwrap();
symlink(&real, &link).unwrap();
assert!(open_file_log(&link).is_err());
}