File: trafficserver_exporter.py

package info (click to toggle)
prometheus-trafficserver-exporter 0.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 348 kB
  • sloc: python: 457; makefile: 7
file content (133 lines) | stat: -rw-r--r-- 3,463 bytes parent folder | download | duplicates (2)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""Prometheus exporter for Apache Traffic Server's stats_over_http plugin."""

import argparse
import logging
import sys
from os import path

from prometheus_client import REGISTRY, ProcessCollector

from .collector import StatsPluginCollector
from .http import start_http_server

PKG_METRICS_FILE = path.join(
    path.dirname(sys.modules["trafficserver_exporter"].__file__), "metrics.yaml"
)

ARGS = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    description="Traffic Server exporter for Prometheus",
)
ARGS.add_argument(
    "--endpoint",
    dest="endpoint",
    default="http://127.0.0.1/_stats",
    help="Traffic Server's stats_over_http plugin URL",
)
ARGS.add_argument(
    "--metrics-file",
    dest="metrics_file",
    default=PKG_METRICS_FILE,
    help="YAML file containing the metrics definition",
)
ARGS.add_argument(
    "--addr", dest="addr", default="", help="Address to bind and listen on"
)
ARGS.add_argument(
    "--port", dest="port", default=9122, type=int, help="Port to bind and listen on"
)
ARGS.add_argument(
    "--pidfile",
    dest="pidfile",
    default="/var/run/trafficserver/server.lock",
    help="Path to trafficserver PID file; used with --procstats",
)
ARGS.add_argument(
    "--procstats",
    dest="procstats",
    action="store_true",
    help="Enable process metric collection",
)
ARGS.add_argument(
    "--no-procstats",
    dest="procstats",
    action="store_false",
    help="Disable process metric collection",
)
ARGS.set_defaults(procstats=True)
ARGS.add_argument(
    "--no-ssl-verification",
    dest="sslverification",
    action="store_false",
    help="Disable SSL certificate verification on metric collection",
)
ARGS.set_defaults(sslverification=True)
ARGS.add_argument(
    "--max-retries",
    dest="max_retries",
    type=int,
    default=0,
    help="Maximum retries for DNS lookups or connnection timeouts/failures",
)
ARGS.add_argument(
    "-v",
    "--verbose",
    action="count",
    dest="level",
    default=0,
    help="Verbose logging (repeat for more verbosity)",
)

LOG = logging.getLogger(__name__)


def get_ts_pid(pidfile):
    """Read a pidfile, return a PID."""
    try:
        with open(pidfile) as f:
            pid = f.readline()
    except EnvironmentError:
        LOG.warning("Unable to read pidfile; process metrics will fail!")
        pid = None
    return pid


def main():
    """Main program.

    Parse arguments, start webserver to serve /metrics.
    """
    args = ARGS.parse_args()

    if args.level >= 2:
        logging.basicConfig(level=logging.DEBUG)
    elif args.level == 1:
        logging.basicConfig(level=logging.INFO)
    elif args.level == 0:
        logging.basicConfig(level=logging.WARNING)

    LOG.debug("Starting HTTP server")
    httpd_thread = start_http_server(args.port, addr=args.addr)

    LOG.debug("Registering StatsPluginCollector")
    REGISTRY.register(
        StatsPluginCollector(
            args.endpoint,
            args.metrics_file,
            max_retries=args.max_retries,
            ssl_verify=args.sslverification,
        )
    )

    if args.procstats:
        LOG.debug("Registering ProcessCollector")
        REGISTRY.register(
            ProcessCollector(
                pid=lambda: get_ts_pid(args.pidfile), namespace="trafficserver"
            )
        )

    LOG.info("Listening on :{port}".format(port=args.port))

    # Wait for the webserver
    httpd_thread.join()