From b33b1461fe815b1a09267118644538a5b9351c60 Mon Sep 17 00:00:00 2001 From: Peter Mikus Date: Fri, 24 Jun 2022 10:32:28 +0000 Subject: feat(telemetry): Rework Signed-off-by: Peter Mikus Change-Id: I0a84ce88b318c488ba2d519b20237c88b9f9f1e6 --- resources/libraries/python/Constants.py | 9 +- resources/libraries/python/ContainerUtils.py | 9 +- resources/libraries/python/TelemetryUtil.py | 4 +- resources/libraries/python/VPPUtil.py | 4 +- resources/libraries/python/topology.py | 4 +- .../robot/performance/performance_actions.robot | 8 +- .../templates/telemetry/vppctl_clear_stats.yaml | 218 ++++++++++ resources/templates/telemetry/vppctl_runtime.yaml | 481 +++++++++++++++++++++ .../templates/telemetry/vppctl_show_stats.yaml | 201 +++++++++ .../templates/telemetry/vppctl_test_teardown.yaml | 201 +++++++++ resources/tools/telemetry/bundle_vppctl.py | 424 ++++++++++++++++++ 11 files changed, 1551 insertions(+), 12 deletions(-) create mode 100644 resources/templates/telemetry/vppctl_clear_stats.yaml create mode 100644 resources/templates/telemetry/vppctl_runtime.yaml create mode 100644 resources/templates/telemetry/vppctl_show_stats.yaml create mode 100644 resources/templates/telemetry/vppctl_test_teardown.yaml create mode 100644 resources/tools/telemetry/bundle_vppctl.py (limited to 'resources') diff --git a/resources/libraries/python/Constants.py b/resources/libraries/python/Constants.py index 83e0854a6b..566dec7421 100644 --- a/resources/libraries/python/Constants.py +++ b/resources/libraries/python/Constants.py @@ -246,6 +246,12 @@ class Constants: # Default path to VPP API socket. SOCKSVR_PATH = u"/run/vpp/api.sock" + # Default path to VPP CLI socket. + SOCKCLI_PATH = u"/run/vpp/cli.sock" + + # Default path to VPP API Stats socket. + SOCKSTAT_PATH = u"/run/vpp/stats.sock" + # Number of trials to execute in MRR test. PERF_TRIAL_MULTIPLICITY = get_int_from_env(u"PERF_TRIAL_MULTIPLICITY", 10) @@ -287,9 +293,6 @@ class Constants: # /tmp directory is inside the DUT1 docker. DUT1_UUID = get_str_from_env(u"DUT1_UUID", u"") - # Default path to VPP API Stats socket. - SOCKSTAT_PATH = u"/run/vpp/stats.sock" - # Global "kill switch" for CRC checking during runtime. FAIL_ON_CRC_MISMATCH = get_pessimistic_bool_from_env( u"FAIL_ON_CRC_MISMATCH" diff --git a/resources/libraries/python/ContainerUtils.py b/resources/libraries/python/ContainerUtils.py index 633144e35f..7ec8258686 100644 --- a/resources/libraries/python/ContainerUtils.py +++ b/resources/libraries/python/ContainerUtils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -587,6 +587,12 @@ class ContainerEngine: topo_instance = BuiltIn().get_library_instance( u"resources.libraries.python.topology.Topology" ) + topo_instance.add_new_socket( + self.container.node, + SocketType.CLI, + self.container.name, + self.container.cli_socket, + ) topo_instance.add_new_socket( self.container.node, SocketType.PAPI, @@ -1277,6 +1283,7 @@ class Container: path = f"/tmp/vpp_sockets/{value}" self.__dict__[u"socket_dir"] = path self.__dict__[u"api_socket"] = f"{path}/api.sock" + self.__dict__[u"cli_socket"] = f"{path}/cli.sock" self.__dict__[u"stats_socket"] = f"{path}/stats.sock" self.__dict__[attr] = value else: diff --git a/resources/libraries/python/TelemetryUtil.py b/resources/libraries/python/TelemetryUtil.py index be2f4796b2..2d4bb096c6 100644 --- a/resources/libraries/python/TelemetryUtil.py +++ b/resources/libraries/python/TelemetryUtil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -133,7 +133,7 @@ class TelemetryUtil: for node in nodes.values(): if node[u"type"] == NodeType.DUT: try: - for socket in node[u"sockets"][u"PAPI"].values(): + for socket in node[u"sockets"][u"CLI"].values(): TelemetryUtil.run_telemetry( node, profile=profile, hook=socket ) diff --git a/resources/libraries/python/VPPUtil.py b/resources/libraries/python/VPPUtil.py index 0d5dea57df..daeb568bda 100644 --- a/resources/libraries/python/VPPUtil.py +++ b/resources/libraries/python/VPPUtil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -72,6 +72,8 @@ class VPPUtil: PapiSocketExecutor.disconnect_all_sockets_by_node(node) DUTSetup.restart_service(node, Constants.VPP_UNIT) if node_key: + Topology.add_new_socket( + node, SocketType.CLI, node_key, Constants.SOCKCLI_PATH) Topology.add_new_socket( node, SocketType.PAPI, node_key, Constants.SOCKSVR_PATH) Topology.add_new_socket( diff --git a/resources/libraries/python/topology.py b/resources/libraries/python/topology.py index fba2dcb189..454692807c 100644 --- a/resources/libraries/python/topology.py +++ b/resources/libraries/python/topology.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -71,6 +71,8 @@ class SocketType: PAPI = u"PAPI" # VPP PAPI Stats (legacy option until stats are migrated to Socket PAPI) STATS = u"STATS" + # VPP Socket CLI + CLI = u"CLI" DICT__nodes = load_topo_from_yaml() diff --git a/resources/libraries/robot/performance/performance_actions.robot b/resources/libraries/robot/performance/performance_actions.robot index 98f53ae4e9..3235dfa868 100644 --- a/resources/libraries/robot/performance/performance_actions.robot +++ b/resources/libraries/robot/performance/performance_actions.robot @@ -94,7 +94,7 @@ | | ... | ramp_up_duration=${ramp_up_duration} | | ... | ramp_up_rate=${ramp_up_rate} | | Run Telemetry On All DUTs -| | ... | ${nodes} | profile=vpp_runtime.yaml +| | ... | ${nodes} | profile=vppctl_runtime.yaml | | Stop traffic on tg | Additional Statistics Action For vpp-runtime-iperf3 @@ -119,7 +119,7 @@ | | | ... | bind=${iperf_client_bind} | | | ... | affinity=${iperf_client_affinity} | | Run Telemetry On All DUTs -| | ... | ${nodes} | profile=vpp_runtime.yaml +| | ... | ${nodes} | profile=vppctl_runtime.yaml | | iPerf Client Stop Remote Exec | ${nodes['${iperf_client_node}']} | ${pids} | Additional Statistics Action For noop @@ -133,7 +133,7 @@ | | ... | Additional Statistics Action for clear VPP statistics. | | | | Run Telemetry On All DUTs -| | ... | ${nodes} | profile=vpp_clear_stats.yaml +| | ... | ${nodes} | profile=vppctl_clear_stats.yaml | Additional Statistics Action For vpp-enable-packettrace | | [Documentation] @@ -154,4 +154,4 @@ | | ... | Additional Statistics Action for show VPP statistics. | | | | Run Telemetry On All DUTs -| | ... | ${nodes} | profile=vpp_show_stats.yaml +| | ... | ${nodes} | profile=vppctl_show_stats.yaml diff --git a/resources/templates/telemetry/vppctl_clear_stats.yaml b/resources/templates/telemetry/vppctl_clear_stats.yaml new file mode 100644 index 0000000000..7c5124eb03 --- /dev/null +++ b/resources/templates/telemetry/vppctl_clear_stats.yaml @@ -0,0 +1,218 @@ +--- +logging: + version: 1 + formatters: + console_stdout: + format: '%(asctime)s - %(name)s - %(message)s' + console_stderr: + format: '%(message)s' + prom: + format: '%(message)s' + handlers: + console_stdout: + class: logging.StreamHandler + level: INFO + formatter: console_stdout + stream: ext://sys.stdout + console_stderr: + class: logging.StreamHandler + level: ERROR + formatter: console_stderr + stream: ext://sys.stderr + prom: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: prom + filename: /tmp/metric.prom + mode: w + loggers: + prom: + handlers: [prom] + level: INFO + propagate: False + root: + level: INFO + handlers: [console_stdout, console_stderr] +scheduler: + duration: 1 +programs: + - name: bundle_vppctl + metrics: + gauge: + - name: calls + documentation: Number of calls total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors + documentation: Number of vectors total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: suspends + documentation: Number of suspends total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: clocks + documentation: Number of clocks total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors_calls + documentation: Number of vectors per call + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + code: | + vppctl -s {socket} clear runtime + - name: bundle_vppctl + metrics: + gauge: + - name: rx_packets + documentation: Number of received packets for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of received bytes for interface + labelnames: + - name + - index + - name: rx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: tx_packets + documentation: Number of transitted packets for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of transitted bytes for interface + labelnames: + - name + - index + - name: tx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: drops + documentation: Number of dropped packets for interface + labelnames: + - name + - index + - name: punt + documentation: Number of punted packets for interface + labelnames: + - name + - index + - name: ip4 + documentation: Number of IPv4 packets for interface + labelnames: + - name + - index + - name: ip6 + documentation: Number of IPv6 packets for interface + labelnames: + - name + - index + - name: mpls + documentation: Number of MPLS packets for interface + labelnames: + - name + - index + - name: rx_no_buf + documentation: Number of out of buffer RX packets on interface + labelnames: + - name + - index + - name: rx_miss + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} clear interfaces + - name: bundle_vppctl + metrics: + gauge: + - name: rx_frames + documentation: Number of RX frames for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of RX bytes for interface + labelnames: + - name + - index + - name: tx_frames + documentation: Number of TX frames for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of TX bytes for interface + labelnames: + - name + - index + - name: rx_missed + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + - name: tx_missed + documentation: Number of missed TX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} clear hardware + - name: bundle_vppctl + metrics: + gauge: + - name: node_counter + documentation: Node counter + labelnames: + - name + - reason + - severity + - thread_name + - thread_id + code: | + vppctl -s {socket} clear node counters + - name: bundle_vppctl + metrics: + gauge: + - name: calls + documentation: Load operations + labelnames: + - name + - thread_name + - thread_id + - name: packets + documentation: Load operations + labelnames: + - name + - thread_name + - thread_id + code: | + vppctl -s {socket} perfmon reset diff --git a/resources/templates/telemetry/vppctl_runtime.yaml b/resources/templates/telemetry/vppctl_runtime.yaml new file mode 100644 index 0000000000..d8ff734e84 --- /dev/null +++ b/resources/templates/telemetry/vppctl_runtime.yaml @@ -0,0 +1,481 @@ +--- +logging: + version: 1 + formatters: + console_stdout: + format: '%(asctime)s - %(name)s - %(message)s' + console_stderr: + format: '%(message)s' + prom: + format: '%(message)s' + handlers: + console_stdout: + class: logging.StreamHandler + level: INFO + formatter: console_stdout + stream: ext://sys.stdout + console_stderr: + class: logging.StreamHandler + level: ERROR + formatter: console_stderr + stream: ext://sys.stderr + prom: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: prom + filename: /tmp/metric.prom + mode: w + loggers: + prom: + handlers: [prom] + level: INFO + propagate: False + root: + level: INFO + handlers: [console_stdout, console_stderr] +scheduler: + duration: 1 +programs: + - name: bundle_vppctl + metrics: + info: + - name: version + documentation: VPP version + namespace: vpp + subsystem: version + labelnames: + - version + code: | + vppctl -s {socket} show version + - name: bundle_vppctl + metrics: + gauge: + - name: calls + documentation: Number of calls total + namespace: vpp + subsystem: runtime + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors + documentation: Number of vectors total + namespace: vpp + subsystem: runtime + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: suspends + documentation: Number of suspends total + namespace: vpp + subsystem: runtime + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: clocks + documentation: Number of clocks total + namespace: vpp + subsystem: runtime + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors_calls + documentation: Number of vectors per call + namespace: vpp + subsystem: runtime + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + code: | + vppctl -s {socket} clear runtime + sleep {duration} + vppctl -s {socket} show runtime + - name: bundle_vppctl + metrics: + gauge: + - name: rx_packets + documentation: Number of received packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of received bytes for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: rx_error + documentation: Number of errors on interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: tx_packets + documentation: Number of transitted packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of transitted bytes for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: tx_error + documentation: Number of errors on interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: drops + documentation: Number of dropped packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: punt + documentation: Number of punted packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: ip4 + documentation: Number of IPv4 packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: ip6 + documentation: Number of IPv6 packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: mpls + documentation: Number of MPLS packets for interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: rx_no_buf + documentation: Number of out of buffer RX packets on interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + - name: rx_miss + documentation: Number of missed RX packets on interface + namespace: vpp + subsystem: interface + labelnames: + - name + - index + code: | + vppctl -s {socket} clear interfaces + sleep {duration} + vppctl -s {socket} show interface + - name: bundle_vppctl + metrics: + gauge: + - name: node_counter + documentation: Node counter + namespace: vpp + subsystem: counters + labelnames: + - name + - reason + - severity + - thread_name + - thread_id + code: | + vppctl -s {socket} clear node counters + sleep {duration} + vppctl -s {socket} show node counters verbose + - name: bundle_vppctl + metrics: + gauge: + - name: context_switches + documentation: Per-thread context switches + namespace: vpp + subsystem: context_switches + labelnames: + - name + - id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle context-switches + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: minor_page_faults + documentation: Per-thread page faults (minor) + namespace: vpp + subsystem: page_faults + labelnames: + - name + - id + - name: major_page_faults + documentation: Per-thread page faults (major) + namespace: vpp + subsystem: page_faults + labelnames: + - name + - id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle page-faults + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: calls + documentation: Instructions/packet, cycles/packet and IPC (calls) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + - name: packets + documentation: Instructions/packet, cycles/packet and IPC (packets) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + - name: packets_per_call + documentation: Instructions/packet, cycles/packet and IPC (packets/call) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + - name: clocks_per_packets + documentation: Instructions/packet, cycles/packet and IPC (clocks/packets) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + - name: instructions_per_packets + documentation: Instructions/packet, cycles/packet and IPC (clocks/packets) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + - name: ipc + documentation: Instructions/packet, cycles/packet and IPC (clocks/packets) + namespace: vpp + subsystem: inst_and_clock + labelnames: + - name + - thread_name + - thread_id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle inst-and-clock + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: l1_hit + documentation: Cache hits and misses (L1 hit) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + - name: l1_miss + documentation: Cache hits and misses (L1 miss) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + - name: l2_hit + documentation: Cache hits and misses (L2 hit) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + - name: l2_miss + documentation: Cache hits and misses (L2 miss) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + - name: l3_hit + documentation: Cache hits and misses (L3 hit) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + - name: l3_miss + documentation: Cache hits and misses (L3 miss) + namespace: vpp + subsystem: cache_hierarchy + labelnames: + - name + - thread_name + - thread_id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle cache-hierarchy + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: calls + documentation: Load operations (calls) + namespace: vpp + subsystem: load_blocks + labelnames: + - name + - thread_name + - thread_id + - name: packets + documentation: Load operations (packets) + namespace: vpp + subsystem: load_blocks + labelnames: + - name + - thread_name + - thread_id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle load-blocks + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: branches_per_call + documentation: Branches/call + namespace: vpp + subsystem: branch_mispred + labelnames: + - name + - thread_name + - thread_id + - name: branches_per_packet + documentation: Branches/packet + namespace: vpp + subsystem: branch_mispred + labelnames: + - name + - thread_name + - thread_id + - name: taken_per_call + documentation: Taken/call + namespace: vpp + subsystem: branch_mispred + labelnames: + - name + - thread_name + - thread_id + - name: taken_per_packet + documentation: Taken/packet + namespace: vpp + subsystem: branch_mispred + labelnames: + - name + - thread_name + - thread_id + - name: mis_predictions + documentation: Mis-predictions + namespace: vpp + subsystem: branch_mispred + labelnames: + - name + - thread_name + - thread_id + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle branch-mispred + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics + - name: bundle_vppctl + metrics: + gauge: + - name: runtime + documentation: RunTime + namespace: vpp + subsystem: memory_bandwidth + labelnames: + - name + - name: reads_mbs + documentation: Reads (MB/s) + namespace: vpp + subsystem: memory_bandwidth + labelnames: + - name + - name: writes_mbs + documentation: Writes (MB/s) + namespace: vpp + subsystem: memory_bandwidth + labelnames: + - name + - name: total_mbs + documentation: Total (MB/s) + namespace: vpp + subsystem: memory_bandwidth + labelnames: + - name + code: | + vppctl -s {socket} perfmon reset + vppctl -s {socket} perfmon start bundle memory-bandwidth + sleep {duration} + vppctl -s {socket} perfmon stop + vppctl -s {socket} show perfmon statistics diff --git a/resources/templates/telemetry/vppctl_show_stats.yaml b/resources/templates/telemetry/vppctl_show_stats.yaml new file mode 100644 index 0000000000..83bb746773 --- /dev/null +++ b/resources/templates/telemetry/vppctl_show_stats.yaml @@ -0,0 +1,201 @@ +--- +logging: + version: 1 + formatters: + console_stdout: + format: '%(asctime)s - %(name)s - %(message)s' + console_stderr: + format: '%(message)s' + prom: + format: '%(message)s' + handlers: + console_stdout: + class: logging.StreamHandler + level: INFO + formatter: console_stdout + stream: ext://sys.stdout + console_stderr: + class: logging.StreamHandler + level: ERROR + formatter: console_stderr + stream: ext://sys.stderr + prom: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: prom + filename: /tmp/metric.prom + mode: w + loggers: + prom: + handlers: [prom] + level: INFO + propagate: False + root: + level: INFO + handlers: [console_stdout, console_stderr] +scheduler: + duration: 1 +programs: + - name: bundle_vppctl + metrics: + counter: + - name: calls + documentation: Number of calls total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors + documentation: Number of vectors total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: suspends + documentation: Number of suspends total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: clocks + documentation: Number of clocks total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors_calls + documentation: Number of vectors per call + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + code: | + vppctl -s {socket} show runtime + - name: bundle_vppctl + metrics: + counter: + - name: rx_packets + documentation: Number of received packets for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of received bytes for interface + labelnames: + - name + - index + - name: rx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: tx_packets + documentation: Number of transitted packets for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of transitted bytes for interface + labelnames: + - name + - index + - name: tx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: drops + documentation: Number of dropped packets for interface + labelnames: + - name + - index + - name: punt + documentation: Number of punted packets for interface + labelnames: + - name + - index + - name: ip4 + documentation: Number of IPv4 packets for interface + labelnames: + - name + - index + - name: ip6 + documentation: Number of IPv6 packets for interface + labelnames: + - name + - index + - name: mpls + documentation: Number of MPLS packets for interface + labelnames: + - name + - index + - name: rx_no_buf + documentation: Number of out of buffer RX packets on interface + labelnames: + - name + - index + - name: rx_miss + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} show interface + - name: bundle_vppctl + metrics: + gauge: + - name: rx_frames + documentation: Number of RX frames for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of RX bytes for interface + labelnames: + - name + - index + - name: tx_frames + documentation: Number of TX frames for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of TX bytes for interface + labelnames: + - name + - index + - name: rx_missed + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + - name: tx_missed + documentation: Number of missed TX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} show hardware verbose + - name: bundle_vppctl + metrics: + counter: + - name: node_counter + documentation: Node counter + labelnames: + - name + - reason + - severity + - thread_name + - thread_id + code: | + vppctl -s {socket} show node counters verbose diff --git a/resources/templates/telemetry/vppctl_test_teardown.yaml b/resources/templates/telemetry/vppctl_test_teardown.yaml new file mode 100644 index 0000000000..10f2077137 --- /dev/null +++ b/resources/templates/telemetry/vppctl_test_teardown.yaml @@ -0,0 +1,201 @@ +--- +logging: + version: 1 + formatters: + console_stdout: + format: '%(asctime)s - %(name)s - %(message)s' + console_stderr: + format: '%(message)s' + prom: + format: '%(message)s' + handlers: + console_stdout: + class: logging.StreamHandler + level: INFO + formatter: console_stdout + stream: ext://sys.stdout + console_stderr: + class: logging.StreamHandler + level: ERROR + formatter: console_stderr + stream: ext://sys.stderr + prom: + class: logging.handlers.RotatingFileHandler + level: INFO + formatter: prom + filename: /tmp/metric.prom + mode: w + loggers: + prom: + handlers: [prom] + level: INFO + propagate: False + root: + level: INFO + handlers: [console_stdout, console_stderr] +scheduler: + duration: 0 +programs: + - name: bundle_vppctl + metrics: + counter: + - name: calls + documentation: Number of calls total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors + documentation: Number of vectors total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: suspends + documentation: Number of suspends total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: clocks + documentation: Number of clocks total + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + - name: vectors_calls + documentation: Number of vectors per call + labelnames: + - name + - state + - thread_name + - thread_id + - thread_lcore + code: | + vppctl -s {socket} show runtime + - name: bundle_vppctl + metrics: + counter: + - name: rx_packets + documentation: Number of received packets for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of received bytes for interface + labelnames: + - name + - index + - name: rx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: tx_packets + documentation: Number of transitted packets for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of transitted bytes for interface + labelnames: + - name + - index + - name: tx_error + documentation: Number of errors on interface + labelnames: + - name + - index + - name: drops + documentation: Number of dropped packets for interface + labelnames: + - name + - index + - name: punt + documentation: Number of punted packets for interface + labelnames: + - name + - index + - name: ip4 + documentation: Number of IPv4 packets for interface + labelnames: + - name + - index + - name: ip6 + documentation: Number of IPv6 packets for interface + labelnames: + - name + - index + - name: mpls + documentation: Number of MPLS packets for interface + labelnames: + - name + - index + - name: rx_no_buf + documentation: Number of out of buffer RX packets on interface + labelnames: + - name + - index + - name: rx_miss + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} show interface + - name: bundle_vppctl + metrics: + gauge: + - name: rx_frames + documentation: Number of RX frames for interface + labelnames: + - name + - index + - name: rx_bytes + documentation: Number of RX bytes for interface + labelnames: + - name + - index + - name: tx_frames + documentation: Number of TX frames for interface + labelnames: + - name + - index + - name: tx_bytes + documentation: Number of TX bytes for interface + labelnames: + - name + - index + - name: rx_missed + documentation: Number of missed RX packets on interface + labelnames: + - name + - index + - name: tx_missed + documentation: Number of missed TX packets on interface + labelnames: + - name + - index + code: | + vppctl -s {socket} show hardware verbose + - name: bundle_vppctl + metrics: + counter: + - name: node_counter + documentation: Node counter + labelnames: + - name + - reason + - severity + - thread_name + - thread_id + code: | + vppctl -s {socket} show node counters verbose diff --git a/resources/tools/telemetry/bundle_vppctl.py b/resources/tools/telemetry/bundle_vppctl.py new file mode 100644 index 0000000000..b417ab07ed --- /dev/null +++ b/resources/tools/telemetry/bundle_vppctl.py @@ -0,0 +1,424 @@ +# Copyright (c) 2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""VPP execution bundle.""" + +from logging import getLogger +from re import fullmatch, sub +import subprocess +import sys + +from .constants import Constants + +M_RUN_THREAD = ( + r"Thread\s" + r"(?P\d+)\s" + r"(?P\S+)\s.*" + r"(?P\d+).*" +) +M_RUN_SEPARATOR = ( + r"(-)+" +) +M_RUN_NODES = ( + r"(?P\S+)\s+" + r"(?P\S+\s\S+|\S+)\s+" + r"(?P\d+)\s+" + r"(?P\d+)\s+" + r"(?P\d+)\s+" + r"(?P\S+)\s+" + r"(?P\S+)" +) +M_RUN_TIME = ( + r"Time\s\S+,\s\d+\ssec\sinternal\snode\svector\srate\s" + r"(?P\S+)\sloops/sec\s" + r"(?P\S+)" +) +M_INT_BEGIN = ( + r"(?P\S+)\s+" + r"(?P\S+)\s+" + r"(?P\S+)\s+" + r"(?P\S+)\s+" + r"(?P\S+\s\S+|\S+)\s+" + r"(?P\d+)" +) +M_INT_CONT = ( + r"\s+" + r"(?P\S+\s\S+|\S+)\s+" + r"(?P\d+)" +) +M_NODE_COUNTERS_THREAD = ( + r"Thread\s" + r"(?P\d+)\s\(" + r"(?P\S+)\):\s*" +) +M_NODE_COUNTERS = ( + r"\s*" + r"(?P\d+)\s+" + r"(?P\S+)\s+" + r"(?P(\S+\s)+)\s+" + r"(?P\S+)\s+" + r"(?P\d+)\s*" +) +M_PMB_CS_HEADER = ( + r"\s*per-thread\s+context\s+switches.*" +) +M_PMB_CS = ( + r"(?P\S+)\s+\(" + r"(?P\S+)\)\s+\S+\s+" + r"(?P[\d\.]+)" +) +M_PMB_PF_HEADER = ( + r"\s*per-thread\s+page\s+faults.*" +) +M_PMB_PF = ( + r"(?P\S+)\s+\(" + r"(?P\S+)\)\s+\S+\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) +M_PMB_THREAD = ( + r"\s*" + r"(?P\S+)\s+\(" + r"(?P\d+)\)\s*" +) +M_PMB_IC_HEADER = ( + r"\s*instructions/packet,\s+cycles/packet\s+and\s+IPC.*" +) +M_PMB_IC_NODE = ( + r"\s*" + r"(?P\S+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) +M_PMB_CM_HEADER = ( + r"\s*cache\s+hits\s+and\s+misses.*" +) +M_PMB_CM_NODE = ( + r"\s*" + r"(?P\S+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) +M_PMB_LO_HEADER = ( + r"\s*load\s+operations.*" +) +M_PMB_LO_NODE = ( + r"\s*" + r"(?P\S+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) +M_PMB_BM_HEADER = ( + r"\s*Branches,\s+branches\s+taken\s+and\s+mis-predictions.*" +) +M_PMB_BM_NODE = ( + r"\s*" + r"(?P\S+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) +M_PMB_MB_HEADER = ( + r"\s*memory\s+reads\s+and\s+writes\s+per\s+memory\s+controller.*" +) +M_PMB_MB = ( + r"\s*" + r"(?P\S+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)\s+" + r"(?P[\d\.]+)" +) + + +class BundleVppctl: + """ + Creates a VPP object. This is the main object for defining a VPP program, + and interacting with its output. + """ + def __init__(self, program, serializer, hook): + """ + Initialize Bundle VPP class. + + :param program: VPP instructions. + :param serializer: Metric serializer. + :param hook: VPP CLI socket. + :type program: dict + :type serializer: Serializer + :type hook: int + """ + self.obj = None + self.code = program["code"] + self.metrics = program["metrics"] + self.cli_command_list = list() + self.cli_replies_list = list() + self.serializer = serializer + self.hook = hook + + def attach(self, duration): + """ + Attach events to VPP. + + :param duration: Trial duration. + :type duration: int + """ + for command in self.code.splitlines(): + self.cli_command_list.append( + command.format(duration=duration, socket=self.hook) + ) + + def detach(self): + """ + Detach from VPP. + """ + + def fetch_data(self): + """ + Fetch data by invoking subprocess calls. + """ + for command in self.cli_command_list: + try: + replies = subprocess.getoutput(command) + except (AssertionError, AttributeError): + getLogger("console_stderr").error( + f"Failed when executing command: {command}" + ) + sys.exit(Constants.err_vpp_execute) + + self.cli_replies_list.append(replies) + replies = sub(r"\x1b[^m]*m", "", replies) + if replies: + getLogger(__name__).info(replies) + else: + getLogger(__name__).info("") + self.serializer.create(metrics=self.metrics) + + def process_data(self): + """ + Post process command reply. + """ + for command in zip(self.cli_command_list, self.cli_replies_list): + self_fn = command[0].replace( + f"-s {self.hook} ", "").replace(" ", "_") + self_method_list = [meth for meth in dir(self) + if callable(getattr(self, meth)) and + meth.startswith('__') is False] + if self_fn not in self_method_list: + continue + try: + self_fn = getattr(self, self_fn) + self_fn(command[1]) + except AttributeError: + pass + except (KeyError, ValueError, TypeError) as exc: + getLogger("console_stderr").error( + f"Failed when processing data. Error message {exc}" + ) + sys.exit(Constants.err_telemetry_process) + + def vppctl_show_interface(self, reply): + """ + Parse the show interface output. + + :param reply: VPP reply. + :type reply: str + """ + for line in reply.splitlines(): + item = dict() + labels = dict() + if fullmatch(M_INT_BEGIN, line): + ifc = fullmatch(M_INT_BEGIN, line).groupdict() + metric = ifc["counter"].replace(" ", "_").replace("-", "_") + item["name"] = metric + item["value"] = ifc["count"] + if fullmatch(M_INT_CONT, line): + ifc_cnt = fullmatch(M_INT_CONT, line).groupdict() + metric = ifc_cnt["counter"].replace(" ", "_").replace("-", "_") + item["name"] = metric + item["value"] = ifc_cnt["count"] + if fullmatch(M_INT_BEGIN, line) or fullmatch(M_INT_CONT, line): + labels["name"] = ifc["name"] + labels["index"] = ifc["index"] + item["labels"] = labels + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + def vppctl_show_runtime(self, reply): + """ + Parse the show runtime output. + + :param reply: VPP reply. + :type reply: str + """ + for line in reply.splitlines(): + if fullmatch(M_RUN_THREAD, line): + thread = fullmatch(M_RUN_THREAD, line).groupdict() + if fullmatch(M_RUN_NODES, line): + nodes = fullmatch(M_RUN_NODES, line).groupdict() + for metric in self.serializer.metric_registry: + item = dict() + labels = dict() + item["name"] = metric + labels["name"] = nodes["name"] + labels["state"] = nodes["state"] + try: + labels["thread_name"] = thread["thread_name"] + labels["thread_id"] = thread["thread_id"] + labels["thread_lcore"] = thread["thread_lcore"] + except UnboundLocalError: + labels["thread_name"] = "vpp_main" + labels["thread_id"] = "0" + labels["thread_lcore"] = "0" + item["labels"] = labels + item["value"] = nodes[metric] + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + def vppctl_show_node_counters_verbose(self, reply): + """ + Parse the show node conuter output. + + :param reply: VPP reply. + :type reply: str + """ + for line in reply.splitlines(): + if fullmatch(M_NODE_COUNTERS_THREAD, line): + thread = fullmatch(M_NODE_COUNTERS_THREAD, line).groupdict() + if fullmatch(M_NODE_COUNTERS, line): + nodes = fullmatch(M_NODE_COUNTERS, line).groupdict() + for metric in self.serializer.metric_registry_registry: + item = dict() + labels = dict() + item["name"] = metric + labels["name"] = nodes["name"] + labels["reason"] = nodes["reason"] + labels["severity"] = nodes["severity"] + try: + labels["thread_name"] = thread["thread_name"] + labels["thread_id"] = thread["thread_id"] + except UnboundLocalError: + labels["thread_name"] = "vpp_main" + labels["thread_id"] = "0" + item["labels"] = labels + item["value"] = nodes["count"] + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + def vppctl_show_perfmon_statistics(self, reply): + """ + Parse the perfmon output. + + :param reply: VPP reply. + :type reply: str + """ + def perfmon_threads(reply, regex_threads): + for line in reply.splitlines(): + if fullmatch(regex_threads, line): + threads = fullmatch(regex_threads, line).groupdict() + for metric in self.serializer.metric_registry: + item = dict() + labels = dict() + item["name"] = metric + labels["name"] = threads["thread_name"] + labels["id"] = threads["thread_id"] + item["labels"] = labels + item["value"] = threads[metric] + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + def perfmon_nodes(reply, regex_threads, regex_nodes): + for line in reply.splitlines(): + if fullmatch(regex_threads, line): + thread = fullmatch(regex_threads, line).groupdict() + if fullmatch(regex_nodes, line): + node = fullmatch(regex_nodes, line).groupdict() + for metric in self.serializer.metric_registry: + item = dict() + labels = dict() + item["name"] = metric + labels["name"] = node["node_name"] + labels["thread_name"] = thread["thread_name"] + labels["thread_id"] = thread["thread_id"] + item["labels"] = labels + item["value"] = node[metric] + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + def perfmon_system(reply, regex_line): + for line in reply.splitlines(): + if fullmatch(regex_line, line): + name = fullmatch(regex_line, line).groupdict() + for metric in self.serializer.metric_registry: + item = dict() + labels = dict() + item["name"] = metric + labels["name"] = name["name"] + item["labels"] = labels + item["value"] = name[metric] + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) + + reply = sub(r"\x1b[^m]*m", "", reply) + + if fullmatch(M_PMB_CS_HEADER, reply.splitlines()[0]): + perfmon_threads(reply, M_PMB_CS) + if fullmatch(M_PMB_PF_HEADER, reply.splitlines()[0]): + perfmon_threads(reply, M_PMB_PF) + if fullmatch(M_PMB_IC_HEADER, reply.splitlines()[0]): + perfmon_nodes(reply, M_PMB_THREAD, M_PMB_IC_NODE) + if fullmatch(M_PMB_CM_HEADER, reply.splitlines()[0]): + perfmon_nodes(reply, M_PMB_THREAD, M_PMB_CM_NODE) + if fullmatch(M_PMB_LO_HEADER, reply.splitlines()[0]): + perfmon_nodes(reply, M_PMB_THREAD, M_PMB_LO_NODE) + if fullmatch(M_PMB_BM_HEADER, reply.splitlines()[0]): + perfmon_nodes(reply, M_PMB_THREAD, M_PMB_BM_NODE) + if fullmatch(M_PMB_MB_HEADER, reply.splitlines()[0]): + perfmon_system(reply, M_PMB_MB) + + def vppctl_show_version(self, reply): + """ + Parse the version output. + + :param reply: VPP reply. + :type reply: str + """ + for metric in self.serializer.metric_registry: + version = reply.split()[1] + item = dict() + labels = dict() + item["name"] = metric + labels["version"] = version + item["labels"] = labels + item["value"] = {} + self.serializer.serialize( + metric=metric, labels=labels, item=item + ) -- cgit 1.2.3-korg