Skip to content

Commit

Permalink
Use gunicorn instead of the Werkzeug development server (#132)
Browse files Browse the repository at this point in the history
crabhi authored Apr 26, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent a27a4ab commit d88f0af
Showing 4 changed files with 35 additions and 4 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ RUN apk update && apk upgrade

RUN apk add --no-cache \
ca-certificates \
py3-gunicorn \
py3-paramiko \
py3-pip \
py3-prometheus-client \
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
"pyyaml",
"requests",
'Werkzeug',
'gunicorn',
],
classifiers=[
"Development Status :: 3 - Alpha",
11 changes: 10 additions & 1 deletion src/pve_exporter/cli.py
Original file line number Diff line number Diff line change
@@ -88,6 +88,8 @@ def main():
help='Port on which the exporter is listening (9221)')
parser.add_argument('address', nargs='?', default='',
help='Address to which the exporter will bind')
parser.add_argument('--server.keyfile', dest='server_keyfile', help='SSL key for server')
parser.add_argument('--server.certfile', dest='server_certfile', help='SSL certificate for server')

params = parser.parse_args()

@@ -107,7 +109,14 @@ def main():
with open(params.config) as handle:
config = config_from_yaml(yaml.safe_load(handle))

gunicorn_options = {
'bind': f'{params.address}:{params.port}',
'threads': 2,
'keyfile': params.server_keyfile,
'certfile': params.server_certfile,
}

if config.valid:
start_http_server(config, params.port, params.address, collectors)
start_http_server(config, gunicorn_options, collectors)
else:
parser.error(str(config))
26 changes: 23 additions & 3 deletions src/pve_exporter/http.py
Original file line number Diff line number Diff line change
@@ -5,9 +5,9 @@
import logging
import time

import gunicorn.app.base
from prometheus_client import CONTENT_TYPE_LATEST, Summary, Counter, generate_latest
from werkzeug.routing import Map, Rule
from werkzeug.serving import run_simple
from werkzeug.wrappers import Request, Response
from werkzeug.exceptions import InternalServerError
from .collector import collect_pve
@@ -112,7 +112,27 @@ def __call__(self, request):
return urls.dispatch(view_func, catch_http_exceptions=True)


def start_http_server(config, port, address, collectors):
class StandaloneGunicornApplication(gunicorn.app.base.BaseApplication):
"""
Copy-paste from https://docs.gunicorn.org/en/stable/custom.html
"""

def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()

def load_config(self):
config = {key: value for key, value in self.options.items()
if key in self.cfg.settings and value is not None}
for key, value in config.items():
self.cfg.set(key.lower(), value)

def load(self):
return self.application


def start_http_server(config, gunicorn_options, collectors):
"""
Start a HTTP API server for Proxmox VE prometheus collector.
"""
@@ -136,4 +156,4 @@ def start_http_server(config, port, address, collectors):
duration.labels(module)

app = PveExporterApplication(config, duration, errors, collectors)
run_simple(address, port, app, threaded=True)
StandaloneGunicornApplication(app, gunicorn_options).run()

0 comments on commit d88f0af

Please sign in to comment.