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