This commit is contained in:
q 2025-04-23 21:50:26 +03:00
parent a38d6f00ea
commit 199e0c4663
5 changed files with 184 additions and 0 deletions

13
Dockerfile Normal file
View file

@ -0,0 +1,13 @@
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "main.py"]

31
docker-compose.yaml Normal file
View file

@ -0,0 +1,31 @@
#vrsion: '3.8'
services:
owen-exporter:
build: .
container_name: owen-exporter
restart: unless-stopped
environment:
- LOGIN=l_salnikov@internet.ru
- PASSWORD=}v]CT]Q"_g7>4H%
ports:
- "8000:8000"
networks:
- monitoring-net
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus:/etc/prometheus
networks:
- monitoring-net
depends_on:
- owen-exporter
networks:
monitoring-net:
driver: bridge

128
main.py Executable file
View file

@ -0,0 +1,128 @@
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()

View file

@ -0,0 +1,8 @@
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'owen-exporter'
static_configs:
- targets: ['owen-exporter:8000']

4
requirements.txt Normal file
View file

@ -0,0 +1,4 @@
prometheus_client
requests
unidecode
python-dotenv