botui/ui/suite/monitoring/metrics.html

383 lines
21 KiB
HTML
Raw Normal View History

<!-- Metrics partial -->
<link rel="stylesheet" href="/static/suite/monitoring/metrics.css">
2025-12-06 11:09:12 -03:00
<div class="metrics-container">
<!-- Metrics Header -->
<div class="metrics-header">
<div class="header-info">
<h2>
2025-12-06 11:09:12 -03:00
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="20" x2="18" y2="10"></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
Metrics Dashboard
</h2>
<span class="last-sync"
hx-get="/api/monitoring/metrics/last-sync"
hx-trigger="load, every 30s"
hx-swap="innerHTML">Last sync: --</span>
</div>
<div class="header-actions">
<select id="metrics-time-range" onchange="updateMetricsRange(this.value)">
<option value="15m">Last 15 minutes</option>
<option value="1h" selected>Last 1 hour</option>
<option value="6h">Last 6 hours</option>
<option value="24h">Last 24 hours</option>
<option value="7d">Last 7 days</option>
</select>
<button class="action-btn secondary" onclick="refreshMetrics()">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="23 4 23 10 17 10"></polyline>
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
</svg>
Refresh
</button>
<a href="/metrics" target="_blank" class="action-btn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
Prometheus Export
</a>
</div>
</div>
<!-- Key Metrics Overview -->
<div class="key-metrics"
hx-get="/api/analytics/dashboard"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
<div class="metric-card">
<div class="metric-icon requests">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">--</span>
<span class="metric-label">Requests/sec</span>
</div>
<div class="metric-trend up">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
<span>--%</span>
</div>
</div>
<div class="metric-card">
<div class="metric-icon latency">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">-- ms</span>
<span class="metric-label">Avg Latency</span>
</div>
<div class="metric-trend down">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
<span>--%</span>
</div>
</div>
<div class="metric-card">
<div class="metric-icon errors">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">--%</span>
<span class="metric-label">Error Rate</span>
</div>
<div class="metric-trend neutral">
<span>--</span>
</div>
</div>
<div class="metric-card">
<div class="metric-icon users">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
<circle cx="9" cy="7" r="4"></circle>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">--</span>
<span class="metric-label">Active Users</span>
</div>
<div class="metric-trend up">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
<span>--%</span>
</div>
</div>
<div class="metric-card">
<div class="metric-icon conversations">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">--</span>
<span class="metric-label">Conversations</span>
</div>
<div class="metric-trend up">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="18 15 12 9 6 15"></polyline>
</svg>
<span>--%</span>
</div>
</div>
<div class="metric-card">
<div class="metric-icon uptime">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
</div>
<div class="metric-info">
<span class="metric-value">--%</span>
<span class="metric-label">Uptime</span>
</div>
<div class="metric-trend neutral">
<span>--</span>
</div>
</div>
</div>
<!-- Charts Grid -->
<div class="charts-grid">
<!-- Request Rate Chart -->
<div class="chart-panel">
<div class="chart-header">
<h3>Request Rate</h3>
<div class="chart-controls">
<select onchange="updateChartType('requests', this.value)">
<option value="line">Line</option>
<option value="area">Area</option>
<option value="bar">Bar</option>
</select>
</div>
</div>
<div class="chart-body" id="requests-chart"
hx-get="/api/analytics/metric?name=requests"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
<svg viewBox="0 0 600 200" class="chart-svg">
<defs>
<linearGradient id="requests-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:var(--primary);stop-opacity:0.3"/>
<stop offset="100%" style="stop-color:var(--primary);stop-opacity:0"/>
</linearGradient>
</defs>
<g class="chart-grid">
<line x1="50" y1="20" x2="580" y2="20" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="70" x2="580" y2="70" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="120" x2="580" y2="120" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="170" x2="580" y2="170" stroke="var(--border)" stroke-dasharray="4"/>
</g>
<g class="chart-axis-y">
<text x="45" y="25" fill="var(--text-secondary)" font-size="10" text-anchor="end">1000</text>
<text x="45" y="75" fill="var(--text-secondary)" font-size="10" text-anchor="end">750</text>
<text x="45" y="125" fill="var(--text-secondary)" font-size="10" text-anchor="end">500</text>
<text x="45" y="175" fill="var(--text-secondary)" font-size="10" text-anchor="end">250</text>
</g>
<path class="chart-area" d="M50,170 Q100,160 150,140 T250,100 T350,120 T450,90 T550,110 L550,170 Z" fill="url(#requests-gradient)"/>
<path class="chart-line" d="M50,170 Q100,160 150,140 T250,100 T350,120 T450,90 T550,110" fill="none" stroke="var(--primary)" stroke-width="2"/>
</svg>
</div>
</div>
<!-- Latency Chart -->
<div class="chart-panel">
<div class="chart-header">
<h3>Response Latency</h3>
<div class="chart-legend">
<span class="legend-item"><span class="legend-dot p50"></span>P50</span>
<span class="legend-item"><span class="legend-dot p95"></span>P95</span>
<span class="legend-item"><span class="legend-dot p99"></span>P99</span>
</div>
</div>
<div class="chart-body" id="latency-chart"
hx-get="/api/analytics/metric?name=latency"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
<svg viewBox="0 0 600 200" class="chart-svg">
<defs>
<linearGradient id="latency-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:var(--success);stop-opacity:0.2"/>
<stop offset="100%" style="stop-color:var(--success);stop-opacity:0"/>
</linearGradient>
</defs>
<g class="chart-grid">
<line x1="50" y1="20" x2="580" y2="20" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="70" x2="580" y2="70" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="120" x2="580" y2="120" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="170" x2="580" y2="170" stroke="var(--border)" stroke-dasharray="4"/>
</g>
<g class="chart-axis-y">
<text x="45" y="25" fill="var(--text-secondary)" font-size="10" text-anchor="end">500ms</text>
<text x="45" y="75" fill="var(--text-secondary)" font-size="10" text-anchor="end">375ms</text>
<text x="45" y="125" fill="var(--text-secondary)" font-size="10" text-anchor="end">250ms</text>
<text x="45" y="175" fill="var(--text-secondary)" font-size="10" text-anchor="end">125ms</text>
</g>
<path class="chart-line p99" d="M50,80 Q150,75 250,85 T450,70 T550,80" fill="none" stroke="var(--error)" stroke-width="1.5" stroke-dasharray="4"/>
<path class="chart-line p95" d="M50,110 Q150,100 250,115 T450,95 T550,105" fill="none" stroke="var(--warning)" stroke-width="1.5"/>
<path class="chart-area" d="M50,170 Q150,160 250,155 T450,150 T550,160 L550,170 Z" fill="url(#latency-gradient)"/>
<path class="chart-line p50" d="M50,170 Q150,160 250,155 T450,150 T550,160" fill="none" stroke="var(--success)" stroke-width="2"/>
</svg>
</div>
</div>
<!-- Error Rate Chart -->
<div class="chart-panel">
<div class="chart-header">
<h3>Error Rate</h3>
<div class="chart-legend">
<span class="legend-item"><span class="legend-dot error-4xx"></span>4xx</span>
<span class="legend-item"><span class="legend-dot error-5xx"></span>5xx</span>
</div>
</div>
<div class="chart-body" id="errors-chart"
hx-get="/api/analytics/metric?name=errors"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
<svg viewBox="0 0 600 200" class="chart-svg">
<g class="chart-grid">
<line x1="50" y1="20" x2="580" y2="20" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="70" x2="580" y2="70" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="120" x2="580" y2="120" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="170" x2="580" y2="170" stroke="var(--border)" stroke-dasharray="4"/>
</g>
<g class="chart-axis-y">
<text x="45" y="25" fill="var(--text-secondary)" font-size="10" text-anchor="end">10%</text>
<text x="45" y="75" fill="var(--text-secondary)" font-size="10" text-anchor="end">7.5%</text>
<text x="45" y="125" fill="var(--text-secondary)" font-size="10" text-anchor="end">5%</text>
<text x="45" y="175" fill="var(--text-secondary)" font-size="10" text-anchor="end">2.5%</text>
</g>
<g class="chart-bars">
<rect x="70" y="160" width="20" height="10" fill="var(--warning)" rx="2"/>
<rect x="70" y="165" width="20" height="5" fill="var(--error)" rx="2"/>
<rect x="120" y="155" width="20" height="15" fill="var(--warning)" rx="2"/>
<rect x="120" y="162" width="20" height="8" fill="var(--error)" rx="2"/>
<rect x="170" y="150" width="20" height="20" fill="var(--warning)" rx="2"/>
<rect x="170" y="160" width="20" height="10" fill="var(--error)" rx="2"/>
<rect x="220" y="158" width="20" height="12" fill="var(--warning)" rx="2"/>
<rect x="220" y="165" width="20" height="5" fill="var(--error)" rx="2"/>
<rect x="270" y="162" width="20" height="8" fill="var(--warning)" rx="2"/>
<rect x="270" y="167" width="20" height="3" fill="var(--error)" rx="2"/>
</g>
</svg>
</div>
</div>
<!-- Throughput Chart -->
<div class="chart-panel">
<div class="chart-header">
<h3>Throughput</h3>
<div class="chart-legend">
<span class="legend-item"><span class="legend-dot incoming"></span>In</span>
<span class="legend-item"><span class="legend-dot outgoing"></span>Out</span>
</div>
</div>
<div class="chart-body" id="throughput-chart"
hx-get="/api/analytics/metric?name=throughput"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
<svg viewBox="0 0 600 200" class="chart-svg">
<defs>
<linearGradient id="throughput-in-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#8b5cf6;stop-opacity:0.3"/>
<stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:0"/>
</linearGradient>
<linearGradient id="throughput-out-gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#06b6d4;stop-opacity:0.3"/>
<stop offset="100%" style="stop-color:#06b6d4;stop-opacity:0"/>
</linearGradient>
</defs>
<g class="chart-grid">
<line x1="50" y1="20" x2="580" y2="20" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="70" x2="580" y2="70" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="120" x2="580" y2="120" stroke="var(--border)" stroke-dasharray="4"/>
<line x1="50" y1="170" x2="580" y2="170" stroke="var(--border)" stroke-dasharray="4"/>
</g>
<g class="chart-axis-y">
<text x="45" y="25" fill="var(--text-secondary)" font-size="10" text-anchor="end">100MB</text>
<text x="45" y="75" fill="var(--text-secondary)" font-size="10" text-anchor="end">75MB</text>
<text x="45" y="125" fill="var(--text-secondary)" font-size="10" text-anchor="end">50MB</text>
<text x="45" y="175" fill="var(--text-secondary)" font-size="10" text-anchor="end">25MB</text>
</g>
<path class="chart-area" d="M50,130 Q150,110 250,120 T450,100 T550,115 L550,170 Z" fill="url(#throughput-in-gradient)"/>
<path class="chart-line" d="M50,130 Q150,110 250,120 T450,100 T550,115" fill="none" stroke="#8b5cf6" stroke-width="2"/>
<path class="chart-area" d="M50,150 Q150,140 250,145 T450,130 T550,140 L550,170 Z" fill="url(#throughput-out-gradient)"/>
<path class="chart-line" d="M50,150 Q150,140 250,145 T450,130 T550,140" fill="none" stroke="#06b6d4" stroke-width="2"/>
</svg>
</div>
</div>
</div>
<!-- Individual Metrics Table -->
<div class="metrics-table-section">
<div class="section-header">
<h3>
2025-12-06 11:09:12 -03:00
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
</svg>
All Metrics
</h3>
<div class="section-actions">
<div class="search-box">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
<input type="text" id="metric-search" placeholder="Search metrics..." onkeyup="filterMetrics(this.value)">
</div>
<select id="metric-category" onchange="filterByCategory(this.value)">
<option value="all">All Categories</option>
<option value="http">HTTP</option>
<option value="system">System</option>
<option value="database">Database</option>
<option value="cache">Cache</option>
<option value="queue">Queue</option>
</select>
</div>
</div>
<div class="metrics-table-container">
<table class="metrics-table" id="metrics-table"
hx-get="/api/analytics/metrics/list"
hx-trigger="load"
hx-swap="innerHTML">
<thead>
<tr>
<th>Metric Name</th>
<th>Type</th>
<th>Value</th>
<th>Category</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="6" class="loading-cell">Loading metrics...</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script src="/static/suite/monitoring/metrics.js"></script>