首页 > 解决方案 > 使用多个目标配置导出器(Python prometheus_client)

问题描述

我正在创建我的第一个 prometheus 导出器,并且在 prometheus 配置中使用多个目标时遇到问题。

我创建了这个导出器来从 API RESP 服务 (json_exporter.py) 获取指标:

from prometheus_client import start_http_server
from prometheus_client.core import GaugeMetricFamily, REGISTRY
import json
import requests
import sys
import time

class JsonCollector(object):
  def __init__(self, endpoint):
    self._endpoint = endpoint

  def collect(self):
    # Fetch the JSON
    print(self._endpoint)
    response = json.loads(requests.get(self._endpoint).content.decode('UTF-8'))
    print(response)

    metric = GaugeMetricFamily(
        'my_metric_devices_status',
        'blah blah',
        labels=["device"])

    for p in response['devices']:
      host = p['host']
      status= p['status']
      metric.add_metric([host], float(status))

    yield metric


if __name__ == '__main__':
  # Usage: json_exporter.py port endpoint
  start_http_server(int(sys.argv[1]))
  REGISTRY.register(JsonCollector(sys.argv[2]))

  while True: time.sleep(1)

然后,我运行导出器:

python json_exporter.py 1234 http://my-rest-server:8000/api

我在普罗米修斯有这个配置:

  ...

  - job_name: json
    scrape_interval: 30s
    scrape_timeout: 30s
    metrics_path: /probe
    static_configs:
      - targets:
        - my_target1
        - my_target2
        - my_target3

    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: localhost:1234 ## Location of the json exporter's real <hostname>:<port>

问题出在我的 REST 服务器中,我收到了三个对 http://my-rest-server:8000/api 的相同查询(prometheus.yml 中每个目标的一个 http 查询),但我无法将目标参数传递给 de REST服务,因为我不知道如何在 json_exporter.py 中获取目标参数

有什么帮助吗?

标签: pythonprometheus

解决方案


After a lot of research, I change my original code to this one and it works fine:

json_exporter.py

from prometheus_client import Gauge, start_http_server, Counter, MetricsHandler
import json
import requests
import sys
from http.server import HTTPServer
import urllib.parse

REQUESTS = Counter('hello_worlds_total',
        'Hello Worlds requested.')
METRIC1 = Gauge('metric1', 'Testing1', ["label1"])
METRIC2 = Gauge('metric2', 'Testing2', ["label2"])

ENDPOINT = ""
PORT = ""

class MyRequestHandler(MetricsHandler):
    def do_GET(self):
      REQUESTS.inc()

      parsed_path = urllib.parse.urlsplit(self.path)
      query = urllib.parse.parse_qs(parsed_path.query)
      print(self.path, query)

      if("target" in query):
        host = query['target'][0]
        j = json.loads(requests.get(urllib.parse.urljoin(ENDPOINT, host)).content.decode('UTF-8'))
        METRIC1.clear()
        METRIC1.clear()
        METRIC1.labels(label1=j['label1']).set(j['value1'])
        METRIC2.labels(label2=j['label2']).set(j['value2'])
        return super(MyRequestHandler, self).do_GET()
      else:
        self.send_response(404)
        self.end_headers()
        self.wfile.write(b"No target defined\n")

if __name__ == '__main__':
  # Usage: json_exporter.py port endpoint
  PORT = sys.argv[1]
  ENDPOINT = sys.argv[2]
  
  server_address = ('', int(PORT))
  HTTPServer(server_address, MyRequestHandler).serve_forever()

To run this code:

python json_exporter.py 8001 http://myjson-server:8000/

推荐阅读