Initial commit
This commit is contained in:
commit
317978c24a
6
.flake8
Normal file
6
.flake8
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[flake8]
|
||||||
|
inline-quotes = "
|
||||||
|
multiline-quotes = """
|
||||||
|
indent-size = 4
|
||||||
|
max-line-length = 160
|
||||||
|
ignore = Q003 E128 E704
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.env
|
9
.gitlint
Normal file
9
.gitlint
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[general]
|
||||||
|
ignore=body-is-missing,T3
|
||||||
|
ignore-stdin=true
|
||||||
|
|
||||||
|
[title-match-regex]
|
||||||
|
regex=[A-Z]
|
||||||
|
|
||||||
|
[author-valid-email]
|
||||||
|
regex=[^@]+@k-space.ee
|
16
.pre-commit-config.yaml
Normal file
16
.pre-commit-config.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 3.9.2
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
additional_dependencies: [flake8-typing-imports==1.10.0,flake8-quotes==3.2.0]
|
||||||
|
|
||||||
|
- repo: https://github.com/jorisroovers/gitlint
|
||||||
|
rev: v0.15.1
|
||||||
|
hooks:
|
||||||
|
- id: gitlint
|
||||||
|
|
||||||
|
- repo: https://github.com/Lucas-C/pre-commit-hooks-nodejs
|
||||||
|
rev: v1.1.1
|
||||||
|
hooks:
|
||||||
|
- id: dockerfile_lint
|
4
Dockerfile
Normal file
4
Dockerfile
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
FROM python:3
|
||||||
|
RUN pip3 install motor sanic
|
||||||
|
ADD wildduck_exporter.py /wildduck_exporter.py
|
||||||
|
ENTRYPOINT /wildduck_exporter.py
|
8
docker-compose.yml
Normal file
8
docker-compose.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
version: '3.7'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: kspaceee/wildduck-exporter:latest
|
||||||
|
network_mode: host
|
||||||
|
env_file: .env
|
||||||
|
build:
|
||||||
|
context: .
|
60
wildduck_exporter.py
Executable file
60
wildduck_exporter.py
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
from motor.motor_asyncio import AsyncIOMotorClient
|
||||||
|
from sanic import Sanic, response, exceptions
|
||||||
|
|
||||||
|
MONGO_URI = os.getenv("MONGO_URI")
|
||||||
|
if not MONGO_URI:
|
||||||
|
raise ValueError("No MONGO_URI specified")
|
||||||
|
|
||||||
|
PROMETHEUS_BEARER_TOKEN = os.getenv("PROMETHEUS_BEARER_TOKEN")
|
||||||
|
if not PROMETHEUS_BEARER_TOKEN:
|
||||||
|
raise ValueError("No PROMETHEUS_BEARER_TOKEN specified")
|
||||||
|
|
||||||
|
app = Sanic("exporter")
|
||||||
|
|
||||||
|
|
||||||
|
@app.listener("before_server_start")
|
||||||
|
async def setup_db(app, loop):
|
||||||
|
app.ctx.db = AsyncIOMotorClient(MONGO_URI).get_default_database()
|
||||||
|
|
||||||
|
|
||||||
|
async def wrap(i, prefix="wildduck_"):
|
||||||
|
metrics_seen = set()
|
||||||
|
async for name, tp, value, labels in i:
|
||||||
|
if name not in metrics_seen:
|
||||||
|
yield "# TYPE %s %s" % (name, tp)
|
||||||
|
metrics_seen.add(name)
|
||||||
|
yield "%s%s %d" % (
|
||||||
|
prefix + name,
|
||||||
|
("{%s}" % ",".join(["%s=\"%s\"" % j for j in labels.items()]) if labels else ""),
|
||||||
|
value)
|
||||||
|
|
||||||
|
|
||||||
|
async def fetch():
|
||||||
|
async for u in app.ctx.db.users.find():
|
||||||
|
labels = {
|
||||||
|
"username": u["username"],
|
||||||
|
"email": u["address"],
|
||||||
|
}
|
||||||
|
if u["lastLogin"]["time"]:
|
||||||
|
yield "last_login", "gauge", u["lastLogin"]["time"].timestamp(), labels
|
||||||
|
if u["storageUsed"]:
|
||||||
|
yield "storage_used", "gauge", u["storageUsed"], labels
|
||||||
|
if u["targets"]:
|
||||||
|
yield "forwarding_addresses", "gauge", len(u["targets"]), labels
|
||||||
|
yield "account_enabled", "gauge", not u["disabled"], labels
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/metrics")
|
||||||
|
async def view_export(request):
|
||||||
|
if request.token != PROMETHEUS_BEARER_TOKEN:
|
||||||
|
raise exceptions.Forbidden("Invalid bearer token")
|
||||||
|
|
||||||
|
async def streaming_fn(response):
|
||||||
|
async for line in wrap(fetch()):
|
||||||
|
await response.write(line + "\n")
|
||||||
|
|
||||||
|
return response.stream(streaming_fn, content_type="text/plain")
|
||||||
|
|
||||||
|
app.run(port=3001)
|
Loading…
Reference in New Issue
Block a user