DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Bruce Richardson <bruce.richardson@intel.com>
To: dev@dpdk.org
Cc: fengchengwen@huawei.com, Bruce Richardson <bruce.richardson@intel.com>
Subject: [PATCH v3 3/3] usertools/telemetry: add help support
Date: Tue,  9 Jun 2026 17:14:00 +0100	[thread overview]
Message-ID: <20260609161400.3661268-4-bruce.richardson@intel.com> (raw)
In-Reply-To: <20260609161400.3661268-1-bruce.richardson@intel.com>

While the telemetry infrastructure supported using "/help,/<cmd>" to get
help on specific commands, with the addition of script-specific
commands, we needed better help support to explain the use of FOREACH,
and to allow e.g. "help /<cmd>" using space separation, which is more
intuitive. This patch adds that help support.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
v2: added "help aliases" to list defined aliases
    updated docs for expanded help command
---
 doc/guides/howto/telemetry.rst | 31 ++++++++++++---
 usertools/dpdk-telemetry.py    | 69 +++++++++++++++++++++++++++++++++-
 2 files changed, 93 insertions(+), 7 deletions(-)

diff --git a/doc/guides/howto/telemetry.rst b/doc/guides/howto/telemetry.rst
index bdefbdc6a6..00cfc1a1e1 100644
--- a/doc/guides/howto/telemetry.rst
+++ b/doc/guides/howto/telemetry.rst
@@ -81,12 +81,31 @@ and query information using the telemetry client python script.
        ...
        "tx_priority7_xon_to_xoff_packets": 0}}
 
-   * Get the help text for a command. This will indicate what parameters are
-     required. Pass the command as a parameter::
-
-       --> /help,/ethdev/xstats
-       {"/help": {"/ethdev/xstats": "Returns the extended stats for a port.
-       Parameters: int port_id"}}
+   * Get the help text for a command.
+     This will indicate what parameters are required.
+     Use the ``help`` keyword followed by the command or keyword of interest,
+     for example::
+
+       --> help FOREACH
+       FOREACH usage:
+          FOREACH /<list_cmd> /<iter_cmd> .<field> [.<field> ...]
+          FOREACH <var> /<list_cmd> /<iter_cmd_with_$var> .<field> [.<field> ...]
+
+       Examples:
+          FOREACH /ethdev/list /ethdev/stats .opackets
+          ...
+
+       --> help /ethdev/xstats
+       {"/help": {"/ethdev/xstats": "Returns the extended stats for a port. Parameters: int port_id"}}
+
+   ..  Note::
+         For commands starting with ``/`` that are telemetry enpoints,
+         the help text can also be obtained by sending the ``/help`` command to the telemetry socket.
+         In this case, the parameter must be separated by a comma, not a space.
+         For example::
+
+           --> /help,/ethdev/xstats
+           {"/help": {"/ethdev/xstats": "Returns the extended stats for a port. Parameters: int port_id"}}
 
    * Run a compound query using ``FOREACH``.
 
diff --git a/usertools/dpdk-telemetry.py b/usertools/dpdk-telemetry.py
index 7a25b78730..20627b596b 100755
--- a/usertools/dpdk-telemetry.py
+++ b/usertools/dpdk-telemetry.py
@@ -25,6 +25,26 @@
 ALIAS_FILE = ".dpdk_telemetry_aliases"
 MAX_ALIAS_EXPANSIONS = 32
 
+BASIC_HELP_TEXT = """Basic usage:
+    /<command>[,<params>]      Send a telemetry command to the app
+    FOREACH ...                Run a compound query over list items
+    help                       Show this help
+    help /<command>            Show app-provided help for a command
+    help FOREACH               Show FOREACH usage and examples
+    quit                       Exit the client
+"""
+
+FOREACH_HELP_TEXT = """FOREACH usage:
+    FOREACH /<list_cmd> /<iter_cmd> .<field> [.<field> ...]
+    FOREACH <var> /<list_cmd> /<iter_cmd_with_$var> .<field> [.<field> ...]
+
+Examples:
+    FOREACH /ethdev/list /ethdev/stats .opackets
+    FOREACH /ethdev/list /ethdev/stats .ipackets .opackets
+    FOREACH i /ethdev/list /ethdev/info,$i .name
+    FOREACH i /ethdev/list /ethdev/stats,$i .ipackets .opackets
+"""
+
 
 def load_aliases(alias_path=None):
     """Load aliases from $HOME/.dpdk_telemetry_aliases or a custom path if provided"""
@@ -209,10 +229,57 @@ def handle_foreach(sock, output_buf_len, text, pretty=False):
     print(json.dumps(output, indent=indent))
 
 
+def command_exists(cmd):
+    """Check if a telemetry command exists in the command list"""
+    return cmd in CMDS
+
+
+def app_help_command_for(target_cmd):
+    """Build a '/help,<command>' query for app-side command help"""
+    if not target_cmd:
+        return None
+    normalized = target_cmd.strip()
+    if not normalized.startswith("/"):
+        return None
+    if not command_exists(normalized):
+        print("Unknown command for help: {}".format(normalized))
+        return None
+    return "/help,{}".format(normalized)
+
+
+def handle_user_help(sock, output_buf_len, text, pretty=False):
+    """Handle local 'help' command and command-specific help lookup"""
+    parts = text.split(None, 1)
+    if len(parts) == 1:
+        print(BASIC_HELP_TEXT, end="")
+        return
+
+    help_arg = parts[1].strip()
+    if help_arg.upper() == "FOREACH":
+        print(FOREACH_HELP_TEXT, end="")
+        return
+    elif help_arg.lower() == "alias" or help_arg.lower() == "aliases":
+        if not ALIASES:
+            print("No aliases defined")
+            return
+        print("Defined aliases:")
+        for name, command in ALIASES.items():
+            print(f"  {name}='{command}'")
+        return
+
+    cmd = app_help_command_for(help_arg)
+    if cmd is None:
+        print("Usage: help [FOREACH|/<command>]")
+        return
+    send_command(sock, cmd, output_buf_len, echo=True, pretty=pretty)
+
+
 def handle_command(sock, output_buf_len, text, pretty=False):
     """Execute a user command if recognized"""
     if text.startswith("/"):
         send_command(sock, text, output_buf_len, echo=True, pretty=pretty)
+    elif text == "help" or text.startswith("help "):
+        handle_user_help(sock, output_buf_len, text, pretty)
     elif text.startswith("FOREACH "):
         handle_foreach(sock, output_buf_len, text, pretty)
 
@@ -346,7 +413,7 @@ def handle_socket(args, path):
 
 def readline_complete(text, state):
     """Find any matching commands from the list based on user input"""
-    all_cmds = ["quit"] + list(ALIASES.keys()) + CMDS
+    all_cmds = ["quit", "help"] + list(ALIASES.keys()) + CMDS
     if text:
         matches = [c for c in all_cmds if c.startswith(text)]
     else:
-- 
2.53.0


  parent reply	other threads:[~2026-06-09 16:14 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-21 15:39 [PATCH 0/2] extend interactive telemetry script Bruce Richardson
2026-05-21 15:39 ` [PATCH 1/2] usertools/telemetry: add a FOREACH command Bruce Richardson
2026-05-21 15:39 ` [PATCH 2/2] usertools/telemetry: support using aliases for long commands Bruce Richardson
2026-05-22  0:44 ` [PATCH 0/2] extend interactive telemetry script fengchengwen
2026-05-22  7:51   ` Bruce Richardson
2026-05-22 13:37 ` [PATCH v2 0/3] " Bruce Richardson
2026-05-22 13:37   ` [PATCH v2 1/3] usertools/telemetry: add a FOREACH command Bruce Richardson
2026-05-29  0:17     ` fengchengwen
2026-05-22 13:37   ` [PATCH v2 2/3] usertools/telemetry: support using aliases for long commands Bruce Richardson
2026-05-29  0:25     ` fengchengwen
2026-05-22 13:37   ` [PATCH v2 3/3] usertools/telemetry: add help support Bruce Richardson
2026-05-29  0:27     ` fengchengwen
2026-06-09 16:13 ` [PATCH v3 0/3] extend interactive telemetry script Bruce Richardson
2026-06-09 16:13   ` [PATCH v3 1/3] usertools/telemetry: add a FOREACH command Bruce Richardson
2026-06-09 16:13   ` [PATCH v3 2/3] usertools/telemetry: support using aliases for long commands Bruce Richardson
2026-06-09 16:14   ` Bruce Richardson [this message]
2026-06-09 16:17     ` [PATCH v3 3/3] usertools/telemetry: add help support Bruce Richardson
2026-06-10  1:39   ` [PATCH v3 0/3] extend interactive telemetry script fengchengwen

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=20260609161400.3661268-4-bruce.richardson@intel.com \
    --to=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=fengchengwen@huawei.com \
    /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