From: Bruce Richardson <bruce.richardson@intel.com>
To: dev@dpdk.org
Cc: Bruce Richardson <bruce.richardson@intel.com>
Subject: [RFC PATCH 1/7] usertools: add new script to monitor telemetry on terminal
Date: Wed, 10 Dec 2025 16:55:26 +0000 [thread overview]
Message-ID: <20251210165532.103450-2-bruce.richardson@intel.com> (raw)
In-Reply-To: <20251210165532.103450-1-bruce.richardson@intel.com>
The dpdk-telemetry.py script is useful for getting telemetry
interactively, but sometimes we want to monitor stats over time, so add
a telemetry-watcher script to do so.
Start off such a script with basic arg processing, and connecting to
dpdk-telemetry as a subprocess, so that we can send-receive commands
from it.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
usertools/dpdk-telemetry-watcher.py | 200 ++++++++++++++++++++++++++++
usertools/meson.build | 1 +
2 files changed, 201 insertions(+)
create mode 100755 usertools/dpdk-telemetry-watcher.py
diff --git a/usertools/dpdk-telemetry-watcher.py b/usertools/dpdk-telemetry-watcher.py
new file mode 100755
index 0000000000..01c8683d33
--- /dev/null
+++ b/usertools/dpdk-telemetry-watcher.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2025 Intel Corporation
+
+"""
+Script to monitor DPDK telemetry statistics on the command line.
+Wraps dpdk-telemetry.py to provide continuous monitoring capabilities.
+"""
+
+import argparse
+import subprocess
+import sys
+import os
+import shutil
+import errno
+import json
+
+
+def get_app_name(pid):
+ """return the app name for a given PID, for printing"""
+ proc_cmdline = os.path.join("/proc", str(pid), "cmdline")
+ try:
+ with open(proc_cmdline) as f:
+ argv0 = f.read(1024).split("\0")[0]
+ return os.path.basename(argv0)
+ except IOError as e:
+ # ignore file not found errors
+ if e.errno != errno.ENOENT:
+ raise
+ return None
+
+
+def find_telemetry_script():
+ """Find the dpdk-telemetry.py script in the script directory or PATH.
+
+ Returns:
+ str: Path to the dpdk-telemetry.py script
+
+ Exits:
+ If the script cannot be found
+ """
+ # First, try to find it in the same directory as this script
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ telemetry_script = os.path.join(script_dir, "dpdk-telemetry.py")
+
+ # If not found locally, check if it's in PATH
+ if not os.path.exists(telemetry_script):
+ telemetry_in_path = shutil.which("dpdk-telemetry.py")
+ if telemetry_in_path:
+ telemetry_script = telemetry_in_path
+ else:
+ print(
+ "Error: dpdk-telemetry.py not found in script directory or PATH",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ return telemetry_script
+
+
+def create_telemetry_process(telemetry_script, args_list):
+ """Create a subprocess for dpdk-telemetry.py with pipes.
+
+ Args:
+ telemetry_script: Path to the dpdk-telemetry.py script
+ args_list: List of arguments to pass to the script
+
+ Returns:
+ subprocess.Popen: Process handle with stdin/stdout/stderr pipes
+
+ Exits:
+ If the process cannot be created
+ """
+ # Build the command
+ cmd = [sys.executable, telemetry_script] + args_list
+
+ try:
+ process = subprocess.Popen(
+ cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ bufsize=1, # Line buffered
+ )
+ return process
+ except FileNotFoundError:
+ print(f"Error: Python interpreter or script not found", file=sys.stderr)
+ sys.exit(1)
+ except Exception as e:
+ print(f"Error running dpdk-telemetry.py: {e}", file=sys.stderr)
+ sys.exit(1)
+
+
+def query_telemetry(process, command):
+ """Send a telemetry command and return the parsed JSON response.
+
+ Args:
+ process: The subprocess.Popen handle to the telemetry process
+ command: The telemetry command to send (e.g., "/info" or "/ethdev/stats,0")
+
+ Returns:
+ dict: The parsed JSON response with the command wrapper stripped,
+ or None if there was an error
+ """
+ # Send the command
+ process.stdin.write(f"{command}\n")
+ process.stdin.flush()
+
+ # Read the JSON response
+ response = process.stdout.readline()
+ try:
+ data = json.loads(response)
+ # When run non-interactively, the response is wrapped with the command
+ # e.g., {"/info": {"version": ..., "pid": ...}}
+ # or {"/ethdev/stats,0": {...}}
+ # The response should have exactly one key which is the command
+ if len(data) == 1:
+ # Extract the value, ignoring the key
+ return next(iter(data.values()))
+ else:
+ return data
+ except (json.JSONDecodeError, KeyError):
+ return None
+
+
+def print_connected_app(process):
+ """Query and print the name of the connected DPDK application.
+
+ Args:
+ process: The subprocess.Popen handle to the telemetry process
+ """
+ info = query_telemetry(process, "/info")
+ if info and "pid" in info:
+ app_name = get_app_name(info["pid"])
+ if app_name:
+ print(f'Connected to application: "{app_name}"')
+
+
+def main():
+ """Main function to parse arguments and run dpdk-telemetry.py with a pipe"""
+
+ # Parse command line arguments - matching dpdk-telemetry.py parameters
+ parser = argparse.ArgumentParser(
+ description="Monitor DPDK telemetry statistics on the command line"
+ )
+ parser.add_argument(
+ "-f",
+ "--file-prefix",
+ default="rte",
+ help="Provide file-prefix for DPDK runtime directory",
+ )
+ parser.add_argument(
+ "-i",
+ "--instance",
+ default=0,
+ type=int,
+ help="Provide instance number for DPDK application",
+ )
+ parser.add_argument(
+ "-l",
+ "--list",
+ action="store_true",
+ default=False,
+ help="List all possible file-prefixes and exit",
+ )
+
+ args = parser.parse_args()
+
+ # Find the dpdk-telemetry.py script
+ telemetry_script = find_telemetry_script()
+
+ # Build arguments list
+ args_list = ["-f", args.file_prefix, "-i", str(args.instance)]
+
+ if args.list:
+ args_list.append("-l")
+ # For --list, just run the command directly without pipes
+ cmd = [sys.executable, telemetry_script] + args_list
+ return subprocess.run(cmd).returncode
+
+ # 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
+
+ # Clean up
+ process.stdin.close()
+ process.stdout.close()
+ process.stderr.close()
+ process.wait()
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/usertools/meson.build b/usertools/meson.build
index eb48e2f440..114d0a65b4 100644
--- a/usertools/meson.build
+++ b/usertools/meson.build
@@ -12,6 +12,7 @@ install_data([
'dpdk-hugepages.py',
'dpdk-rss-flows.py',
'dpdk-telemetry-exporter.py',
+ 'dpdk-telemetry-watcher.py',
],
install_dir: 'bin')
--
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 ` Bruce Richardson [this message]
2025-12-10 16:55 ` [RFC PATCH 2/7] usertools/telemetry-watcher: add displaying stats Bruce Richardson
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-2-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).