Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 75 additions & 1 deletion app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,29 @@
import shutil
from datetime import datetime
from threading import Lock
from flask import Flask, jsonify, render_template, send_from_directory, request, redirect
from flask import Flask, jsonify, render_template, send_from_directory, request, redirect, g, Response
import psutil

# Gunicorn -w N: set PROMETHEUS_MULTIPROC_DIR before workers import this module (e.g. in gunicorn.conf.py).
if os.environ.get("PROMETHEUS_MULTIPROC_DIR", "").strip():
_prom_mpdir = os.environ["PROMETHEUS_MULTIPROC_DIR"].strip()
os.makedirs(_prom_mpdir, exist_ok=True)

try:
from prometheus_client import (
CONTENT_TYPE_LATEST,
CollectorRegistry,
Counter,
Histogram,
generate_latest,
multiprocess,
)

_PROMETHEUS_AVAILABLE = True
except ImportError:
_PROMETHEUS_AVAILABLE = False
CONTENT_TYPE_LATEST = "text/plain; version=0.0.4; charset=utf-8"

# Try to import OpenAI (optional)
try:
import openai
Expand All @@ -27,6 +47,60 @@
OPENAI_AVAILABLE = False

app = Flask(__name__)

if _PROMETHEUS_AVAILABLE:
REQUEST_COUNT = Counter(
"http_requests_total",
"Total HTTP requests",
["method", "endpoint", "status"],
)
REQUEST_LATENCY = Histogram(
"http_request_duration_seconds",
"HTTP request latency in seconds",
buckets=(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, float("inf")),
)

@app.before_request
def _prometheus_before_request():
g._prom_start = time.perf_counter()

@app.after_request
def _prometheus_after_request(response):
start = getattr(g, "_prom_start", None)
if start is not None:
REQUEST_LATENCY.observe(time.perf_counter() - start)
ep = request.endpoint
rule = request.url_rule.rule if request.url_rule else None
endpoint_label = ep or rule or "unmatched"
try:
REQUEST_COUNT.labels(
method=request.method,
endpoint=endpoint_label,
status=str(response.status_code),
).inc()
except Exception:
pass
return response

@app.route("/metrics")
def prometheus_metrics():
if os.environ.get("PROMETHEUS_MULTIPROC_DIR", "").strip():
registry = CollectorRegistry()
multiprocess.MultiProcessCollector(registry)
data = generate_latest(registry)
else:
data = generate_latest()
return Response(data, mimetype=CONTENT_TYPE_LATEST)

else:

@app.route("/metrics")
def prometheus_metrics_disabled():
return jsonify(
{"error": "prometheus_client not installed; pip install prometheus-client"}
), 503


TRACEROUTE_CACHE = {}
TRACEROUTE_CACHE_TTL_SECONDS = 60
NETWORK_STACK_PREV = {
Expand Down
2 changes: 1 addition & 1 deletion templates/linux-memory-subsystem.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ <h2>Linux kernel memory management</h2>

<script src="/static/js/safe-utils.js?v=2"></script>
<script src="/static/js/frontend-logger.js?v=2"></script>
<script src="/static/js/memory-belt.js?v=1"></script>
<script src="/static/js/memory-belt.js?v=2"></script>
<script>
(function startMemoryPage() {
if (typeof window.MemorySubsystemVisualization !== 'function') {
Expand Down
Loading