From e5fbc14a34f4fd4bbbb0004ee9fe7c950c287294 Mon Sep 17 00:00:00 2001 From: elpatron Date: Sat, 2 Aug 2025 14:25:07 +0200 Subject: [PATCH] =?UTF-8?q?Dashboard=20erweitert:=20Toggle=20zwischen=20Wo?= =?UTF-8?q?chen-=20und=2024-Stunden-Verlauf=20f=C3=BCr=20alle=20Charts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 45 +++++- templates/stats_dashboard.html | 265 ++++++++++++++++++++++++++------- 2 files changed, 250 insertions(+), 60 deletions(-) diff --git a/app.py b/app.py index 83a68ba..105fa98 100644 --- a/app.py +++ b/app.py @@ -237,26 +237,63 @@ def index(): def parse_log_stats(log_path): pageviews = 0 func_counts = {} + func_counts_hourly = {} impressions_per_day = {} + impressions_per_hour = {} api_counts = {} + api_counts_hourly = {} if os.path.exists(log_path): with open(log_path, encoding='utf-8') as f: for line in f: if 'PAGEVIEW' in line: pageviews += 1 try: - date = line[:10] + # Parse timestamp (format: YYYY-MM-DDTHH:MM:SS) + timestamp = line[:19] # First 19 chars for YYYY-MM-DDTHH:MM:SS + date = timestamp[:10] # YYYY-MM-DD + hour = timestamp[11:13] # HH + if len(date) == 10 and date[4] == '-' and date[7] == '-': impressions_per_day[date] = impressions_per_day.get(date, 0) + 1 + + if len(hour) == 2 and hour.isdigit(): + hour_key = f"{date} {hour}:00" + impressions_per_hour[hour_key] = impressions_per_hour.get(hour_key, 0) + 1 except Exception: pass elif 'FUNC:' in line: func = line.split('FUNC:')[1].strip() func_counts[func] = func_counts.get(func, 0) + 1 + + # Stündliche Funktionsaufrufe + try: + timestamp = line[:19] + date = timestamp[:10] + hour = timestamp[11:13] + if len(hour) == 2 and hour.isdigit(): + hour_key = f"{date} {hour}:00" + if hour_key not in func_counts_hourly: + func_counts_hourly[hour_key] = {} + func_counts_hourly[hour_key][func] = func_counts_hourly[hour_key].get(func, 0) + 1 + except Exception: + pass elif 'FUNC_API:' in line: api = line.split('FUNC_API:')[1].strip() api_counts[api] = api_counts.get(api, 0) + 1 - return pageviews, func_counts, impressions_per_day, api_counts + + # Stündliche API-Aufrufe + try: + timestamp = line[:19] + date = timestamp[:10] + hour = timestamp[11:13] + if len(hour) == 2 and hour.isdigit(): + hour_key = f"{date} {hour}:00" + if hour_key not in api_counts_hourly: + api_counts_hourly[hour_key] = {} + api_counts_hourly[hour_key][api] = api_counts_hourly[hour_key].get(api, 0) + 1 + except Exception: + pass + return pageviews, func_counts, func_counts_hourly, impressions_per_day, impressions_per_hour, api_counts, api_counts_hourly @app.route('/stats', methods=['GET', 'POST']) def stats(): @@ -270,8 +307,8 @@ def stats(): return render_template('stats_login.html', error='Falsches Passwort!') return render_template('stats_login.html', error=None) log_path = os.path.join('log', 'pageviews.log') - pageviews, func_counts, impressions_per_day, api_counts = parse_log_stats(log_path) - return render_template('stats_dashboard.html', pageviews=pageviews, func_counts=func_counts, impressions_per_day=impressions_per_day, api_counts=api_counts) + pageviews, func_counts, func_counts_hourly, impressions_per_day, impressions_per_hour, api_counts, api_counts_hourly = parse_log_stats(log_path) + return render_template('stats_dashboard.html', pageviews=pageviews, func_counts=func_counts, func_counts_hourly=func_counts_hourly, impressions_per_day=impressions_per_day, impressions_per_hour=impressions_per_hour, api_counts=api_counts, api_counts_hourly=api_counts_hourly) # --- REST API --- def log_api_usage(api_name): diff --git a/templates/stats_dashboard.html b/templates/stats_dashboard.html index bd06df4..d280238 100644 --- a/templates/stats_dashboard.html +++ b/templates/stats_dashboard.html @@ -19,6 +19,32 @@ .stats-label { color: #64748b; } .stats-value { font-size: 1.5em; font-weight: bold; } .chart-container { margin: 2em 0; } + .toggle-container { + display: flex; + justify-content: center; + margin-bottom: 1.5em; + gap: 0.5em; + } + .toggle-btn { + padding: 0.5em 1em; + border: 1px solid #d1d5db; + background: #f9fafb; + color: #6b7280; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s; + } + .toggle-btn.active { + background: #2563eb; + color: white; + border-color: #2563eb; + } + .toggle-btn:hover { + background: #e5e7eb; + } + .toggle-btn.active:hover { + background: #1d4ed8; + } @@ -28,6 +54,12 @@
Gesamt-Pageviews (7 Tage):
{{ pageviews }}
+ +
+ + +
+
@@ -43,75 +75,196 @@