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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """BPF performance bundle."""
16 from logging import getLogger
20 from .constants import Constants
25 Creates a BPF object. This is the main object for defining a BPF program,
26 and interacting with its output.
28 Syntax: BPF({text=BPF_program | src_file=filename}
29 [, usdt_contexts=[USDT_object, ...]]
30 [, cflags=[arg1, ...]] [, debug=int]
33 Exactly one of text or src_file must be supplied (not both).
35 def __init__(self, program, serializer, hook):
36 """Initialize Bundle BPF Perf event class.
38 :param program: BPF C code.
39 :param serializer: Metric serializer.
40 :param hook: Process ID.
42 :type serializer: Serializer
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
53 self.obj = BPF(text=self.code)
55 def attach(self, duration):
59 :param duration: Trial duration.
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
70 except AttributeError:
71 getLogger("console_stderr").error(u"Could not attach BPF events!")
72 sys.exit(Constants.err_linux_attach)
76 Dettach events from BPF.
79 for event in self.events:
80 self.obj.detach_perf_event(
81 ev_type=event[u"type"],
82 ev_config=event[u"name"]
84 except AttributeError:
85 getLogger("console_stderr").error(u"Could not detach BPF events!")
86 sys.exit(Constants.err_linux_detach)
90 Fetch data by invoking API calls to BPF.
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():
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)
106 def process_data(self):
108 Post process API replies.
110 for item in self.api_replies_list:
111 self.serializer.serialize(
112 metric=item[u"name"], labels=item[u"labels"], item=item