17afbe082455475d28766133a9b8714a7a241428
[csit.git] / resources / tools / telemetry / bundle_perf_stat.py
1 # Copyright (c) 2022 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Perf Stat performance bundle."""
15
16 from logging import getLogger
17 import sys
18 import subprocess
19
20 from .constants import Constants
21
22
23 class BundlePerfStat:
24     """
25     Creates a Perf stat object. This is the main object for defining a Perf Stat
26     program and interacting with its output.
27
28     Syntax: perf stat [-e <EVENT> | --event=EVENT] [-a] — <command> [<options>]
29     """
30     def __init__(self, program, serializer, hook):
31         """Initialize Bundle Perf Stat event class.
32
33         :param program: events
34         :param serializer: Metric serializer.
35         :param hook: Process ID.
36         :type program: dict
37         :type serializer: Serializer
38         :type hook: int
39         """
40         self.metrics = program[u"metrics"]
41         self.events = program[u"events"]
42         self.api_replies_list = list()
43         self.serializer = serializer
44         self.hook = hook
45
46     def attach(self, duration=1):
47         """
48                Performs perf stat.
49
50                :param duration: Time how long perf stat is collecting data (in
51                seconds). Default value is 1 second.
52                :type duration: int
53                """
54         try:
55             self.serializer.create(metrics=self.metrics)
56             event = self.events[0]
57             text = subprocess.getoutput(
58                 f"""sudo perf stat -x\; -e\
59                 '{{cpu/event={hex(event[u"eventcode"])},\
60                 umask={hex(event[u"umask"])}/u}}'\
61                 -a --per-thread\
62                 sleep {duration}"""
63             )
64         except subprocess.CalledProcessError:
65             getLogger("console_stderr").error(f"Could not successfully run "
66                                               f"perf stat command.")
67             sys.exit(Constants.err_linux_perf_stat)
68
69         if text == u"":
70             getLogger("console_stdout").info(event[u"eventcode"])
71         else:
72             for line in text.splitlines():
73                 if line.count(u";") < 6:
74                     getLogger("console_stdout").info(
75                         f"Could not get counters for current thread."
76                         f"{line}"
77                     )
78                     continue
79                 item = dict()
80                 labels = dict()
81                 item[u"name"] = self.metrics['counter'][0]['name']
82                 item[u"value"] = line.split(";")[1]
83                 labels["thread"] = u"-".join(
84                     line.split(";")[0].split("-")[0:-1]
85                 )
86                 labels["pid"] = line.split(";")[0].split("-")[-1]
87                 item[u"labels"] = labels
88
89                 getLogger("console_stdout").info(item)
90                 self.api_replies_list.append(item)
91
92
93     def detach(self):
94         pass
95
96     def fetch_data(self):
97        pass
98
99     def process_data(self):
100         """
101         Post process API replies.
102         """
103         for item in self.api_replies_list:
104             self.serializer.serialize(
105                 metric=item[u"name"], labels=item[u"labels"], item=item
106             )