Compare commits
1 Commits
06d19c8c8d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e9f5586f48 |
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FROM python:3.12-slim-trixie
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||||
|
|
||||||
|
# Copy the project into the image
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
# Disable development dependencies
|
||||||
|
ENV UV_NO_DEV=1
|
||||||
|
|
||||||
|
# Sync the project into a new environment, asserting the lockfile is up to date
|
||||||
|
WORKDIR /app
|
||||||
|
RUN uv sync --locked
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import shlex
|
||||||
|
|
||||||
|
|
||||||
|
def tokenize(text):
|
||||||
|
lexer = shlex.shlex(text, posix=True)
|
||||||
|
lexer.whitespace_split = True
|
||||||
|
lexer.commenters = "#"
|
||||||
|
lexer.wordchars += ".:/-@(),"
|
||||||
|
return list(lexer)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_sites_imports(text):
|
||||||
|
tokens = tokenize(text)
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
current_site = None
|
||||||
|
depth = 0
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < len(tokens):
|
||||||
|
tok = tokens[i]
|
||||||
|
|
||||||
|
# detect site start
|
||||||
|
if i + 1 < len(tokens) and tokens[i + 1] == "{":
|
||||||
|
if depth == 0:
|
||||||
|
sites = [s.strip() for s in tok.split(",")]
|
||||||
|
|
||||||
|
for s in sites:
|
||||||
|
result.setdefault(s, [])
|
||||||
|
|
||||||
|
current_site = sites
|
||||||
|
|
||||||
|
depth += 1
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
|
||||||
|
if tok == "{":
|
||||||
|
depth += 1
|
||||||
|
|
||||||
|
elif tok == "}":
|
||||||
|
depth -= 1
|
||||||
|
if depth == 0:
|
||||||
|
current_site = None
|
||||||
|
|
||||||
|
elif tok == "import" and i + 1 < len(tokens) and current_site:
|
||||||
|
name = tokens[i + 1]
|
||||||
|
for site in current_site:
|
||||||
|
result[site].append(name)
|
||||||
|
i += 2
|
||||||
|
continue
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def filter_globals_out(data):
|
||||||
|
import re
|
||||||
|
|
||||||
|
ret = dict()
|
||||||
|
for key, values in data.items():
|
||||||
|
if re.match(r"\(\w+\)", key): # exclude import definitions e.g (auth)
|
||||||
|
continue
|
||||||
|
ret[key] = values
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
data = parse_sites_imports(data)
|
||||||
|
data = filter_globals_out(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
with open("Caddyfile") as f:
|
||||||
|
data = parse(f.read())
|
||||||
|
print(data)
|
||||||
@@ -1,6 +1,88 @@
|
|||||||
def main():
|
import os
|
||||||
print("Hello from authelia-metrics!")
|
import time
|
||||||
|
from prometheus_client import start_http_server, Gauge, REGISTRY
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# 1. Define Metrics with Labels
|
||||||
|
# Use labels for domain and feature to avoid creating 100s of unique metric names
|
||||||
|
DOMAIN_FEATURE = Gauge(
|
||||||
|
"caddy_domain_imports",
|
||||||
|
"Binary status of domain features (1=enabled, 0=disabled)",
|
||||||
|
["domain", "feature"],
|
||||||
|
)
|
||||||
|
|
||||||
|
GLOBAL_STATS = Gauge(
|
||||||
|
"caddy_global_stats", "Aggregated counts of features across all domains", ["type"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
CADDY_PATH = os.environ["CADDY_PATH"]
|
||||||
|
|
||||||
|
|
||||||
|
def load_caddyfile():
|
||||||
|
with open(CADDY_PATH, "r") as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
from libs.parse_caddyfile import parse as caddy_parse
|
||||||
|
|
||||||
|
return caddy_parse(data)
|
||||||
|
|
||||||
|
|
||||||
|
def mathing(data: dict):
|
||||||
|
total_domains = len(data.items())
|
||||||
|
# info = dict({"auth": 0, "wan": 0, "noauth": 0, "nowan": 0, "none": 0})
|
||||||
|
info = dict({"no_auth": 0, "no_wan": 0})
|
||||||
|
for domain, imports in data.items():
|
||||||
|
if len(imports) == 0:
|
||||||
|
if "none" not in info:
|
||||||
|
info["none"] = 1
|
||||||
|
info["none"] += 1
|
||||||
|
continue
|
||||||
|
for imp in imports:
|
||||||
|
if imp not in info:
|
||||||
|
info[imp] = 1
|
||||||
|
info[imp] += 1
|
||||||
|
if "auth" not in imports:
|
||||||
|
info["no_auth"] += 1
|
||||||
|
if "wan" not in imports:
|
||||||
|
info["no_wan"] += 1
|
||||||
|
info["total_domains"] = total_domains
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
def update_metrics():
|
||||||
|
# Your existing parsing logic
|
||||||
|
try:
|
||||||
|
raw_data = load_caddyfile()
|
||||||
|
hosts = parse(raw_data)
|
||||||
|
info = mathing(hosts)
|
||||||
|
|
||||||
|
# --- Update Global Metrics ---
|
||||||
|
for key, value in info.items():
|
||||||
|
GLOBAL_STATS.labels(type=key).set(value)
|
||||||
|
|
||||||
|
# --- Update Per-Domain Metrics ---
|
||||||
|
tracked_features = ["auth", "wan"]
|
||||||
|
|
||||||
|
for domain, imports in hosts.items():
|
||||||
|
for feature in tracked_features:
|
||||||
|
is_enabled = 1 if feature in imports else 0
|
||||||
|
DOMAIN_FEATURE.labels(domain=domain, feature=feature).set(is_enabled)
|
||||||
|
|
||||||
|
print(f"Metrics updated at {time.ctime()}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error updating metrics: {e}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
start_http_server(port=8000, addr="0.0.0.0")
|
||||||
|
print("Prometheus server started on port 8000")
|
||||||
|
|
||||||
|
while True:
|
||||||
|
update_metrics()
|
||||||
|
time.sleep(60)
|
||||||
|
|||||||
+4
-1
@@ -4,4 +4,7 @@ version = "0.1.0"
|
|||||||
description = "Add your description here"
|
description = "Add your description here"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
dependencies = []
|
dependencies = [
|
||||||
|
"prometheus-client>=0.24.1",
|
||||||
|
"python-dotenv>=1.2.2",
|
||||||
|
]
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "authelia-metrics"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "prometheus-client" },
|
||||||
|
{ name = "python-dotenv" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "prometheus-client", specifier = ">=0.24.1" },
|
||||||
|
{ name = "python-dotenv", specifier = ">=1.2.2" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "prometheus-client"
|
||||||
|
version = "0.24.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dotenv"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user