telemetry: fix Linux bundles
[csit.git] / resources / tools / telemetry / serializer.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 """Config executor library."""
15
16 from importlib import import_module
17 from logging import getLogger
18
19
20 class Serializer:
21     """
22     Executor class reponsible for executing configuration.
23     """
24     def __init__(self):
25         """
26         Config Executor init.=
27         """
28         self.metric_registry = dict()
29
30     def create(self, metrics):
31         """
32         Create metrics based on input configuration.
33
34         :param metrics: Metric list to create.
35         :type metrics: list
36         """
37         for metric_type, metric_list in metrics.items():
38             for metric in metric_list:
39                 module = import_module(
40                     name=u"telemetry.metrics", package=metric_type.capitalize()
41                 )
42                 self.metric_registry[metric[u"name"]] = getattr(
43                     module, metric_type.capitalize()
44                 )(**metric)
45
46     def serialize(self, metric, labels, item):
47         """
48         Serialize metric into destination format.
49
50         :param metrics: Metric name.
51         :param labels: Metric labels.
52         :param item: Metric dict.
53         :type metrics: str
54         :type labels: dict
55         :type item: dict
56         """
57         if type(self.metric_registry[metric]).__name__ == u"Counter":
58             self.metric_registry[metric].labels(**labels).inc(
59                 float(item[u"value"])
60             )
61         if type(self.metric_registry[metric]).__name__ == u"Gauge":
62             self.metric_registry[metric].labels(**labels).set(
63                 float(item[u"value"])
64             )
65         if type(self.metric_registry[metric]).__name__ == u"Info":
66             self.metric_registry[metric].labels(**labels).info(
67                 item[u"value"]
68             )
69
70     def publish(self):
71         """
72         Publish metric into logger.
73         """
74         output = []
75         for _, metric_list in self.metric_registry.items():
76             for metric in metric_list.collect():
77                 mname = metric.name
78                 mtype = metric.type
79
80                 # Adjust from OpenMetrics into Prometheus format.
81                 mname = f"{mname}_total" if mtype == u"counter" else mname
82                 mname = f"{mname}_info" if mtype == u"info" else mname
83                 if mtype in (u"info", u"stateset"):
84                     mtype = u"gauge"
85                 if mtype in (u"gaugehistogram", u"histogram"):
86                     mtype = u"histogram"
87
88                 mdocumentation = metric.documentation.replace(u"\\", r"\\")
89                 mdocumentation = mdocumentation.replace(u"\n", r"\n")
90                 output.append(f"# HELP {mname} {mdocumentation}\n")
91                 output.append(f"# TYPE {mname} {mtype}\n")
92
93                 for line in metric.samples:
94                     if line.labels:
95                         llabel = []
96                         for k, value in sorted(line.labels.items()):
97                             value = str(value)
98                             value = value.replace(u"\\", r"\\")
99                             value = value.replace(u"\n", r"\n")
100                             value = value.replace(u'"', r'\"')
101                             llabel.append(f'{k}="{value}"')
102                         labelstr = f"{{{','.join(llabel)}}}"
103                     else:
104                         labelstr = u""
105
106                     timestamp = f" {int(float(line.timestamp) * 1000):d}" \
107                         if line.timestamp else u""
108                     output.append(
109                         f"{line.name}{labelstr} {line.value}{timestamp}\n"
110                     )
111         getLogger(u"prom").info(u"".join(output))