From: Bruce Richardson <bruce.richardson@intel.com>
To: dev@dpdk.org
Cc: Bruce Richardson <bruce.richardson@intel.com>
Subject: [RFC PATCH 3/7] usertools/telemetry-watcher: add delta and timeout opts
Date: Wed, 10 Dec 2025 16:55:28 +0000 [thread overview]
Message-ID: <20251210165532.103450-4-bruce.richardson@intel.com> (raw)
In-Reply-To: <20251210165532.103450-1-bruce.richardson@intel.com>
Add options to the script to time out and quit after a certain number of
seconds. Also, add an option to display delta instead of absolute
values, allowing easy display of e.g. PPS.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
usertools/dpdk-telemetry-watcher.py | 64 +++++++++++++++++++++--------
1 file changed, 48 insertions(+), 16 deletions(-)
diff --git a/usertools/dpdk-telemetry-watcher.py b/usertools/dpdk-telemetry-watcher.py
index 824c9a37be..8af9af867c 100755
--- a/usertools/dpdk-telemetry-watcher.py
+++ b/usertools/dpdk-telemetry-watcher.py
@@ -146,9 +146,13 @@ def validate_stats(process, stat_specs):
stat_specs: List of stat specifications in format "command.field"
Returns:
- List of tuples (spec, command, field) for valid specs, or None on error
+ Tuple of (parsed_specs, initial_values) where:
+ parsed_specs: List of tuples (spec, command, field) for valid specs
+ initial_values: List of initial values for each stat
+ Returns (None, None) on error
"""
parsed_specs = []
+ initial_values = []
for spec in stat_specs:
# Parse the stat specification
if "." not in spec:
@@ -157,7 +161,7 @@ def validate_stats(process, stat_specs):
"Expected format: 'command.field' (e.g., /ethdev/stats,0.ipackets)",
file=sys.stderr,
)
- return None
+ return None, None
command, field = spec.rsplit(".", 1)
if not command or not field:
@@ -166,38 +170,39 @@ def validate_stats(process, stat_specs):
"Expected format: 'command.field' (e.g., /ethdev/stats,0.ipackets)",
file=sys.stderr,
)
- return None
+ return None, 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
+ return None, None
if field not in data:
print(f"Error: Field '{field}' not found in '{command}' response", file=sys.stderr)
- return None
+ return None, 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
+ return None, None
parsed_specs.append((spec, command, field))
+ initial_values.append(value)
- return parsed_specs
+ return parsed_specs, initial_values
-def monitor_stats(process, stat_specs):
+def monitor_stats(process, args):
"""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"
+ args: Parsed command line arguments
"""
- # Validate all stat specifications
- parsed_specs = validate_stats(process, stat_specs)
+ # Validate all stat specifications and get initial values
+ parsed_specs, prev_values = validate_stats(process, args.stats)
if not parsed_specs:
return
@@ -208,17 +213,30 @@ def monitor_stats(process, stat_specs):
print(header)
# Monitor loop - once per second
+ count = 0
try:
- while True:
+ while args.timeout is None or count < args.timeout:
+ time.sleep(1)
+ count += 1
+
timestamp = time.strftime("%H:%M:%S")
row = timestamp.ljust(10)
- for spec, command, field in parsed_specs:
+ current_values = []
+ for i, (spec, command, field) in enumerate(parsed_specs):
data = query_telemetry(process, command)
- row += str(data[field]).rjust(25)
+ current_value = data[field]
+ current_values.append(current_value)
+
+ if args.delta:
+ display_value = current_value - prev_values[i]
+ else:
+ display_value = current_value
+
+ row += str(display_value).rjust(25)
print(row)
- time.sleep(1)
+ prev_values = current_values
except KeyboardInterrupt:
print("\nMonitoring stopped")
@@ -250,6 +268,20 @@ def main():
default=False,
help="List all possible file-prefixes and exit",
)
+ parser.add_argument(
+ "-t",
+ "--timeout",
+ type=int,
+ default=None,
+ help="Number of iterations to run before stopping (default: run indefinitely)",
+ )
+ parser.add_argument(
+ "-d",
+ "--delta",
+ action="store_true",
+ default=False,
+ help="Display delta values instead of absolute values",
+ )
parser.add_argument(
"stats",
nargs="*",
@@ -284,7 +316,7 @@ def main():
print_connected_app(process)
# Monitor the requested statistics
- monitor_stats(process, args.stats)
+ monitor_stats(process, args)
# Clean up
process.stdin.close()
--
2.51.0
next prev parent reply other threads:[~2025-12-10 16:56 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 ` [RFC PATCH 2/7] usertools/telemetry-watcher: add displaying stats Bruce Richardson
2025-12-10 16:55 ` Bruce Richardson [this message]
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-4-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).