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 <[email protected]> --- usertools/dpdk-telemetry.py | 61 ++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/usertools/dpdk-telemetry.py b/usertools/dpdk-telemetry.py index 8b976160e0..2c88b91517 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(): """Load aliases from $HOME/.dpdk_telemetry_aliases""" @@ -203,10 +223,49 @@ 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 + + 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) @@ -340,7 +399,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

