This commit is contained in:
Mateusz Gruszczyński committed 2026-10-10 08:53:55 +02:00
1 parent 1431dd47f0
commit f3dd34dae4
42 files changed
+950 -133

No files matched your search

+20 -8
View File
@@ -122,12 +122,17 @@ async fn sink_loop(
let config = settings.load_full();
let mut payload = format_entry(&entry, &config.format);
redact_value(&mut payload);
// File and Logstash consume the same JSONL record. Serialize once and
// keep no JSONL buffer at all for Loki-only configurations.
let mut jsonl_line = Vec::new();
if config.file.enabled || config.logstash.enabled {
jsonl_line = serde_json::to_vec(&payload).unwrap_or_default();
jsonl_line.push(b'\n');
}
let mut attempted = false;
let mut failed = false;
if config.file.enabled {
attempted = true;
let mut line = serde_json::to_vec(&payload).unwrap_or_default();
line.push(b'\n');
if config.file.per_vhost {
file = None;
let directory = PathBuf::from(&config.file.directory);
@@ -157,7 +162,7 @@ async fn sink_loop(
}
}
let write_failed = match vhost_files.get_mut(&path) {
Some(opened) => opened.write_all(&line).await.is_err(),
Some(opened) => opened.write_all(&jsonl_line).await.is_err(),
None => true,
};
if write_failed {
@@ -182,7 +187,7 @@ async fn sink_loop(
};
}
if let Some(state) = file.as_mut() {
if state.file.write_all(&line).await.is_err() {
if state.file.write_all(&jsonl_line).await.is_err() {
failed = true;
file = None;
}
@@ -211,11 +216,9 @@ async fn sink_loop(
_ => None,
};
}
let mut line = serde_json::to_vec(&payload).unwrap_or_default();
line.push(b'\n');
if let Some(state) = logstash.as_mut() {
if !matches!(
tokio::time::timeout(SINK_TIMEOUT, state.stream.write_all(&line)).await,
tokio::time::timeout(SINK_TIMEOUT, state.stream.write_all(&jsonl_line)).await,
Ok(Ok(()))
) {
failed = true;
@@ -234,7 +237,16 @@ async fn sink_loop(
} else {
config.loki.labels.clone()
};
let body = json!({"streams":[{"stream":labels,"values":[[(entry.time_ms as u128 * 1_000_000).to_string(), payload.to_string()]]}]});
// Loki needs the same redacted JSON event as the file/Logstash
// sinks, only without the JSONL terminator. Reuse the already
// serialized record when another sink is active; avoid a second
// full serde_json pass for every high-volume access event.
let event_json = if jsonl_line.is_empty() {
payload.to_string()
} else {
String::from_utf8_lossy(&jsonl_line[..jsonl_line.len() - 1]).into_owned()
};
let body = json!({"streams":[{"stream":labels,"values":[[(entry.time_ms as u128 * 1_000_000).to_string(), event_json]]}]});
let result = async {
let uri: Uri = config.loki.url.parse()?;
let mut request = Request::post(uri)