X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Ftools%2Ftelemetry%2Fbundle_perf_stat.py;fp=resources%2Ftools%2Ftelemetry%2Fbundle_perf_stat.py;h=038e86e7a0fdb6adb95d21b090e89a77c8a447be;hp=0000000000000000000000000000000000000000;hb=a2182abd2665aa9264464a99ad77718e2c7bbe18;hpb=bff439b69ee71b654b1da92564ff62de7327fe71 diff --git a/resources/tools/telemetry/bundle_perf_stat.py b/resources/tools/telemetry/bundle_perf_stat.py new file mode 100644 index 0000000000..038e86e7a0 --- /dev/null +++ b/resources/tools/telemetry/bundle_perf_stat.py @@ -0,0 +1,109 @@ +# 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. + +"""Perf Stat performance bundle.""" + +from logging import getLogger +import sys +import subprocess + +from .constants import Constants + + +class BundlePerfStat: + """ + Creates a Perf stat object. This is the main object for defining a Perf Stat + program and interacting with its output. + + Syntax: perf stat [-e | --event=EVENT] [-a] — [] + """ + def __init__(self, program, serializer, hook): + """Initialize Bundle Perf Stat event class. + + :param program: events + :param serializer: Metric serializer. + :param hook: Process ID. + :type program: dict + :type serializer: Serializer + :type hook: int + """ + self.metrics = program[u"metrics"] + self.events = program[u"events"] + self.api_replies_list = list() + self.serializer = serializer + self.hook = hook + + def attach(self, duration=1): + """ + Performs perf stat. + + :param duration: Time how long perf stat is collecting data (in + seconds). Default value is 1 second. + :type duration: int + EventCode, UMask, EdgeDetect, AnyThread, Invert, CounterMask + """ + try: + self.serializer.create(metrics=self.metrics) + for event in self.events: + text = subprocess.getoutput( + f"""sudo perf stat -x\; -e\ + '{{cpu/event={hex(event[u"EventCode"])},\ + umask={hex(event[u"UMask"])}/u}}'\ + -a --per-thread\ + sleep {duration}""" + ) + + if text == u"": + getLogger("console_stdout").info(event[u"name"]) + continue + if u";" not in text: + getLogger("console_stdout").info( + f"Could not get counters for event \"{event[u'name']}\"" + f". Is it supported by CPU?" + ) + continue + + for line in text.splitlines(): + item = dict() + labels = dict() + item[u"name"] = event[u"name"] + item[u"value"] = line.split(";")[1] + labels["thread"] = u"-".join( + line.split(";")[0].split("-")[0:-1] + ) + labels["pid"] = line.split(";")[0].split("-")[-1] + labels["name"] = item[u"name"] + item[u"labels"] = labels + + getLogger("console_stdout").info(item) + self.api_replies_list.append(item) + + except AttributeError: + getLogger("console_stderr").error(f"Could not successfully run " + f"perf stat command.") + sys.exit(Constants.err_linux_perf_stat) + + def detach(self): + pass + + def fetch_data(self): + pass + + def process_data(self): + """ + Post process API replies. + """ + for item in self.api_replies_list: + self.serializer.serialize( + metric=item[u"name"], labels=item[u"labels"], item=item + )