quynhvuongg / Prometheus

0 stars 1 forks source link

Writing exporter #13

Open quynhvuongg opened 4 years ago

quynhvuongg commented 4 years ago

@vtdat Em gửi tạm phần doc Writing exporter. Còn phần code em vẫn đang trong quá trình tìm hiểu chưa ra được kết quả, em sẽ hoàn thiện thêm phần doc và code sau khi tìm hiểu xong Config.

vtdat commented 4 years ago

ok

quynhvuongg commented 4 years ago

Writing Exporter with Python

Python cung cấp thư viện prometheus_client để sử dụng viết Exporter cho Prometheus:

pip install prometheus_client

Instrumentation

Counter

Ví dụ: Add metric trả về số lần Hello World được yêu cầu

import http.server
from prometheus_client import start_http_server
from prometheus_client import Counter

REQUESTS = Counter('hello_worlds_total','Hello Worlds requested')

class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        REQUESTS.inc()
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello World!")

if __name__ == "__main__":
    start_http_server(8000)
    server = http.server.HTTPServer(('localhost', 8001),MyHandler)
    server.serve_forever()

Gồm 3 phần:

  @c.count_exceptions()
  def f():
    pass

  with c.count_exceptions():
    pass

# Count only one type of exception
  with c.count_exceptions(ValueError):
    pass

Gauge

Ví dụ: Add metrics trả về số yêu cầu đang xử lý và xác định khi nào yêu cầu cuối cùng được xử lý.

import http.server
import time
from prometheus_client import start_http_server
from prometheus_client import Gauge

INPROGRESS = Gauge('hello_worlds_inprogress',
        'Number of Hello Worlds in progress.')
LAST = Gauge('hello_world_last_time_seconds',
        'The last time a Hello World was served.')

class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        INPROGRESS.inc()
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello World")
        LAST.set(time.time())
        INPROGRESS.dec()

if __name__ == "__main__":
    start_http_server(8000)
    server = http.server.HTTPServer(('localhost', 8001), MyHandler)
    server.serve_forever()

Methods and utilities:

g.set_to_current_time()   # Set to current unixtime

# Increment when entered, decrement when exited.
@g.track_inprogress()
def f():
  pass

with g.track_inprogress():
  pass
d = Gauge('data_objects', 'Number of objects')
my_dict = {}
d.set_function(lambda: len(my_dict))

Summary

Ví dụ: Theo dõi trình xử lý Hello World mất bao lâu để xử lý.

import http.server
import time
from prometheus_client import start_http_server
from prometheus_client import Summary

LATENCY = Summary('hello_world_latency_seconds',
        'Time for a request Hello World.')

class MyHandler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        start = time.time()
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello World")
        LATENCY.observe(time.time() - start)

if __name__ == "__main__":
    start_http_server(8000)
    server = http.server.HTTPServer(('localhost', 8001), MyHandler)
    server.serve_forever()

Methods and utilities:

@s.time()
def f():
  pass

with s.time():
  pass

Histogram

Tương tự như Sumary, chú ý tham số bucket:

LATENCY = Histogram('hello_world_latency_seconds',
'Time for a request Hello World.',
  buckets=[0.0001, 0.0002, 0.0005, 0.001, 0.01, 0.1])

  buckets=[0.1 * x for x in range(1, 10)] # Linear
  buckets=[0.1 * 2**x for x in range(1, 10)] # Exponential

Labels

Tất cả metrics đều có thể có nhãn, cho phép nhóm time series liên quan.

from prometheus_client import Counter
c = Counter('my_requests_total', 'HTTP Failures', ['method', 'endpoint'])
c.labels(method='get', endpoint='/').inc()
c.labels(method='post', endpoint='/submit').inc()

Info

Tracks thông tin về các target.

from prometheus_client import Info
i = Info('my_build_version', 'Description of info')
i.info({'version': '1.2.3', 'buildhost': 'foo@bar'})

Enum

Tracks thông tin về trạng thái hiện tại.

from prometheus_client import Enum
e = Enum('my_task_state', 'Description of enum',
        states=['starting', 'running', 'stopped'])
e.state('running')

Exposition

HTTP

from prometheus_client import start_http_server

start_http_server(8000)

WSGI

from prometheus_client import make_wsgi_app
from wsgiref.simple_server import make_server

metrics_app = make_wsgi_app()

def my_app(environ, start_fn):
    if environ['PATH_INFO'] == '/metrics':
        return metrics_app(environ, start_fn)
    start_fn('200 OK', [])
    return [b'Hello World']

if __name__ == '__main__':
    httpd = make_server('', 8000, my_app)
    httpd.serve_forever()

Flask

Để sử dụng Prometheus với Flask, chúng ta cần cung cấp metrics thông qua ứng dụng WSGI của Prometheus.

from flask import Flask
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from prometheus_client import make_wsgi_app

# Create my app
app = Flask(__name__)

# Add prometheus wsgi middleware to route /metrics requests
app_dispatch = DispatcherMiddleware(app, {
    '/metrics': make_wsgi_app()
})

Custom Collector

Thay vì sử dụng Direct Instrumentation mà bạn muốn cung cấp từ một số nguồn khác khi đó hãy sử dụng Custom Collector, đó là bất kỳ Collector nào không phải là một trong bốn loại dữ liệu chuẩn trên.

import json
import re
import time
from urllib.request import urlopen

from prometheus_client.core import GaugeMetricFamily, CounterMetricFamily
from prometheus_client.core import SummaryMetricFamily, REGISTRY
from prometheus_client import start_http_server

def sanitise_name(s):
    return re.sub(r"[^a-zA-Z0-9:_]", "_", s)

class ConsulCollector(object):
  def collect(self):
    out = urlopen("http://localhost:8500/v1/agent/metrics").read()
    metrics = json.loads(out.decode("utf-8"))

    for g in metrics["Gauges"]:
      yield GaugeMetricFamily(sanitise_name(g["Name"]),
          "Consul metric " + g["Name"], g["Value"])

    for c in metrics["Counters"]:
      yield CounterMetricFamily(sanitise_name(c["Name"]) + "_total",
          "Consul metric " + c["Name"], c["Count"])

    for s in metrics["Samples"]:
      yield SummaryMetricFamily(sanitise_name(s["Name"]) + "_seconds",
          "Consul metric " + s["Name"],
          count_value=c["Count"], sum_value=s["Sum"] / 1000)

if __name__ == '__main__':
  REGISTRY.register(ConsulCollector())
  start_http_server(8000)
  while True:
    time.sleep(1)
vtdat commented 4 years ago

cho vào trong file md luôn đi chứ

quynhvuongg commented 4 years ago

cho vào trong file md luôn đi chứ

Em muốn sau này code thì thay ví dụ khác nên chưa muốn cho vào ạ.

vtdat commented 4 years ago

cho vào trong file md luôn đi chứ

Em muốn sau này code thì thay ví dụ khác nên chưa muốn cho vào ạ.

ok