Coverage for osm_mon/evaluator/backends/prometheus.py: 57%

56 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-05-06 19:04 +0000

1# -*- coding: utf-8 -*- 

2 

3# Copyright 2018 Whitestack, LLC 

4# ************************************************************* 

5 

6# This file is part of OSM Monitoring module 

7# All Rights Reserved to Whitestack, LLC 

8 

9# Licensed under the Apache License, Version 2.0 (the "License"); you may 

10# not use this file except in compliance with the License. You may obtain 

11# a copy of the License at 

12 

13# http://www.apache.org/licenses/LICENSE-2.0 

14 

15# Unless required by applicable law or agreed to in writing, software 

16# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

17# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

18# License for the specific language governing permissions and limitations 

19# under the License. 

20# For those usages not covered by the Apache License, Version 2.0 please 

21# contact: bdiaz@whitestack.com or glavado@whitestack.com 

22## 

23import base64 

24import logging 

25from typing import Dict, List 

26 

27import requests 

28 

29from osm_mon.core.config import Config 

30from osm_mon.evaluator.backends.base import BaseBackend 

31 

32log = logging.getLogger(__name__) 

33 

34OSM_METRIC_PREFIX = "osm_" 

35 

36DEFAULT_QUERY_METRICS = ["ns_id", "vnf_member_index", "vdu_name"] 

37 

38 

39class PrometheusBackend(BaseBackend): 

40 def __init__(self, config: Config): 

41 super().__init__(config) 

42 self.conf = config 

43 

44 def get_metric_data(self, metric_name: str, tags: dict): 

45 query = self._build_query(metric_name, tags) 

46 request_url = self._build_url(query) 

47 request_headers = self._build_headers() 

48 return self._query_metric(request_url, request_headers) 

49 

50 def _query_metric(self, request_url: str, headers: Dict[str, str]): 

51 log.info("Querying Prometheus: %s", request_url) 

52 r = requests.get( 

53 request_url, 

54 timeout=int(self.conf.get("global", "request_timeout")), 

55 headers=headers, 

56 ) 

57 if r.status_code == 200: 

58 json_response = r.json() 

59 if json_response["status"] == "success": 

60 return self._get_metric_data_from_response(json_response) 

61 else: 

62 log.warning( 

63 "Prometheus response is not success. Got status %s", 

64 json_response["status"], 

65 ) 

66 else: 

67 log.warning( 

68 "Error contacting Prometheus. Got status code %s: %s", 

69 r.status_code, 

70 r.text, 

71 ) 

72 return None 

73 

74 def _build_query(self, metric_name: str, tags: dict) -> str: 

75 query_section_tags = [] 

76 for k, v in tags.items(): 

77 query_section_tags.append(k + '="' + v + '"') 

78 query_section = "query={0}{{{1}}}".format( 

79 OSM_METRIC_PREFIX + metric_name, ",".join(query_section_tags) 

80 ) 

81 return query_section 

82 

83 def _build_url(self, query: str): 

84 return self.conf.get("prometheus", "url") + "/api/v1/query?" + query 

85 

86 def _build_headers(self) -> Dict[str, str]: 

87 headers = {} 

88 user = self.conf.get("prometheus", "user") 

89 password = self.conf.get("prometheus", "password") 

90 if user and password: 

91 _phrase = f"{user}:{password}".encode("utf-8") 

92 token = base64.b64encode(_phrase).decode("utf-8") 

93 headers["Authorization"] = f"Basic {token}" 

94 return headers 

95 

96 def _get_metric_data_from_response(self, json_response) -> List[Dict[str, str]]: 

97 result = json_response["data"]["result"] 

98 metrics_data = [] 

99 if len(result): 

100 for metric in result: 

101 metrics_labels = metric["metric"] 

102 metric_value = float(metric["value"][1]) 

103 log.info("Metric value: %s", metric_value) 

104 metrics_data.append({"labels": metrics_labels, "value": metric_value}) 

105 return metrics_data 

106 else: 

107 return None