Files

123 lines
4.0 KiB
HTML

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Log Analyzer Dashboard</title>
<link rel="stylesheet" href="css/style.css">
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div id="app">
<header>
<h1>🔥 Log Analyzer</h1>
<span class="subtitle">Firewall &amp; Proxy Log Dashboard</span>
</header>
<main>
<section class="upload-card">
<h2>📤 Log-Datei hochladen</h2>
<input type="file" @change="handleFile" accept=".log,.txt,.csv">
<button @click="uploadFile" :disabled="!selectedFile || uploading">
{{ uploading ? 'Hochladen...' : 'Hochladen & Parsen' }}
</button>
<div v-if="uploadMsg" :class="['msg', uploadOk ? 'ok' : 'err']">{{ uploadMsg }}</div>
</section>
<section class="stats-grid" v-if="stats.overview.total_entries > 0">
<div class="stat-card">
<div class="stat-label">Gesamt Logs</div>
<div class="stat-value">{{ stats.overview.total_entries }}</div>
</div>
<div class="stat-card">
<div class="stat-label">Firewall</div>
<div class="stat-value">{{ stats.overview.firewall_entries }}</div>
</div>
<div class="stat-card">
<div class="stat-label">Proxy</div>
<div class="stat-value">{{ stats.overview.proxy_entries }}</div>
</div>
<div class="stat-card">
<div class="stat-label">Unique Sources</div>
<div class="stat-value">{{ stats.unique_counts.unique_sources }}</div>
</div>
<div class="stat-card">
<div class="stat-label">Unique Destinations</div>
<div class="stat-value">{{ stats.unique_counts.unique_destinations }}</div>
</div>
</section>
<section class="charts-grid" v-if="stats.overview.total_entries > 0">
<div class="chart-card">
<h3>Top Quellen</h3>
<canvas id="chartSources"></canvas>
</div>
<div class="chart-card">
<h3>Top Ziele</h3>
<canvas id="chartDestinations"></canvas>
</div>
<div class="chart-card">
<h3>Top Ports</h3>
<canvas id="chartPorts"></canvas>
</div>
<div class="chart-card wide">
<h3>Zeitverlauf (pro Stunde)</h3>
<canvas id="chartTimeline"></canvas>
</div>
</section>
<section class="tables" v-if="stats.top_urls.length > 0">
<h3>🔝 Top URLs</h3>
<table>
<thead><tr><th>URL</th><th>Hits</th></tr></thead>
<tbody>
<tr v-for="u in stats.top_urls.slice(0,20)" :key="u.url">
<td class="url">{{ u.url }}</td>
<td>{{ u.count }}</td>
</tr>
</tbody>
</table>
</section>
<section class="actions" v-if="stats.actions.length > 0">
<h3>⚡ Actions</h3>
<div class="action-tags">
<span v-for="a in stats.actions" :key="a.action" class="tag">
{{ a.action }}: {{ a.count }}
</span>
</div>
</section>
<section class="analyze">
<h2>🤖 LLM-Analyse</h2>
<div class="analyze-controls">
<label>Log-Typ:
<select v-model="analyzeType">
<option value="all">Alle</option>
<option value="firewall">Firewall</option>
<option value="proxy">Proxy</option>
</select>
</label>
<label>Zeilen:
<input type="number" v-model.number="analyzeLimit" min="10" max="500" step="10">
</label>
<button @click="runAnalysis" :disabled="analyzing || stats.overview.total_entries === 0">
{{ analyzing ? 'Analysiere...' : 'Analyse starten' }}
</button>
</div>
<div v-if="analysisResult" class="analysis-result">
<pre>{{ analysisResult }}</pre>
</div>
</section>
</main>
<footer>
<small>Log Analyzer Backend — <a href="/docs">API Docs</a></small>
</footer>
</div>
<script src="js/app.js"></script>
</body>
</html>