Skip to content

Commit 2826255

Browse files
authored
procdockerstatsd-rs: use ASCII hyphen for invalid container name (#346)
Replace Unicode dash with ASCII hyphen-minus in INVALID_CONTAINER_NAME constant and related comment, so the invalid container name matches what docker stats actually returns. Why I did this We found some error in syslog: ERR memory_threshold_check: Failed to parse memory usage for "{'CPU%': '--', 'MEM%': '--', 'MEM_BYTES': '0', 'MEM_LIMIT_BYTES': '0', 'NAME': '--', 'PIDS': '--'}": could not convert string to float: '--' 2026 Feb 6 22:43:04.172360 air-2700-1 ERR memory_threshold_check: Failed to parse memory usage for "{'CPU%': '--', 'MEM%': '--', 'MEM_BYTES': '0', 'MEM_LIMIT_BYTES': '0', 'NAME': '--', 'PIDS': '--'}": could not convert string to float: '--' 2026 Feb 6 22:43:04.172422 air-2700-1 ERR memory_threshold_check: Failure occurred could not convert string to float: '--' The error is statistical. The flow is as below: procdockerstatsd calls "docker stats" command periodically, parse the output and store to STATE DB memory_threshold_check which is called by monit service, handles the data in STATE DB and check the memory usage For detailed docker code, please check: https://github.com/docker/cli/blob/93fa57bbcd08f2f5be7f6cf22f4273a2b5a49e71/cli/command/container/formatter_stats.go#L25 https://github.com/docker/cli/blob/93fa57bbcd08f2f5be7f6cf22f4273a2b5a49e71/cli/command/container/formatter_stats.go#L169 How I did this procdockerstatsd should check the command output and ignore invalid value: If the name is empty of "--", ignore the output, log a warning message to syslog. How I test this Manual test.
1 parent 84b2892 commit 2826255

File tree

1 file changed

+28
-2
lines changed
  • crates/procdockerstatsd-rs/src

1 file changed

+28
-2
lines changed

crates/procdockerstatsd-rs/src/main.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::ffi::CString;
1515
use serde::Deserialize;
1616

1717
const UPDATE_INTERVAL: u64 = 120; // 2 minutes
18-
const INVALID_CONTAINER_NAME: &str = "-"; // invalid container name returned by docker stats command
18+
const INVALID_CONTAINER_NAME: &str = "--"; // invalid container name returned by docker stats command
1919

2020
#[derive(Debug, Deserialize)]
2121
#[serde(rename_all = "PascalCase")]
@@ -106,7 +106,7 @@ fn parse_docker_json_output(json_output: &str) -> HashMap<String, HashMap<String
106106

107107
if stats.name.is_empty() || stats.name == INVALID_CONTAINER_NAME {
108108
// If a container stops suddenly after we send the docker stats command,
109-
// it might return with a container name "-". We should ignore such output.
109+
// it might return with a container name "--". We should ignore such output.
110110
warn!("Skipping docker stats JSON for container {} with output: {}", stats.id, line);
111111
continue;
112112
}
@@ -387,3 +387,29 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
387387
daemon.run();
388388
Ok(())
389389
}
390+
391+
#[cfg(test)]
392+
mod tests {
393+
use super::*;
394+
395+
/// Invalid container line: NAME "--", other fields "--" or "0", no ID (empty).
396+
/// Matches real docker stats output that leads to "Failed to parse memory usage" when not skipped.
397+
const INVALID_LINE: &str = r#"{"ID":"","Name":"--","CPUPerc":"--","MemPerc":"--","MemUsage":"--","NetIO":"--","BlockIO":"--","PIDs":"--"}"#;
398+
399+
/// Valid container line with proper MemUsage/NetIO/BlockIO format.
400+
const VALID_LINE: &str = r#"{"ID":"abc123","Name":"valid-container","CPUPerc":"0.5%","MemPerc":"1.2%","MemUsage":"100MiB / 2GiB","NetIO":"1kB / 2kB","BlockIO":"3MB / 4MB","PIDs":"10"}"#;
401+
402+
#[test]
403+
fn test_parse_docker_json_skips_invalid_container_name() {
404+
let result = parse_docker_json_output(INVALID_LINE);
405+
assert!(result.is_empty(), "lines with NAME \"--\" (invalid container) should be skipped");
406+
}
407+
408+
#[test]
409+
fn test_parse_docker_json_includes_valid_container() {
410+
let result = parse_docker_json_output(VALID_LINE);
411+
assert_eq!(result.len(), 1);
412+
assert!(result.contains_key("DOCKER_STATS|abc123"));
413+
assert_eq!(result["DOCKER_STATS|abc123"].get("NAME").map(String::as_str), Some("valid-container"));
414+
}
415+
}

0 commit comments

Comments
 (0)