Files
python-observabilityclient/observabilityclient/utils/metric_utils.py
Jaromír Wysoglad a580772449 Prometheus interaction (#7)
* Remove old observability client

* Add initial functionality for prometheus querying

* Fix a copy-paste error in get_client()

* Add additional functionality.

This commit adds:
    - commands:
        delete
        clear-tombstones
        snapshot
    - Better rbac injection as well as a possibility
      to disable rbac.
    - Configuration of prometheus_client through
      env variables and /etc/openstack/prometheus.yaml

* Make README up to date

* Implement Martin's PR comments

* Implement better support for label values in rbac

* PEP8
2023-08-03 15:30:19 +02:00

111 lines
3.2 KiB
Python

# Copyright 2023 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
import yaml
from observabilityclient.prometheus_client import PrometheusAPIClient
DEFAULT_CONFIG_LOCATIONS = [os.environ["HOME"] + "/.config/openstack/",
"/etc/openstack/"]
CONFIG_FILE_NAME = "prometheus.yaml"
LOG = logging.getLogger(__name__)
class ConfigurationError(Exception):
pass
def get_config_file():
if os.path.exists(CONFIG_FILE_NAME):
LOG.debug(f"Using {CONFIG_FILE_NAME} as prometheus configuration")
return open(CONFIG_FILE_NAME, "r")
for path in DEFAULT_CONFIG_LOCATIONS:
full_filename = path + CONFIG_FILE_NAME
if os.path.exists(full_filename):
LOG.debug(f"Using {full_filename} as prometheus configuration")
return open(full_filename, "r")
return None
def get_prometheus_client():
host = None
port = None
conf_file = get_config_file()
if conf_file is not None:
conf = yaml.safe_load(conf_file)
if 'host' in conf:
host = conf['host']
if 'port' in conf:
port = conf['port']
conf_file.close()
# NOTE(jwysogla): We allow to overide the prometheus.yaml by
# the environment variables
if 'PROMETHEUS_HOST' in os.environ:
host = os.environ['PROMETHEUS_HOST']
if 'PROMETHEUS_PORT' in os.environ:
port = os.environ['PROMETHEUS_PORT']
if host is None or port is None:
raise ConfigurationError("Can't find prometheus host and "
"port configuration.")
return PrometheusAPIClient(f"{host}:{port}")
def get_client(obj):
return obj.app.client_manager.observabilityclient
def list2cols(cols, objs):
return cols, [tuple([o[k] for k in cols])
for o in objs]
def format_labels(d: dict) -> str:
def replace_doubled_quotes(string):
if "''" in string:
string = string.replace("''", "'")
if '""' in string:
string = string.replace('""', '"')
return string
ret = ""
for key, value in d.items():
ret += "{}='{}', ".format(key, value)
ret = ret[0:-2]
old = ""
while ret != old:
old = ret
ret = replace_doubled_quotes(ret)
return ret
def metrics2cols(m):
cols = []
fields = []
first = True
for metric in m:
row = []
for key, value in metric.labels.items():
if first:
cols.append(key)
row.append(value)
if first:
cols.append("value")
row.append(metric.value)
fields.append(row)
first = False
return cols, fields