File size: 2,104 Bytes
7387da9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import logging
import os
import urllib.parse

from bottle import request
from dtos import V1RequestBase, V1ResponseBase
from metrics import start_metrics_http_server, REQUEST_COUNTER, REQUEST_DURATION

PROMETHEUS_ENABLED = os.environ.get('PROMETHEUS_ENABLED', 'false').lower() == 'true'
PROMETHEUS_PORT = int(os.environ.get('PROMETHEUS_PORT', 8192))


def setup():
    if PROMETHEUS_ENABLED:
        start_metrics_http_server(PROMETHEUS_PORT)


def prometheus_plugin(callback):
    """

    Bottle plugin to expose Prometheus metrics

    http://bottlepy.org/docs/dev/plugindev.html

    """
    def wrapper(*args, **kwargs):
        actual_response = callback(*args, **kwargs)

        if PROMETHEUS_ENABLED:
            try:
                export_metrics(actual_response)
            except Exception as e:
                logging.warning("Error exporting metrics: " + str(e))

        return actual_response

    def export_metrics(actual_response):
        res = V1ResponseBase(actual_response)

        if res.startTimestamp is None or res.endTimestamp is None:
            # skip management and healthcheck endpoints
            return

        domain = "unknown"
        if res.solution and res.solution.url:
            domain = parse_domain_url(res.solution.url)
        else:
            # timeout error
            req = V1RequestBase(request.json)
            if req.url:
                domain = parse_domain_url(req.url)

        run_time = (res.endTimestamp - res.startTimestamp) / 1000
        REQUEST_DURATION.labels(domain=domain).observe(run_time)

        result = "unknown"
        if res.message == "Challenge solved!":
            result = "solved"
        elif res.message == "Challenge not detected!":
            result = "not_detected"
        elif res.message.startswith("Error"):
            result = "error"
        REQUEST_COUNTER.labels(domain=domain, result=result).inc()

    def parse_domain_url(url):
        parsed_url = urllib.parse.urlparse(url)
        return parsed_url.hostname

    return wrapper