1
0
Эх сурвалжийг харах

began with prometheus metric for page visits

Rodja Trappe 2 жил өмнө
parent
commit
cb7467fff7
5 өөрчлөгдсөн 51 нэмэгдсэн , 4 устгасан
  1. 2 1
      fly.dockerfile
  2. 5 1
      fly.toml
  3. 4 1
      main.py
  4. 1 1
      nicegui/client.py
  5. 39 0
      prometheus.py

+ 2 - 1
fly.dockerfile

@@ -6,8 +6,9 @@ WORKDIR /app
 
 ADD . .
 RUN pip install -e .
-RUN pip install itsdangerous
+RUN pip install itsdangerous prometheus_client
 
 EXPOSE 8080
+EXPOSE 9062
 
 CMD python3 main.py

+ 5 - 1
fly.toml

@@ -57,4 +57,8 @@ strategy = "canary"
 
   [[statics]]
     guest_path = "/app/nicegui/static"
-    url_prefix = "/_nicegui/static"
+    url_prefix = "/_nicegui/static"
+
+  [metrics]
+  port = 9062
+  path = "/metrics" # default for most prometheus clients

+ 4 - 1
main.py

@@ -11,13 +11,16 @@ from pathlib import Path
 
 from pygments.formatters import HtmlFormatter
 
-from nicegui import Client
+import prometheus
+from nicegui import Client, app
 from nicegui import globals as nicegui_globals
 from nicegui import ui
 from website import demo_card, reference, svg
 from website.example import bash_window, browser_window, python_window
 from website.style import example_link, features, heading, link_target, section_heading, subtitle, title
 
+prometheus.start_monitor(app)
+
 ui.add_static_files('/favicon', Path(__file__).parent / 'website' / 'favicon')
 ui.add_static_files('/fonts', Path(__file__).parent / 'website' / 'fonts')
 

+ 1 - 1
nicegui/client.py

@@ -79,7 +79,7 @@ class Client:
             'dark': str(self.page.resolve_dark()),
             'prefix': prefix,
             'socket_io_js_extra_headers': globals.socket_io_js_extra_headers,
-        }, status_code, {'Cache-Control': 'no-store'})
+        }, status_code, {'Cache-Control': 'no-store', 'X-NiceGUI-Content': 'page'})
 
     async def handshake(self, timeout: float = 3.0, check_interval: float = 0.1) -> None:
         self.is_waiting_for_handshake = True

+ 39 - 0
prometheus.py

@@ -0,0 +1,39 @@
+import inspect
+import logging
+import uuid
+
+from fastapi import FastAPI, Request
+from starlette.middleware.base import BaseHTTPMiddleware
+from starlette.middleware.sessions import SessionMiddleware
+
+EXCLUDED_USER_AGENTS = ('bot', 'spider', 'crawler', 'monitor', 'curl',
+                        'wget', 'python-requests', 'kuma', 'health check')
+
+
+def start_monitor(app: FastAPI):
+    try:
+        import prometheus_client
+        visits = prometheus_client.Counter('nicegui_page_visits', 'Number of real page visits', [
+                                           'path', 'session', 'origin'])
+
+        class PrometheusMiddleware(BaseHTTPMiddleware):
+            async def dispatch(self, request: Request, call_next):
+                if 'id' not in request.session:
+                    request.session['id'] = str(uuid.uuid4())
+                response = await call_next(request)
+                if response.headers.get('x-nicegui-content') == 'page':
+                    agent = request.headers.get('user-agent', 'unknown').lower()
+                    # ignore monitoring, web crawlers and the like
+                    if not any(s in agent for s in EXCLUDED_USER_AGENTS):
+                        origin_url = request.headers.get('referer', 'unknown')
+                        print(request.get('path'), agent, request.session['id'], origin_url, flush=True)
+                        visits.labels(request.get('path'), request.session['id'], origin_url).inc()
+                return response
+
+        if inspect.stack()[-2].filename.endswith('spawn.py'):
+            prometheus_client.start_http_server(9062)
+
+        app.add_middleware(PrometheusMiddleware)
+        app.add_middleware(SessionMiddleware, secret_key='NiceGUI is awesome!')
+    except ModuleNotFoundError:
+        logging.info('Prometheus not installed, skipping monitoring')