128 lines
4.3 KiB
Python
Executable file
128 lines
4.3 KiB
Python
Executable file
import json
|
||
import time
|
||
import os
|
||
import requests
|
||
import logging
|
||
from prometheus_client import start_http_server, Gauge
|
||
from unidecode import unidecode
|
||
from dotenv import load_dotenv
|
||
|
||
# Настройка логгирования
|
||
logging.basicConfig(
|
||
level=logging.INFO,
|
||
format='%(asctime)s - %(levelname)s - %(message)s',
|
||
handlers=[
|
||
logging.StreamHandler()
|
||
]
|
||
)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
load_dotenv()
|
||
|
||
# Устанавливаем соответствие кириллицы латинице
|
||
TRANS_TABLE = str.maketrans({
|
||
"у": "u", "с": "s", "т": "t", "а": "a", "н": "n", "о": "o", "в": "v", "л": "l",
|
||
"е": "e", "ч": "ch", "а": "a", "с": "s", "т": "t", "ь": "", "п": "p", "ч": "ch",
|
||
"-": "_", ".": "_", "'": "", "`": "", '"': "", "h": "h", "h": "h" # Оставляем 'h' как есть
|
||
})
|
||
|
||
def sanitize_metric_name(name):
|
||
# Удаляем все недопустимые символы
|
||
name = unidecode(name) # Транслитерация сначала
|
||
name = name.lower() # Приводим к нижнему регистру
|
||
name = name.translate(TRANS_TABLE) # Применяем таблицу замен
|
||
|
||
# Дополнительная очистка от недопустимых символов
|
||
valid_chars = []
|
||
for c in name:
|
||
if c.isalpha() or c.isdigit() or c == '_':
|
||
valid_chars.append(c)
|
||
elif c in ['-', '.', ' ']:
|
||
valid_chars.append('_')
|
||
|
||
name = ''.join(valid_chars)
|
||
|
||
# Удаляем повторяющиеся подчеркивания
|
||
name = '_'.join(filter(None, name.split('_')))
|
||
|
||
# Добавляем префикс, если имя начинается с цифры
|
||
if name and name[0].isdigit():
|
||
name = f"metric_{name}"
|
||
|
||
# Проверяем, что имя не пустое
|
||
if not name:
|
||
name = 'unnamed_metric'
|
||
|
||
return name
|
||
|
||
def get_token():
|
||
login = os.getenv("LOGIN")
|
||
password = os.getenv("PASSWORD")
|
||
|
||
if not login or not password:
|
||
logger.error("Логин или пароль не заданы в .env")
|
||
raise ValueError("Логин или пароль не заданы в .env")
|
||
|
||
data = {'login': login, 'password': password}
|
||
headers = {
|
||
"Content-Type": "application/json",
|
||
"Accept": "application/json"
|
||
}
|
||
|
||
try:
|
||
req = requests.post("https://api.owencloud.ru/v1/auth/open/", json=data, headers=headers)
|
||
req.raise_for_status()
|
||
return "Bearer " + req.json()["token"]
|
||
except requests.exceptions.RequestException as e:
|
||
logger.error(f"Ошибка авторизации: {e}")
|
||
return None
|
||
|
||
def load_json_data():
|
||
token = get_token()
|
||
if not token:
|
||
logger.error("Не удалось получить токен. Завершаем работу.")
|
||
return []
|
||
|
||
device_id = "459205"
|
||
headers = {'Authorization': token}
|
||
data = json.dumps({'filter': ''})
|
||
|
||
try:
|
||
req = requests.post(f"https://api.owencloud.ru/v1/device/{device_id}", data=data, headers=headers)
|
||
req.raise_for_status()
|
||
json_response = req.json()
|
||
return json_response.get("parameters", [])
|
||
except requests.exceptions.RequestException as e:
|
||
logger.error(f"Ошибка запроса устройства: {e}")
|
||
return []
|
||
|
||
metrics = {}
|
||
|
||
def main():
|
||
logger.info("Запуск сервера Prometheus на порту 8000")
|
||
start_http_server(8000)
|
||
logger.info("Сервер запущен")
|
||
|
||
while True:
|
||
parameters = load_json_data()
|
||
|
||
if parameters:
|
||
for param in parameters:
|
||
try:
|
||
metric_name = sanitize_metric_name(param["name"])
|
||
value = float(param["value"])
|
||
|
||
if metric_name not in metrics:
|
||
metrics[metric_name] = Gauge(metric_name, "Описание метрики")
|
||
logger.info(f"Создана новая метрика: {metric_name}")
|
||
|
||
metrics[metric_name].set(value)
|
||
logger.debug(f"Метрика {metric_name} обновлена: {value}")
|
||
|
||
except Exception as e:
|
||
logger.error(f"Ошибка обработки параметра {param}: {e}")
|
||
|
||
time.sleep(60)
|
||
|
||
if __name__ == "__main__":
|
||
main()
|