telemetry: error message handling part2
[csit.git] / resources / tools / telemetry / bundle_bpf.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 """BPF performance bundle."""
15
16 from logging import getLogger
17 import sys
18
19 from bcc import BPF
20 from .constants import Constants
21
22
23 class BundleBpf:
24     """
25     Creates a BPF object. This is the main object for defining a BPF program,
26     and interacting with its output.
27
28     Syntax: BPF({text=BPF_program | src_file=filename}
29                 [, usdt_contexts=[USDT_object, ...]]
30                 [, cflags=[arg1, ...]] [, debug=int]
31             )
32
33     Exactly one of text or src_file must be supplied (not both).
34     """
35     def __init__(self, program, serializer, hook):
36         """Initialize Bundle BPF Perf event class.
37
38         :param program: BPF C code.
39         :param serializer: Metric serializer.
40         :param hook: Process ID.
41         :type program: dict
42         :type serializer: Serializer
43         :type hook: int
44         """
45         self.obj = None
46         self.code = program[u"code"]
47         self.metrics = program[u"metrics"]
48         self.events = program[u"events"]
49         self.api_replies_list = list()
50         self.serializer = serializer
51         self.hook = hook
52
53         self.obj = BPF(text=self.code)
54
55     def attach(self, duration):
56         """
57         Attach events to BPF.
58
59         :param duration: Trial duration.
60         :type duration: int
61         """
62         try:
63             for event in self.events:
64                 self.obj.attach_perf_event(
65                     ev_type=event[u"type"],
66                     ev_config=event[u"name"],
67                     fn_name=event[u"target"],
68                     sample_period=duration
69                 )
70         except AttributeError:
71             getLogger("console_stderr").error(u"Could not attach BPF events!")
72             sys.exit(Constants.err_linux_attach)
73
74     def detach(self):
75         """
76         Dettach events from BPF.
77         """
78         try:
79             for event in self.events:
80                 self.obj.detach_perf_event(
81                     ev_type=event[u"type"],
82                     ev_config=event[u"name"]
83                 )
84         except AttributeError:
85             getLogger("console_stderr").error(u"Could not detach BPF events!")
86             sys.exit(Constants.err_linux_detach)
87
88     def fetch_data(self):
89         """
90         Fetch data by invoking API calls to BPF.
91         """
92         self.serializer.create(metrics=self.metrics)
93         for _, metric_list in self.metrics.items():
94             for metric in metric_list:
95                 for (key, val) in self.obj.get_table(metric[u"name"]).items():
96                     item = dict()
97                     labels = dict()
98                     item[u"name"] = metric[u"name"]
99                     item[u"value"] = val.value
100                     for label in metric[u"labelnames"]:
101                         labels[label] = getattr(key, label)
102                     item[u"labels"] = labels
103                     self.api_replies_list.append(item)
104                     getLogger(__name__).info(item)
105
106     def process_data(self):
107         """
108         Post process API replies.
109         """
110         for item in self.api_replies_list:
111             self.serializer.serialize(
112                 metric=item[u"name"], labels=item[u"labels"], item=item
113             )