From: Bruce Richardson <bruce.richardson@intel.com>
To: dev@dpdk.org
Cc: Bruce Richardson <bruce.richardson@intel.com>
Subject: [RFC PATCH 2/7] usertools/telemetry-watcher: add displaying stats
Date: Wed, 10 Dec 2025 16:55:27 +0000 [thread overview]
Message-ID: <20251210165532.103450-3-bruce.richardson@intel.com> (raw)
In-Reply-To: <20251210165532.103450-1-bruce.richardson@intel.com>
Add support for printing out particular stats once every second. The
stats to be queried are given on the commandline, in the format of
<command>.<result-field>, for example /ethdev/stats,0.ipackets.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
usertools/dpdk-telemetry-watcher.py | 101 +++++++++++++++++++++++++++-
1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/usertools/dpdk-telemetry-watcher.py b/usertools/dpdk-telemetry-watcher.py
index 01c8683d33..824c9a37be 100755
--- a/usertools/dpdk-telemetry-watcher.py
+++ b/usertools/dpdk-telemetry-watcher.py
@@ -14,6 +14,7 @@
import shutil
import errno
import json
+import time
def get_app_name(pid):
@@ -137,6 +138,91 @@ def print_connected_app(process):
print(f'Connected to application: "{app_name}"')
+def validate_stats(process, stat_specs):
+ """Validate stat specifications and check that fields are numeric.
+
+ Args:
+ process: The subprocess.Popen handle to the telemetry process
+ stat_specs: List of stat specifications in format "command.field"
+
+ Returns:
+ List of tuples (spec, command, field) for valid specs, or None on error
+ """
+ parsed_specs = []
+ for spec in stat_specs:
+ # Parse the stat specification
+ if "." not in spec:
+ print(f"Error: Invalid stat specification '{spec}'", file=sys.stderr)
+ print(
+ "Expected format: 'command.field' (e.g., /ethdev/stats,0.ipackets)",
+ file=sys.stderr,
+ )
+ return None
+
+ command, field = spec.rsplit(".", 1)
+ if not command or not field:
+ print(f"Error: Invalid stat specification '{spec}'", file=sys.stderr)
+ print(
+ "Expected format: 'command.field' (e.g., /ethdev/stats,0.ipackets)",
+ file=sys.stderr,
+ )
+ return None
+
+ # Query the stat once to validate it exists and is numeric
+ data = query_telemetry(process, command)
+ if not isinstance(data, dict):
+ print(f"Error: Command '{command}' did not return a dictionary", file=sys.stderr)
+ return None
+ if field not in data:
+ print(f"Error: Field '{field}' not found in '{command}' response", file=sys.stderr)
+ return None
+ value = data[field]
+ if not isinstance(value, (int, float)):
+ print(
+ f"Error: Field '{field}' in '{command}' is not numeric (got {type(value).__name__})",
+ file=sys.stderr,
+ )
+ return None
+
+ parsed_specs.append((spec, command, field))
+
+ return parsed_specs
+
+
+def monitor_stats(process, stat_specs):
+ """Monitor and display statistics in columns.
+
+ Args:
+ process: The subprocess.Popen handle to the telemetry process
+ stat_specs: List of stat specifications in format "command.field"
+ """
+ # Validate all stat specifications
+ parsed_specs = validate_stats(process, stat_specs)
+ if not parsed_specs:
+ return
+
+ # Print header
+ header = "Time".ljust(10)
+ for spec, _, _ in parsed_specs:
+ header += spec.rjust(25)
+ print(header)
+
+ # Monitor loop - once per second
+ try:
+ while True:
+ timestamp = time.strftime("%H:%M:%S")
+ row = timestamp.ljust(10)
+
+ for spec, command, field in parsed_specs:
+ data = query_telemetry(process, command)
+ row += str(data[field]).rjust(25)
+
+ print(row)
+ time.sleep(1)
+ except KeyboardInterrupt:
+ print("\nMonitoring stopped")
+
+
def main():
"""Main function to parse arguments and run dpdk-telemetry.py with a pipe"""
@@ -164,6 +250,11 @@ def main():
default=False,
help="List all possible file-prefixes and exit",
)
+ parser.add_argument(
+ "stats",
+ nargs="*",
+ help="Statistics to monitor in format 'command.field' (e.g., /ethdev/stats,0.ipackets)",
+ )
args = parser.parse_args()
@@ -179,13 +270,21 @@ def main():
cmd = [sys.executable, telemetry_script] + args_list
return subprocess.run(cmd).returncode
+ # Check if stats were provided
+ if not args.stats:
+ print("Error: No statistics to monitor specified", file=sys.stderr)
+ print("Usage: dpdk-telemetry-watcher.py [options] stat1 stat2 ...", file=sys.stderr)
+ print("Example: dpdk-telemetry-watcher.py /ethdev/stats,0.ipackets", file=sys.stderr)
+ return 1
+
# Run dpdk-telemetry.py with pipes for stdin and stdout
process = create_telemetry_process(telemetry_script, args_list)
# Get and display the connected application name
print_connected_app(process)
- # TODO: Add monitoring logic here
+ # Monitor the requested statistics
+ monitor_stats(process, args.stats)
# Clean up
process.stdin.close()
--
2.51.0
next prev parent reply other threads:[~2025-12-10 16:55 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-10 16:55 [RFC PATCH 0/7] Add script for real-time telemetry monitoring Bruce Richardson
2025-12-10 16:55 ` [RFC PATCH 1/7] usertools: add new script to monitor telemetry on terminal Bruce Richardson
2025-12-10 16:55 ` Bruce Richardson [this message]
2025-12-10 16:55 ` [RFC PATCH 3/7] usertools/telemetry-watcher: add delta and timeout opts Bruce Richardson
2025-12-10 16:55 ` [RFC PATCH 4/7] usertools/telemetry-watcher: add total and one-line opts Bruce Richardson
2025-12-10 16:55 ` [RFC PATCH 5/7] usertools/telemetry-watcher: add thousands separator Bruce Richardson
2025-12-10 16:55 ` [RFC PATCH 6/7] usertools/telemetry-watcher: add eth name shortcuts Bruce Richardson
2025-12-10 16:55 ` [RFC PATCH 7/7] usertools/telemetry-watcher: support reconnection Bruce Richardson
2025-12-11 1:09 ` [RFC PATCH 0/7] Add script for real-time telemetry monitoring Stephen Hemminger
2025-12-11 9:10 ` Bruce Richardson
2025-12-12 5:32 ` Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251210165532.103450-3-bruce.richardson@intel.com \
--to=bruce.richardson@intel.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).