Limit app-server storage metrics to session directories (#43790)

## What changed

Restrict the startup size scan to `sessions` and `archived_sessions` under
`CODEX_HOME`, and stop emitting the aggregate `directory=codex_home` sample.
Skip missing session directories and inspect scan roots without following
symlinks.

GitOrigin-RevId: c046d097de9b630af68cc9ad70e87cdd63e49319
This commit is contained in:
jif
2026-09-08 10:18:59 +00:00
committed by copyberry
parent d6489472f3
commit df522cae16
+20 -8
View File
@@ -1,7 +1,8 @@
//! Measures local CODEX_HOME storage once at standalone app-server startup.
//! Measures local session storage once at standalone app-server startup.
//!
//! The background scan sums regular-file lengths, without reading file contents or
//! following symlinks. Incomplete scans emit no samples, and shutdown cancels the scan.
//! The background scan only visits sessions and archived_sessions under CODEX_HOME.
//! It sums regular-file lengths without reading file contents or following symlinks.
//! Incomplete scans emit no samples, and shutdown cancels the scan.
//! The compression tag reflects the effective startup config, not compression completion.
use codex_core::config::Config;
@@ -15,7 +16,7 @@ use tokio::task::JoinHandle;
use tokio_util::sync::CancellationToken;
const SIZE_BYTES_METRIC: &str = "codex.app_server.codex_home.size_bytes";
// Bucket sizes range from 1 MiB through 1 TiB; larger homes use the overflow bucket.
// Bucket sizes range from 1 MiB through 1 TiB; larger directories use the overflow bucket.
const SIZE_BYTES_BOUNDARIES: &[f64] = &[
1_048_576.0,
10_485_760.0,
@@ -45,7 +46,6 @@ pub(crate) fn spawn(
}
};
for (directory, bytes) in [
("codex_home", sizes.codex_home),
(SESSIONS_SUBDIR, sizes.sessions),
(ARCHIVED_SESSIONS_SUBDIR, sizes.archived_sessions),
] {
@@ -64,7 +64,6 @@ pub(crate) fn spawn(
#[derive(Debug, Default, PartialEq, Eq)]
struct DirectorySizes {
codex_home: u64,
sessions: u64,
archived_sessions: u64,
}
@@ -73,7 +72,21 @@ fn directory_sizes(codex_home: &Path, shutdown: &CancellationToken) -> io::Resul
let sessions = codex_home.join(SESSIONS_SUBDIR);
let archived_sessions = codex_home.join(ARCHIVED_SESSIONS_SUBDIR);
let mut sizes = DirectorySizes::default();
let mut pending = vec![codex_home.to_path_buf()];
let mut pending = Vec::new();
for directory in [&sessions, &archived_sessions] {
if shutdown.is_cancelled() {
return Err(io::ErrorKind::Interrupted.into());
}
// Inspect the roots without following symlinks, just like entries below them.
let metadata = match std::fs::symlink_metadata(directory) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => continue,
Err(error) => return Err(error),
};
if metadata.is_dir() {
pending.push(directory.to_path_buf());
}
}
while let Some(directory) = pending.pop() {
if shutdown.is_cancelled() {
return Err(io::ErrorKind::Interrupted.into());
@@ -90,7 +103,6 @@ fn directory_sizes(codex_home: &Path, shutdown: &CancellationToken) -> io::Resul
pending.push(path);
} else if metadata.is_file() {
let bytes = metadata.len();
sizes.codex_home = sizes.codex_home.saturating_add(bytes);
if path.starts_with(&sessions) {
sizes.sessions = sizes.sessions.saturating_add(bytes);
} else if path.starts_with(&archived_sessions) {