1708 lines
76 KiB
HTML
1708 lines
76 KiB
HTML
|
|
<!--
|
||
|
|
============================================================================
|
||
|
|
CAMELEER3 v2 — Operations Dashboard (Dark Theme)
|
||
|
|
============================================================================
|
||
|
|
|
||
|
|
DESIGN NOTES — SYNTHESIS RATIONALE
|
||
|
|
===================================
|
||
|
|
|
||
|
|
What was taken from each expert:
|
||
|
|
|
||
|
|
FROM DESIGN EXPERT:
|
||
|
|
- Amber-gold accent (#D4940F) as the primary brand color, maintaining the
|
||
|
|
"Desert Dusk" identity even in dark mode. The camel silhouette SVG logo.
|
||
|
|
- Typography system: DM Sans + JetBrains Mono, four-level hierarchy.
|
||
|
|
- Card-based layouts with subtle borders and layered surfaces.
|
||
|
|
- Duration bar sparklines for quick visual comparison.
|
||
|
|
- Warm sidebar tone (not pure black, but warm obsidian).
|
||
|
|
|
||
|
|
FROM USABILITY EXPERT:
|
||
|
|
- Full information hierarchy: health strip -> filter bar -> results -> detail.
|
||
|
|
- Master-detail pattern with slide-in panel (45% width on row select).
|
||
|
|
- Status pills with live counts, time preset chips, removable filter tags.
|
||
|
|
- Relative timestamps ("2m ago") with absolute fallback.
|
||
|
|
- Keyboard shortcut hints bar.
|
||
|
|
- Failed/running row border accents for scan-ability.
|
||
|
|
- Processor Gantt timeline in detail panel.
|
||
|
|
- Tab-based progressive disclosure in detail (Overview/Processors/Exchange/Error).
|
||
|
|
|
||
|
|
FROM OPERATOR EXPERT:
|
||
|
|
- Business IDs (Order ID, Customer, Source) as first-class table columns.
|
||
|
|
- Inline error previews directly below failed rows — no click needed.
|
||
|
|
- SLA threshold indicators on metric charts and duration cells.
|
||
|
|
- Agent health panel (integrated into sidebar).
|
||
|
|
- Trend arrows on all metric cards (directional context).
|
||
|
|
- Top error pattern grouping with occurrence counts.
|
||
|
|
- Shift-aware labeling ("since 06:00", overnight vs. today split).
|
||
|
|
|
||
|
|
KEY DESIGN DECISIONS:
|
||
|
|
1. Dark palette uses refined obsidian (#0B0F18) not generic navy. Surfaces
|
||
|
|
layer from #0B0F18 -> #111827 -> #1A2332 -> #212D3F for depth.
|
||
|
|
2. Status colors are tuned for dark contrast: emerald (#10B981), amber
|
||
|
|
(#F0B429), rose (#F43F5E), sky blue (#3B82F6) with subtle glow effects.
|
||
|
|
3. The warm amber accent (#D4940F) provides brand continuity with the light
|
||
|
|
theme — both mocks are clearly the same product.
|
||
|
|
4. Glow effects on status indicators (box-shadow with colored alpha) give
|
||
|
|
the dark theme a polished, premium feel without being garish.
|
||
|
|
5. Chart palettes use semi-transparent fills that work on dark backgrounds,
|
||
|
|
with SLA threshold lines clearly visible.
|
||
|
|
|
||
|
|
WHAT MAKES THIS BETTER THAN EACH INDIVIDUAL:
|
||
|
|
- Design expert had the warm brand but was light-only. This proves the amber
|
||
|
|
brand works equally well on dark backgrounds.
|
||
|
|
- Usability expert had a dark theme but with generic navy colors and no
|
||
|
|
business context. This uses refined obsidian + business data.
|
||
|
|
- Operator expert had excellent data but a flat single-page layout with no
|
||
|
|
sidebar or detail panel. This adds proper navigation + drill-down.
|
||
|
|
- The synthesis creates a cohesive dark monitoring experience: professional
|
||
|
|
enough for a NOC wall display, detailed enough for incident response.
|
||
|
|
|
||
|
|
============================================================================
|
||
|
|
-->
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=1920">
|
||
|
|
<title>Cameleer3 — Operations Dashboard (Dark)</title>
|
||
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
||
|
|
<style>
|
||
|
|
/* ==========================================================================
|
||
|
|
RESET & FOUNDATIONS
|
||
|
|
========================================================================== */
|
||
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||
|
|
|
||
|
|
:root {
|
||
|
|
/* Surface palette (obsidian layers) */
|
||
|
|
--bg-deep: #0B0F18;
|
||
|
|
--bg-base: #0E1220;
|
||
|
|
--bg-surface: #141B2A;
|
||
|
|
--bg-raised: #1A2332;
|
||
|
|
--bg-hover: #212D3F;
|
||
|
|
|
||
|
|
/* Sidebar (warm obsidian) */
|
||
|
|
--sidebar-bg: #0E1118;
|
||
|
|
--sidebar-hover: #171D28;
|
||
|
|
--sidebar-active: #1D2636;
|
||
|
|
--sidebar-text: #94A3B8;
|
||
|
|
--sidebar-muted: #475569;
|
||
|
|
|
||
|
|
/* Text */
|
||
|
|
--text-primary: #E8ECF4;
|
||
|
|
--text-secondary: #94A3B8;
|
||
|
|
--text-muted: #5A6B83;
|
||
|
|
--text-faint: #3A4A5E;
|
||
|
|
|
||
|
|
/* Borders */
|
||
|
|
--border: #1E2D3D;
|
||
|
|
--border-subtle: #172030;
|
||
|
|
|
||
|
|
/* Brand accent (amber-gold) */
|
||
|
|
--amber: #D4940F;
|
||
|
|
--amber-light: #F0C060;
|
||
|
|
--amber-bg: rgba(212, 148, 15, 0.12);
|
||
|
|
--amber-deep: #A67200;
|
||
|
|
--amber-glow: rgba(212, 148, 15, 0.15);
|
||
|
|
|
||
|
|
/* Status colors (dark-optimized, brighter for contrast) */
|
||
|
|
--success: #10B981;
|
||
|
|
--success-bg: rgba(16, 185, 129, 0.10);
|
||
|
|
--success-border: rgba(16, 185, 129, 0.25);
|
||
|
|
--success-glow: rgba(16, 185, 129, 0.15);
|
||
|
|
|
||
|
|
--warning: #F0B429;
|
||
|
|
--warning-bg: rgba(240, 180, 41, 0.10);
|
||
|
|
--warning-border: rgba(240, 180, 41, 0.25);
|
||
|
|
|
||
|
|
--error: #F43F5E;
|
||
|
|
--error-bg: rgba(244, 63, 94, 0.08);
|
||
|
|
--error-border: rgba(244, 63, 94, 0.20);
|
||
|
|
--error-glow: rgba(244, 63, 94, 0.12);
|
||
|
|
|
||
|
|
--running: #3B82F6;
|
||
|
|
--running-bg: rgba(59, 130, 246, 0.10);
|
||
|
|
--running-border: rgba(59, 130, 246, 0.25);
|
||
|
|
|
||
|
|
--cyan: #22D3EE;
|
||
|
|
--cyan-bg: rgba(34, 211, 238, 0.10);
|
||
|
|
|
||
|
|
/* Typography */
|
||
|
|
--font-body: 'DM Sans', system-ui, -apple-system, sans-serif;
|
||
|
|
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||
|
|
|
||
|
|
/* Spacing & Radii */
|
||
|
|
--radius-sm: 6px;
|
||
|
|
--radius-md: 8px;
|
||
|
|
--radius-lg: 12px;
|
||
|
|
|
||
|
|
/* Shadows (dark-optimized: deeper, colored) */
|
||
|
|
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||
|
|
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35);
|
||
|
|
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||
|
|
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.2), 0 0 0 1px var(--border-subtle);
|
||
|
|
}
|
||
|
|
|
||
|
|
html { font-size: 14px; }
|
||
|
|
body {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
background: var(--bg-deep);
|
||
|
|
color: var(--text-primary);
|
||
|
|
line-height: 1.5;
|
||
|
|
min-height: 100vh;
|
||
|
|
-webkit-font-smoothing: antialiased;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Subtle gradient background */
|
||
|
|
body::before {
|
||
|
|
content: '';
|
||
|
|
position: fixed;
|
||
|
|
inset: 0;
|
||
|
|
background:
|
||
|
|
radial-gradient(ellipse 900px 450px at 15% 10%, rgba(212, 148, 15, 0.03), transparent),
|
||
|
|
radial-gradient(ellipse 700px 700px at 85% 85%, rgba(34, 211, 238, 0.015), transparent);
|
||
|
|
pointer-events: none;
|
||
|
|
z-index: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
::-webkit-scrollbar { width: 6px; height: 6px; }
|
||
|
|
::-webkit-scrollbar-track { background: transparent; }
|
||
|
|
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
|
||
|
|
::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
ANIMATIONS
|
||
|
|
========================================================================== */
|
||
|
|
@keyframes fadeIn {
|
||
|
|
from { opacity: 0; transform: translateY(6px); }
|
||
|
|
to { opacity: 1; transform: translateY(0); }
|
||
|
|
}
|
||
|
|
@keyframes pulse {
|
||
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.4); }
|
||
|
|
50% { box-shadow: 0 0 0 5px rgba(16, 185, 129, 0); }
|
||
|
|
}
|
||
|
|
@keyframes errorPulse {
|
||
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(244, 63, 94, 0.2); }
|
||
|
|
50% { box-shadow: 0 0 0 4px rgba(244, 63, 94, 0); }
|
||
|
|
}
|
||
|
|
@keyframes slideIn {
|
||
|
|
from { opacity: 0; transform: translateX(20px); }
|
||
|
|
to { opacity: 1; transform: translateX(0); }
|
||
|
|
}
|
||
|
|
@keyframes glowPulse {
|
||
|
|
0%, 100% { opacity: 0.6; }
|
||
|
|
50% { opacity: 1; }
|
||
|
|
}
|
||
|
|
.animate-in { animation: fadeIn 0.3s ease-out both; }
|
||
|
|
.delay-1 { animation-delay: 0.04s; }
|
||
|
|
.delay-2 { animation-delay: 0.08s; }
|
||
|
|
.delay-3 { animation-delay: 0.12s; }
|
||
|
|
.delay-4 { animation-delay: 0.16s; }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
LAYOUT: 3-column
|
||
|
|
========================================================================== */
|
||
|
|
.app {
|
||
|
|
display: flex;
|
||
|
|
height: 100vh;
|
||
|
|
overflow: hidden;
|
||
|
|
position: relative;
|
||
|
|
z-index: 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
SIDEBAR (warm obsidian)
|
||
|
|
========================================================================== */
|
||
|
|
.sidebar {
|
||
|
|
width: 220px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
background: var(--sidebar-bg);
|
||
|
|
border-right: 1px solid var(--border-subtle);
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-logo {
|
||
|
|
padding: 16px 18px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 10px;
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-logo .brand {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 15px;
|
||
|
|
color: var(--amber-light);
|
||
|
|
letter-spacing: -0.3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-logo .version {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
margin-left: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-search { padding: 10px 12px; }
|
||
|
|
|
||
|
|
.sidebar-search input {
|
||
|
|
width: 100%;
|
||
|
|
background: var(--bg-raised);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
padding: 6px 10px 6px 28px;
|
||
|
|
color: var(--sidebar-text);
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: 12px;
|
||
|
|
outline: none;
|
||
|
|
transition: border-color 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-search input::placeholder { color: var(--sidebar-muted); }
|
||
|
|
.sidebar-search input:focus { border-color: var(--amber); }
|
||
|
|
|
||
|
|
.sidebar-search-wrap { position: relative; }
|
||
|
|
.sidebar-search-wrap .search-icon {
|
||
|
|
position: absolute;
|
||
|
|
left: 9px;
|
||
|
|
top: 50%;
|
||
|
|
transform: translateY(-50%);
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
font-size: 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-section {
|
||
|
|
padding: 14px 12px 5px;
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 1.2px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-items {
|
||
|
|
flex: 1;
|
||
|
|
overflow-y: auto;
|
||
|
|
padding: 0 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 10px;
|
||
|
|
padding: 7px 12px;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
color: var(--sidebar-text);
|
||
|
|
font-size: 13px;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: all 0.12s;
|
||
|
|
text-decoration: none;
|
||
|
|
border-left: 3px solid transparent;
|
||
|
|
margin-bottom: 1px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-item:hover { background: var(--sidebar-hover); color: var(--text-primary); }
|
||
|
|
.sidebar-item.active { background: var(--sidebar-active); color: var(--amber-light); border-left-color: var(--amber); }
|
||
|
|
|
||
|
|
.sidebar-item .health {
|
||
|
|
width: 7px;
|
||
|
|
height: 7px;
|
||
|
|
border-radius: 50%;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.health-live { background: var(--success); box-shadow: 0 0 6px var(--success-glow); }
|
||
|
|
.health-stale { background: var(--warning); box-shadow: 0 0 6px rgba(240, 180, 41, 0.3); }
|
||
|
|
.health-dead { background: var(--sidebar-muted); }
|
||
|
|
|
||
|
|
.sidebar-item .item-info { flex: 1; min-width: 0; }
|
||
|
|
.sidebar-item .item-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||
|
|
.sidebar-item .item-meta { font-size: 11px; color: var(--sidebar-muted); font-family: var(--font-mono); }
|
||
|
|
|
||
|
|
.sidebar-item .item-count {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
background: var(--bg-raised);
|
||
|
|
padding: 1px 6px;
|
||
|
|
border-radius: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-item.active .item-count { background: var(--amber-bg); color: var(--amber-light); }
|
||
|
|
|
||
|
|
.sidebar-divider {
|
||
|
|
height: 1px;
|
||
|
|
background: var(--border-subtle);
|
||
|
|
margin: 6px 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Agent health in sidebar */
|
||
|
|
.sidebar-agents-header {
|
||
|
|
padding: 14px 12px 6px;
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 1.2px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-agent-badge {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
padding: 1px 6px;
|
||
|
|
border-radius: 10px;
|
||
|
|
background: var(--success-bg);
|
||
|
|
color: var(--success);
|
||
|
|
border: 1px solid var(--success-border);
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-item {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
padding: 6px 12px;
|
||
|
|
margin: 0 6px 2px;
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
font-size: 11px;
|
||
|
|
color: var(--sidebar-text);
|
||
|
|
transition: background 0.1s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-item:hover { background: var(--sidebar-hover); }
|
||
|
|
|
||
|
|
.agent-dot {
|
||
|
|
width: 6px;
|
||
|
|
height: 6px;
|
||
|
|
border-radius: 50%;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-info { flex: 1; min-width: 0; }
|
||
|
|
.agent-name { font-family: var(--font-mono); font-size: 11px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text-secondary); }
|
||
|
|
.agent-detail { font-size: 10px; color: var(--sidebar-muted); }
|
||
|
|
|
||
|
|
.agent-stats-col {
|
||
|
|
text-align: right;
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-tps { color: var(--sidebar-text); }
|
||
|
|
|
||
|
|
.sidebar-bottom {
|
||
|
|
border-top: 1px solid var(--border-subtle);
|
||
|
|
padding: 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-bottom .sidebar-item {
|
||
|
|
font-size: 12px;
|
||
|
|
color: var(--sidebar-muted);
|
||
|
|
border-left: 3px solid transparent;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar-bottom .sidebar-item:hover { color: var(--sidebar-text); }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
MAIN CONTENT AREA
|
||
|
|
========================================================================== */
|
||
|
|
.main {
|
||
|
|
flex: 1;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
overflow: hidden;
|
||
|
|
min-width: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Top bar */
|
||
|
|
.topbar {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 12px;
|
||
|
|
padding: 0 24px;
|
||
|
|
height: 48px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
background: rgba(14, 18, 32, 0.85);
|
||
|
|
backdrop-filter: blur(16px);
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-breadcrumb {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
font-size: 13px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-breadcrumb .crumb-active { color: var(--text-primary); font-weight: 600; }
|
||
|
|
.topbar-breadcrumb .crumb-sep { color: var(--text-faint); font-size: 11px; }
|
||
|
|
|
||
|
|
.topbar-search {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 5px 12px;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
background: var(--bg-raised);
|
||
|
|
color: var(--text-muted);
|
||
|
|
font-size: 12px;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: border-color 0.15s;
|
||
|
|
min-width: 280px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-search:hover { border-color: var(--text-muted); }
|
||
|
|
|
||
|
|
.topbar-kbd {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
padding: 0 4px;
|
||
|
|
border-radius: 3px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
margin-left: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-right {
|
||
|
|
margin-left: auto;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-env {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
padding: 3px 10px;
|
||
|
|
border-radius: 10px;
|
||
|
|
background: var(--success-bg);
|
||
|
|
color: var(--success);
|
||
|
|
border: 1px solid var(--success-border);
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-shift {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
padding: 3px 10px;
|
||
|
|
border-radius: 10px;
|
||
|
|
background: var(--cyan-bg);
|
||
|
|
color: var(--cyan);
|
||
|
|
border: 1px solid rgba(34, 211, 238, 0.2);
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-user {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 8px;
|
||
|
|
font-size: 12px;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
}
|
||
|
|
|
||
|
|
.topbar-avatar {
|
||
|
|
width: 28px;
|
||
|
|
height: 28px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--amber-bg);
|
||
|
|
color: var(--amber);
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 11px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
border: 1px solid rgba(212, 148, 15, 0.3);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Content scroll container */
|
||
|
|
.content-wrap {
|
||
|
|
flex: 1;
|
||
|
|
display: flex;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.content {
|
||
|
|
flex: 1;
|
||
|
|
overflow-y: auto;
|
||
|
|
padding: 20px 24px 40px;
|
||
|
|
min-width: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
HEALTH STATUS BAR
|
||
|
|
========================================================================== */
|
||
|
|
.health-strip {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(5, 1fr);
|
||
|
|
gap: 10px;
|
||
|
|
margin-bottom: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-card {
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border-subtle);
|
||
|
|
border-radius: var(--radius-md);
|
||
|
|
padding: 12px 16px;
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
transition: border-color 0.2s;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-card:hover { border-color: var(--border); }
|
||
|
|
|
||
|
|
.stat-card::before {
|
||
|
|
content: '';
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
right: 0;
|
||
|
|
height: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-card.card-amber::before { background: linear-gradient(90deg, var(--amber), transparent); }
|
||
|
|
.stat-card.card-green::before { background: linear-gradient(90deg, var(--success), transparent); }
|
||
|
|
.stat-card.card-error::before { background: linear-gradient(90deg, var(--error), transparent); }
|
||
|
|
.stat-card.card-teal::before { background: linear-gradient(90deg, var(--cyan), transparent); }
|
||
|
|
.stat-card.card-warn::before { background: linear-gradient(90deg, var(--warning), transparent); }
|
||
|
|
|
||
|
|
.stat-card.has-errors { animation: errorPulse 2.5s ease-in-out infinite; }
|
||
|
|
|
||
|
|
.stat-label {
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.6px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
margin-bottom: 3px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-value-row {
|
||
|
|
display: flex;
|
||
|
|
align-items: baseline;
|
||
|
|
gap: 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-value {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 20px;
|
||
|
|
font-weight: 600;
|
||
|
|
line-height: 1.2;
|
||
|
|
color: var(--text-primary);
|
||
|
|
}
|
||
|
|
|
||
|
|
.stat-value.val-amber { color: var(--amber); }
|
||
|
|
.stat-value.val-green { color: var(--success); }
|
||
|
|
.stat-value.val-error { color: var(--error); }
|
||
|
|
.stat-value.val-teal { color: var(--cyan); }
|
||
|
|
.stat-value.val-warn { color: var(--warning); }
|
||
|
|
|
||
|
|
.stat-unit { font-size: 12px; color: var(--text-muted); }
|
||
|
|
|
||
|
|
.stat-trend {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 2px;
|
||
|
|
margin-left: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.trend-up-good { color: var(--success); }
|
||
|
|
.trend-up-bad { color: var(--error); }
|
||
|
|
.trend-down-good { color: var(--success); }
|
||
|
|
.trend-down-bad { color: var(--error); }
|
||
|
|
.trend-flat { color: var(--text-muted); }
|
||
|
|
|
||
|
|
.stat-detail { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
|
||
|
|
.stat-detail strong { color: var(--text-secondary); }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
FILTER BAR
|
||
|
|
========================================================================== */
|
||
|
|
.filter-section {
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border-subtle);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
padding: 12px 16px;
|
||
|
|
margin-bottom: 16px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-row {
|
||
|
|
display: flex;
|
||
|
|
gap: 8px;
|
||
|
|
align-items: center;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-group {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 5px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-label {
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.5px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
white-space: nowrap;
|
||
|
|
margin-right: 2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-sep {
|
||
|
|
width: 1px;
|
||
|
|
height: 22px;
|
||
|
|
background: var(--border);
|
||
|
|
margin: 0 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-pill {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 4px;
|
||
|
|
padding: 4px 12px;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: 20px;
|
||
|
|
background: transparent;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 500;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: all 0.12s;
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-pill:hover { border-color: var(--text-muted); background: var(--bg-raised); }
|
||
|
|
|
||
|
|
.filter-pill.active {
|
||
|
|
background: var(--amber-bg);
|
||
|
|
border-color: rgba(212, 148, 15, 0.35);
|
||
|
|
color: var(--amber-light);
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.pill-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
||
|
|
.pill-count { font-family: var(--font-mono); font-size: 10px; opacity: 0.7; }
|
||
|
|
|
||
|
|
.filter-input-wrap { position: relative; flex: 1; max-width: 360px; }
|
||
|
|
|
||
|
|
.filter-input-wrap .fi-icon {
|
||
|
|
position: absolute;
|
||
|
|
left: 10px;
|
||
|
|
top: 50%;
|
||
|
|
transform: translateY(-50%);
|
||
|
|
color: var(--text-muted);
|
||
|
|
font-size: 13px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-input {
|
||
|
|
width: 100%;
|
||
|
|
padding: 6px 12px 6px 30px;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
background: var(--bg-raised);
|
||
|
|
color: var(--text-primary);
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: 12px;
|
||
|
|
outline: none;
|
||
|
|
transition: border-color 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-input::placeholder { color: var(--text-muted); }
|
||
|
|
.filter-input:focus { border-color: var(--amber); box-shadow: 0 0 0 3px var(--amber-bg); }
|
||
|
|
|
||
|
|
.active-filters {
|
||
|
|
display: flex;
|
||
|
|
gap: 6px;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
align-items: center;
|
||
|
|
margin-top: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-tag {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 3px 10px;
|
||
|
|
background: var(--amber-bg);
|
||
|
|
border: 1px solid rgba(212, 148, 15, 0.25);
|
||
|
|
border-radius: 20px;
|
||
|
|
font-size: 11px;
|
||
|
|
color: var(--amber-light);
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
}
|
||
|
|
|
||
|
|
.filter-tag-remove { cursor: pointer; opacity: 0.5; font-size: 13px; line-height: 1; background: none; border: none; color: inherit; }
|
||
|
|
.filter-tag-remove:hover { opacity: 1; }
|
||
|
|
|
||
|
|
.clear-all { font-size: 11px; color: var(--text-muted); cursor: pointer; padding: 3px 6px; background: none; border: none; }
|
||
|
|
.clear-all:hover { color: var(--error); }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
EXECUTION TABLE
|
||
|
|
========================================================================== */
|
||
|
|
.table-section {
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border-subtle);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
overflow: hidden;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.table-header {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 10px 16px;
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
}
|
||
|
|
|
||
|
|
.table-title { font-size: 13px; font-weight: 600; color: var(--text-primary); }
|
||
|
|
|
||
|
|
.table-right { display: flex; align-items: center; gap: 12px; }
|
||
|
|
.table-meta { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
|
||
|
|
|
||
|
|
.live-btn {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 5px 12px;
|
||
|
|
border: 1px solid var(--success-border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
background: var(--success-bg);
|
||
|
|
color: var(--success);
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
font-weight: 500;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: all 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.live-btn:hover { background: rgba(16, 185, 129, 0.15); }
|
||
|
|
|
||
|
|
.live-dot {
|
||
|
|
width: 6px;
|
||
|
|
height: 6px;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: var(--success);
|
||
|
|
animation: pulse 2s ease-in-out infinite;
|
||
|
|
}
|
||
|
|
|
||
|
|
.table-scroll { overflow-x: auto; }
|
||
|
|
|
||
|
|
table { width: 100%; border-collapse: collapse; }
|
||
|
|
|
||
|
|
thead {
|
||
|
|
background: var(--bg-raised);
|
||
|
|
border-bottom: 1px solid var(--border);
|
||
|
|
}
|
||
|
|
|
||
|
|
th {
|
||
|
|
padding: 9px 14px;
|
||
|
|
text-align: left;
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.8px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
white-space: nowrap;
|
||
|
|
user-select: none;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: color 0.12s;
|
||
|
|
}
|
||
|
|
|
||
|
|
th:hover { color: var(--text-secondary); }
|
||
|
|
th.sorted { color: var(--amber); }
|
||
|
|
.sort-arrow { font-size: 8px; margin-left: 3px; opacity: 0.4; }
|
||
|
|
th.sorted .sort-arrow { opacity: 1; }
|
||
|
|
|
||
|
|
tbody tr {
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
border-left: 3px solid transparent;
|
||
|
|
transition: background 0.08s;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
tbody tr:last-child { border-bottom: none; }
|
||
|
|
tbody tr:hover { background: var(--bg-hover); }
|
||
|
|
tbody tr.selected { background: var(--amber-bg); }
|
||
|
|
|
||
|
|
tbody tr.row-error { border-left-color: var(--error); }
|
||
|
|
tbody tr.row-warning { border-left-color: var(--warning); }
|
||
|
|
tbody tr.row-running { border-left-color: var(--running); }
|
||
|
|
|
||
|
|
td {
|
||
|
|
padding: 9px 14px;
|
||
|
|
font-size: 13px;
|
||
|
|
vertical-align: top;
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Status badge with glow */
|
||
|
|
.status-badge {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 5px;
|
||
|
|
padding: 2px 10px;
|
||
|
|
border-radius: 12px;
|
||
|
|
font-size: 11px;
|
||
|
|
font-weight: 600;
|
||
|
|
letter-spacing: 0.2px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-success { background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border); }
|
||
|
|
.status-warning { background: var(--warning-bg); color: var(--warning); border: 1px solid var(--warning-border); }
|
||
|
|
.status-error { background: var(--error-bg); color: var(--error); border: 1px solid var(--error-border); }
|
||
|
|
.status-running { background: var(--running-bg); color: var(--running); border: 1px solid var(--running-border); }
|
||
|
|
|
||
|
|
.status-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
||
|
|
|
||
|
|
/* Glow on status indicators */
|
||
|
|
.status-success .status-dot { box-shadow: 0 0 4px var(--success-glow); }
|
||
|
|
.status-error .status-dot { box-shadow: 0 0 4px var(--error-glow); }
|
||
|
|
|
||
|
|
.route-name { font-weight: 500; color: var(--text-primary); }
|
||
|
|
.route-name:hover { color: var(--amber); }
|
||
|
|
.route-group { font-size: 11px; color: var(--text-muted); }
|
||
|
|
|
||
|
|
.biz-id { font-family: var(--font-mono); font-weight: 500; color: var(--cyan); font-size: 12px; }
|
||
|
|
.biz-id-secondary { font-family: var(--font-mono); font-size: 11px; color: var(--text-muted); }
|
||
|
|
|
||
|
|
.time-relative { color: var(--text-secondary); font-size: 13px; }
|
||
|
|
.time-absolute { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); display: block; }
|
||
|
|
|
||
|
|
.duration { font-family: var(--font-mono); font-size: 12px; }
|
||
|
|
.dur-fast { color: var(--success); }
|
||
|
|
.dur-normal { color: var(--text-primary); }
|
||
|
|
.dur-slow { color: var(--warning); }
|
||
|
|
.dur-breach { color: var(--error); font-weight: 600; }
|
||
|
|
|
||
|
|
.sla-tag {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 2px;
|
||
|
|
color: var(--error);
|
||
|
|
font-size: 10px;
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-weight: 600;
|
||
|
|
margin-left: 4px;
|
||
|
|
animation: glowPulse 2s ease-in-out infinite;
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-badge {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 4px;
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
}
|
||
|
|
|
||
|
|
.agent-badge-dot { width: 5px; height: 5px; border-radius: 50%; }
|
||
|
|
|
||
|
|
/* Error preview row */
|
||
|
|
.error-preview-row td {
|
||
|
|
padding: 0 14px 8px 20px !important;
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-preview {
|
||
|
|
display: flex;
|
||
|
|
align-items: flex-start;
|
||
|
|
gap: 8px;
|
||
|
|
padding: 8px 12px;
|
||
|
|
background: rgba(244, 63, 94, 0.05);
|
||
|
|
border: 1px solid var(--error-border);
|
||
|
|
border-left: 3px solid var(--error);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 11px;
|
||
|
|
color: var(--error);
|
||
|
|
line-height: 1.6;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-preview-icon { flex-shrink: 0; margin-top: 1px; }
|
||
|
|
.error-preview-text { white-space: normal; word-break: break-word; }
|
||
|
|
.error-expand-hint { color: var(--text-muted); font-size: 10px; margin-top: 4px; font-family: var(--font-body); }
|
||
|
|
|
||
|
|
/* Pagination */
|
||
|
|
.table-footer {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 8px 16px;
|
||
|
|
border-top: 1px solid var(--border-subtle);
|
||
|
|
font-size: 12px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
background: var(--bg-raised);
|
||
|
|
}
|
||
|
|
|
||
|
|
.pagination { display: flex; align-items: center; gap: 4px; }
|
||
|
|
|
||
|
|
.page-btn {
|
||
|
|
padding: 4px 10px;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
background: transparent;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
font-size: 12px;
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
cursor: pointer;
|
||
|
|
transition: all 0.12s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.page-btn:hover { background: var(--bg-hover); border-color: var(--text-muted); }
|
||
|
|
.page-btn.active { background: var(--amber-bg); border-color: rgba(212, 148, 15, 0.35); color: var(--amber-light); font-weight: 600; }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
METRICS ROW
|
||
|
|
========================================================================== */
|
||
|
|
.metrics-row {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 1fr 1fr 1fr;
|
||
|
|
gap: 14px;
|
||
|
|
margin-bottom: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.metric-card {
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border-subtle);
|
||
|
|
border-radius: var(--radius-lg);
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.metric-card-header {
|
||
|
|
padding: 12px 16px 0;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
}
|
||
|
|
|
||
|
|
.metric-card-title { font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
|
||
|
|
.metric-card-value { font-family: var(--font-mono); font-size: 14px; font-weight: 600; color: var(--text-primary); }
|
||
|
|
|
||
|
|
.metric-chart { padding: 10px 16px 12px; height: 90px; position: relative; }
|
||
|
|
|
||
|
|
.chart-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
||
|
|
.chart-area { opacity: 0.15; }
|
||
|
|
.chart-grid-line { stroke: var(--border-subtle); stroke-width: 0.5; }
|
||
|
|
.chart-label { font-family: var(--font-mono); font-size: 9px; fill: var(--text-muted); }
|
||
|
|
|
||
|
|
.sla-line { stroke: var(--error); stroke-width: 1; stroke-dasharray: 4 3; opacity: 0.6; }
|
||
|
|
.sla-label-text { fill: var(--error); font-size: 8px; font-family: var(--font-mono); opacity: 0.7; }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
DETAIL PANEL
|
||
|
|
========================================================================== */
|
||
|
|
.detail-panel {
|
||
|
|
width: 0;
|
||
|
|
overflow: hidden;
|
||
|
|
transition: width 0.25s ease, opacity 0.2s ease;
|
||
|
|
opacity: 0;
|
||
|
|
border-left: 1px solid transparent;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
background: var(--bg-surface);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-panel.open {
|
||
|
|
width: 400px;
|
||
|
|
opacity: 1;
|
||
|
|
border-left-color: var(--border);
|
||
|
|
animation: slideIn 0.25s ease-out both;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-header {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 12px 16px;
|
||
|
|
border-bottom: 1px solid var(--border-subtle);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-breadcrumb { font-size: 11px; color: var(--text-muted); display: flex; align-items: center; gap: 5px; }
|
||
|
|
.detail-breadcrumb .bc-sep { color: var(--text-faint); font-size: 9px; }
|
||
|
|
.detail-breadcrumb .bc-current { color: var(--amber); font-weight: 500; }
|
||
|
|
|
||
|
|
.detail-close {
|
||
|
|
width: 26px;
|
||
|
|
height: 26px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
background: none;
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
color: var(--text-muted);
|
||
|
|
cursor: pointer;
|
||
|
|
font-size: 13px;
|
||
|
|
transition: all 0.15s;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-close:hover { color: var(--text-primary); border-color: var(--text-muted); }
|
||
|
|
|
||
|
|
.detail-tabs { display: flex; border-bottom: 1px solid var(--border-subtle); flex-shrink: 0; }
|
||
|
|
|
||
|
|
.detail-tab {
|
||
|
|
padding: 9px 16px;
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 500;
|
||
|
|
color: var(--text-muted);
|
||
|
|
cursor: pointer;
|
||
|
|
border-bottom: 2px solid transparent;
|
||
|
|
transition: all 0.15s;
|
||
|
|
background: none;
|
||
|
|
border-top: none; border-left: none; border-right: none;
|
||
|
|
font-family: var(--font-body);
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-tab:hover { color: var(--text-secondary); }
|
||
|
|
.detail-tab.active { color: var(--amber); border-bottom-color: var(--amber); }
|
||
|
|
|
||
|
|
.detail-body {
|
||
|
|
flex: 1;
|
||
|
|
overflow-y: auto;
|
||
|
|
padding: 16px;
|
||
|
|
background: var(--bg-deep);
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-section { margin-bottom: 18px; }
|
||
|
|
|
||
|
|
.detail-section-title {
|
||
|
|
font-size: 10px;
|
||
|
|
font-weight: 600;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.8px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
margin-bottom: 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-grid {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: 100px 1fr;
|
||
|
|
gap: 6px 10px;
|
||
|
|
font-size: 12px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.detail-key { color: var(--text-muted); font-size: 11px; }
|
||
|
|
.detail-val { color: var(--text-primary); font-family: var(--font-mono); font-size: 11px; word-break: break-all; }
|
||
|
|
.detail-val.error-text { color: var(--error); }
|
||
|
|
.detail-val.link { color: var(--amber); cursor: pointer; }
|
||
|
|
|
||
|
|
/* Processor timeline */
|
||
|
|
.processor-timeline { display: flex; flex-direction: column; gap: 5px; }
|
||
|
|
.proc-row { display: flex; align-items: center; gap: 8px; font-size: 11px; }
|
||
|
|
|
||
|
|
.proc-name {
|
||
|
|
width: 100px;
|
||
|
|
text-align: right;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 10px;
|
||
|
|
overflow: hidden;
|
||
|
|
text-overflow: ellipsis;
|
||
|
|
white-space: nowrap;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.proc-bar-bg {
|
||
|
|
flex: 1;
|
||
|
|
height: 16px;
|
||
|
|
background: var(--bg-raised);
|
||
|
|
border-radius: 3px;
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
|
||
|
|
.proc-bar-fill {
|
||
|
|
position: absolute;
|
||
|
|
top: 0;
|
||
|
|
height: 100%;
|
||
|
|
border-radius: 3px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: flex-end;
|
||
|
|
padding-right: 5px;
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 8px;
|
||
|
|
color: rgba(255,255,255,0.8);
|
||
|
|
min-width: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.proc-ok { background: rgba(16, 185, 129, 0.45); }
|
||
|
|
.proc-slow { background: rgba(240, 180, 41, 0.45); }
|
||
|
|
.proc-fail { background: rgba(244, 63, 94, 0.45); }
|
||
|
|
|
||
|
|
.proc-dur { width: 42px; font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); flex-shrink: 0; }
|
||
|
|
|
||
|
|
/* Error block */
|
||
|
|
.error-block {
|
||
|
|
background: rgba(244, 63, 94, 0.05);
|
||
|
|
border: 1px solid var(--error-border);
|
||
|
|
border-left: 3px solid var(--error);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
padding: 12px 14px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-class { font-family: var(--font-mono); font-size: 11px; color: var(--error); font-weight: 600; margin-bottom: 4px; }
|
||
|
|
|
||
|
|
.error-message-detail { font-family: var(--font-mono); font-size: 10px; color: var(--text-secondary); line-height: 1.6; }
|
||
|
|
|
||
|
|
.error-expand { margin-top: 6px; font-size: 10px; color: var(--text-muted); cursor: pointer; background: none; border: none; font-family: var(--font-mono); }
|
||
|
|
.error-expand:hover { color: var(--amber); }
|
||
|
|
|
||
|
|
/* Detail actions */
|
||
|
|
.detail-actions {
|
||
|
|
display: flex;
|
||
|
|
gap: 6px;
|
||
|
|
padding: 10px 16px;
|
||
|
|
border-top: 1px solid var(--border-subtle);
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.action-btn { padding: 6px 14px; border-radius: var(--radius-sm); font-size: 11px; font-weight: 500; cursor: pointer; transition: all 0.15s; font-family: var(--font-body); }
|
||
|
|
.action-btn.primary { background: var(--amber); color: var(--bg-deep); border: none; }
|
||
|
|
.action-btn.primary:hover { background: var(--amber-light); }
|
||
|
|
.action-btn.secondary { background: none; border: 1px solid var(--border); color: var(--text-secondary); }
|
||
|
|
.action-btn.secondary:hover { border-color: var(--text-muted); color: var(--text-primary); }
|
||
|
|
|
||
|
|
/* ==========================================================================
|
||
|
|
KEYBOARD SHORTCUTS BAR
|
||
|
|
========================================================================== */
|
||
|
|
.shortcuts-bar {
|
||
|
|
position: fixed;
|
||
|
|
bottom: 12px;
|
||
|
|
right: 12px;
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
z-index: 50;
|
||
|
|
animation: fadeIn 0.5s ease-out 0.5s both;
|
||
|
|
}
|
||
|
|
|
||
|
|
.shortcut-hint {
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 5px;
|
||
|
|
font-size: 10px;
|
||
|
|
color: var(--text-muted);
|
||
|
|
background: var(--bg-surface);
|
||
|
|
border: 1px solid var(--border-subtle);
|
||
|
|
border-radius: var(--radius-sm);
|
||
|
|
padding: 4px 8px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.shortcut-hint kbd {
|
||
|
|
font-family: var(--font-mono);
|
||
|
|
font-size: 9px;
|
||
|
|
background: var(--bg-raised);
|
||
|
|
border: 1px solid var(--border);
|
||
|
|
border-radius: 3px;
|
||
|
|
padding: 0 4px;
|
||
|
|
color: var(--text-secondary);
|
||
|
|
}
|
||
|
|
|
||
|
|
.mono { font-family: var(--font-mono); }
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="app">
|
||
|
|
|
||
|
|
<!-- SIDEBAR -->
|
||
|
|
<aside class="sidebar">
|
||
|
|
<div class="sidebar-logo">
|
||
|
|
<svg width="24" height="26" viewBox="940 300 900 1000" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
|
|
<path style="fill:#D4940F" d="M 1385.2768,1205.0273 c -1.7727,-1.0809 -3.4419,-2.9917 -3.7093,-4.2463 -0.2674,-1.2545 -0.6851,-23.881 -0.9282,-50.281 -0.4544,-49.3389 -1.4003,-65.7355 -5.6645,-98.1921 -10.4552,-79.57719 -28.3441,-125.96796 -62.5438,-162.19311 -9.2529,-9.80096 -19.9748,-18.38696 -33.931,-27.17162 -12.6119,-7.93853 -24.8581,-13.73088 -49.5,-23.41316 -41.7081,-16.38789 -67.8677,-32.29827 -89.0588,-54.16599 -34.7586,-35.86827 -54.3653,-83.30392 -59.0504,-142.86402 -0.8357,-10.6245 -0.92,-22.5842 -0.2891,-41 0.4899,-14.3 0.8164,-35.225 0.7255,-46.5 -0.1983,-24.59199 -2.0251,-34.76973 -8.4617,-47.14159 -6.2021,-11.92135 -10.364,-15.10789 -36.2345,-27.74305 -25.4032,-12.40694 -27.7701,-13.30168 -35.4717,-13.40961 -4.63013,-0.0649 -7.47783,0.72754 -15.6593,4.35747 -9.86218,4.37563 -10.15161,4.43672 -21,4.43267 -10.86566,-0.004 -11.08917,-0.0517 -18.30169,-3.90103 -17.43524,-9.3052 -21.50075,-23.5772 -13.55784,-47.59486 2.73631,-8.27402 10.00732,-22.43593 14.69263,-28.61719 5.4984,-7.25394 10.89014,-11.83885 20.83968,-17.72117 15.06768,-8.90827 29.60254,-11.98884 63.90372,-13.54403 l 16.5765,-0.75156 14.9235,-7.05735 c 8.2079,-3.88154 17.1735,-7.76831 19.9235,-8.63727 7.7052,-2.43474 21.059,-4.67186 27.8605,-4.66741 8.0518,0.005 22.643,2.41202 30.0139,4.95066 l 5.8744,2.02321 4.8856,-4.09041 c 10.341,-8.65797 18.6496,-12.95738 28.96,-14.98583 6.9966,-1.37649 26.3532,-0.64631 32.1116,1.21134 4.5531,1.46885 5.4951,3.7902 6.3689,15.69592 1.5167,20.66426 -5.0112,40.44987 -18.1772,55.09363 -4.3065,4.78983 -4.5016,5.25488 -3.4977,8.33516 4.5184,13.86447 5.3154,38.07517 2.1537,65.42564 -5.169,44.71349 -5.0411,70.7797 0.5404,110.15637 6.8135,48.06863 22.3335,73.51874 48.2051,79.04779 24.1748,5.16643 45.2921,-5.78181 66.8353,-34.65077 4.809,-6.4442 11.1363,-14.93006 14.0608,-18.85747 7.3865,-9.91943 25.6102,-27.11708 35.952,-33.92766 12.5235,-8.24739 26.8808,-14.74833 42.8527,-19.40354 15.4108,-4.49168 26.7091,-9.74984 36.2432,-16.86731 3.4338,-2.56341 13.3338,-12.03104 22,-21.03916 26.2356,-27.27067 44.5755,-40.32368 66.9928,-47.68062 19.1052,-6.26998 35.4927,-7.73718 50.8681,-4.55427 37.0856,7.67726 63.5507,26.77589 100.2888,72.37362 16.6011,20.60463 29.9711,32.07977 51.6071,44.29313 39.3131,22.19195 50.1228,30.50985 68.8076,52.94655 5.4963,6.6 12.9187,14.91604 16.4941,18.4801 33.6796,33.57259 54.1965,72.51092 61.6587,117.0199 2.7315,16.29242 3.3374,26.62538 3.1861,54.33713 l -0.1465,26.83714 -2.7975,2.40572 c -3.9132,3.36522 -7.2806,3.99163 -11.2591,2.09442 -6.4731,-3.08682 -6.5715,-3.57833 -6.878,-34.36929 -0.2908,-29.2175 -2.0265,-46.13705 -6.6479,-64.80512 -3.2997,-13.32891 -12.2529,-34.61943 -17.0313,-40.5 l -2.0314,-2.5 0.5698,3.5 c 5.8574,35.97875 4.2855,72.40287 -5.3946,125 -8.4016,45.65054 -4.3665,69.39588 20.7318,122 11.4175,23.93009 12.5452,27.25907 12.4212,36.6684 -0.1018,7.7227 -2.5346,19.5162 -13.1674,63.8316 -1.0558,4.4 -3.5336,14.975 -5.5063,23.5 -1.9727,8.525 -4.2259,18.2 -5.0072,21.5 -0.7812,3.3 -3.4495,15.225 -5.9296,26.5 -9.1636,41.6596 -13.4372,59.8787 -14.5204,61.9027 -2.4994,4.6702 -5.2312,5.0973 -32.6024,5.0973 H 1765.8 l -3.4,-3.4 c -2.3518,-2.3518 -3.4,-4.3226 -3.4,-6.3925 0,-1.6458 2.2347,-12.1533 4.966,-23.35 8.6906,-35.6259 11.6969,-54.778 12.6921,-80.8575 1.3475,-35.3073 -4.6406,-62.7687 -18.7825,-86.137 -7.6672,-12.66954 -11.9163,-17.84148 -29.8756,-36.36415 -22.9362,-23.65574 -34.6222,-39.72583 -47.9268,-65.90697 -5.7294,-11.27448 -13.6061,-31.99995 -15.5051,-40.79778 -0.3212,-1.48824 -1.0176,-3.84619 -1.5475,-5.2399 l -0.9634,-2.534 -11.7786,7.15145 c -38.634,23.45687 -74.5513,34.71091 -124.1895,38.91257 -14.5402,1.23075 -58.2359,0.66344 -71.9142,-0.93369 -5.4419,-0.63542 -6.4542,-0.49723 -7.25,0.98972 -0.5545,1.03621 -0.9249,60.63835 -0.9249,148.84365 0,161.6262 0.4025,151.2052 -5.9673,154.4992 -2.3865,1.2341 -7.4633,1.5162 -27.233,1.5132 -22.3926,-0 -24.5527,-0.158 -27.5229,-1.969 z M 1424,1045.6452 c 0,-87.21053 0.3878,-144.17994 1.0365,-152.24998 1.8115,-22.53829 7.2373,-44.8067 16.1142,-66.13567 20.7842,-49.93942 66.8961,-95.01414 129.8493,-126.92865 14.9469,-7.57742 29.283
|
||
|
|
</svg>
|
||
|
|
<div>
|
||
|
|
<span class="brand">cameleer</span><span class="version">v3</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="sidebar-search">
|
||
|
|
<div class="sidebar-search-wrap">
|
||
|
|
<span class="search-icon">◇</span>
|
||
|
|
<input type="text" placeholder="Filter applications...">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="sidebar-section">Applications</div>
|
||
|
|
|
||
|
|
<div class="sidebar-items">
|
||
|
|
<div class="sidebar-item">
|
||
|
|
<span class="health health-live"></span>
|
||
|
|
<div class="item-info"><div class="item-name">All Applications</div></div>
|
||
|
|
<span class="item-count">4</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-divider"></div>
|
||
|
|
<div class="sidebar-item active">
|
||
|
|
<span class="health health-live"></span>
|
||
|
|
<div class="item-info"><div class="item-name">order-service</div><div class="item-meta">2 agents</div></div>
|
||
|
|
<span class="item-count">1,847</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-item">
|
||
|
|
<span class="health health-live"></span>
|
||
|
|
<div class="item-info"><div class="item-name">payment-gateway</div><div class="item-meta">2 agents</div></div>
|
||
|
|
<span class="item-count">923</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-item">
|
||
|
|
<span class="health health-live"></span>
|
||
|
|
<div class="item-info"><div class="item-name">shipment-tracker</div><div class="item-meta">2 agents</div></div>
|
||
|
|
<span class="item-count">471</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-item">
|
||
|
|
<span class="health health-stale"></span>
|
||
|
|
<div class="item-info"><div class="item-name">notification-hub</div><div class="item-meta">1 agent</div></div>
|
||
|
|
<span class="item-count">128</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-divider"></div>
|
||
|
|
<div class="sidebar-section">Routes</div>
|
||
|
|
<div class="sidebar-item" style="padding-left: 22px;">
|
||
|
|
<span style="color: var(--sidebar-muted); font-size: 10px;">▸</span>
|
||
|
|
<div class="item-info"><div class="item-name">order-intake</div></div>
|
||
|
|
<span class="item-count">892</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-item" style="padding-left: 22px;">
|
||
|
|
<span style="color: var(--sidebar-muted); font-size: 10px;">▸</span>
|
||
|
|
<div class="item-info"><div class="item-name">order-enrichment</div></div>
|
||
|
|
<span class="item-count">541</span>
|
||
|
|
</div>
|
||
|
|
<div class="sidebar-item" style="padding-left: 22px;">
|
||
|
|
<span style="color: var(--sidebar-muted); font-size: 10px;">▸</span>
|
||
|
|
<div class="item-info"><div class="item-name">payment-process</div></div>
|
||
|
|
<span class="item-count">414</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Agent health -->
|
||
|
|
<div class="sidebar-agents-header">
|
||
|
|
<span>Agents</span>
|
||
|
|
<span class="sidebar-agent-badge">4/4 live</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div style="padding: 0 0 6px; overflow-y: auto; max-height: 180px;">
|
||
|
|
<div class="agent-item">
|
||
|
|
<span class="agent-dot health-live"></span>
|
||
|
|
<div class="agent-info"><div class="agent-name">prod-1</div><div class="agent-detail">order-service v3.2.1</div></div>
|
||
|
|
<div class="agent-stats-col"><div class="agent-tps">14.2/s</div><div>12s ago</div></div>
|
||
|
|
</div>
|
||
|
|
<div class="agent-item">
|
||
|
|
<span class="agent-dot health-live"></span>
|
||
|
|
<div class="agent-info"><div class="agent-name">prod-2</div><div class="agent-detail">payment-svc v3.2.1</div></div>
|
||
|
|
<div class="agent-stats-col"><div class="agent-tps">11.8/s</div><div style="color: var(--error);">3 err/h</div></div>
|
||
|
|
</div>
|
||
|
|
<div class="agent-item">
|
||
|
|
<span class="agent-dot health-live"></span>
|
||
|
|
<div class="agent-info"><div class="agent-name">prod-3</div><div class="agent-detail">shipment-svc v3.2.0</div></div>
|
||
|
|
<div class="agent-stats-col"><div class="agent-tps">12.1/s</div><div>5s ago</div></div>
|
||
|
|
</div>
|
||
|
|
<div class="agent-item">
|
||
|
|
<span class="agent-dot health-live"></span>
|
||
|
|
<div class="agent-info"><div class="agent-name">prod-4</div><div class="agent-detail">shipment-svc v3.2.0</div></div>
|
||
|
|
<div class="agent-stats-col"><div class="agent-tps">9.1/s</div><div>3s ago</div></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="sidebar-bottom">
|
||
|
|
<div class="sidebar-item"><span style="font-size: 13px; width: 18px; text-align: center;">⚙</span><div class="item-info"><div class="item-name">Admin</div></div></div>
|
||
|
|
<div class="sidebar-item"><span style="font-size: 13px; width: 18px; text-align: center;">☰</span><div class="item-info"><div class="item-name">API Docs</div></div></div>
|
||
|
|
</div>
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
<!-- MAIN CONTENT -->
|
||
|
|
<div class="main">
|
||
|
|
<div class="topbar">
|
||
|
|
<div class="topbar-breadcrumb">
|
||
|
|
<span>Applications</span>
|
||
|
|
<span class="crumb-sep">/</span>
|
||
|
|
<span class="crumb-active">order-service</span>
|
||
|
|
</div>
|
||
|
|
<div class="topbar-search">
|
||
|
|
<span style="font-size: 12px; color: var(--text-muted);">🔎</span>
|
||
|
|
<span>Search by Order ID, route, error...</span>
|
||
|
|
<span class="topbar-kbd">Ctrl+K</span>
|
||
|
|
</div>
|
||
|
|
<div class="topbar-right">
|
||
|
|
<span class="topbar-env">PRODUCTION</span>
|
||
|
|
<span class="topbar-shift">Shift: Day (06:00-18:00)</span>
|
||
|
|
<div class="topbar-user">
|
||
|
|
<span>hendrik</span>
|
||
|
|
<div class="topbar-avatar">H</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="content-wrap">
|
||
|
|
<div class="content">
|
||
|
|
|
||
|
|
<!-- Health strip -->
|
||
|
|
<div class="health-strip animate-in">
|
||
|
|
<div class="stat-card card-amber">
|
||
|
|
<div class="stat-label">Executions (shift)</div>
|
||
|
|
<div class="stat-value-row"><span class="stat-value">3,241</span><span class="stat-trend trend-up-good">+12%</span></div>
|
||
|
|
<div class="stat-detail"><strong>97.1%</strong> success since 06:00</div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-card card-green">
|
||
|
|
<div class="stat-label">Success Rate</div>
|
||
|
|
<div class="stat-value-row"><span class="stat-value val-green">97.1%</span><span class="stat-trend trend-down-bad">-0.4%</span></div>
|
||
|
|
<div class="stat-detail">3,147 ok / 56 warn / 38 error</div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-card card-error has-errors">
|
||
|
|
<div class="stat-label">Errors (shift)</div>
|
||
|
|
<div class="stat-value-row"><span class="stat-value val-error">38</span><span class="stat-trend trend-up-bad">+5</span></div>
|
||
|
|
<div class="stat-detail"><strong>23</strong> overnight · <strong>15</strong> since 06:00</div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-card card-teal">
|
||
|
|
<div class="stat-label">Throughput</div>
|
||
|
|
<div class="stat-value-row"><span class="stat-value">47.2</span><span class="stat-unit">msg/s</span><span class="stat-trend trend-flat">↔</span></div>
|
||
|
|
<div class="stat-detail">Capacity: 120 msg/s · <strong>39%</strong></div>
|
||
|
|
</div>
|
||
|
|
<div class="stat-card card-warn">
|
||
|
|
<div class="stat-label">Latency p99</div>
|
||
|
|
<div class="stat-value-row"><span class="stat-value val-warn">287</span><span class="stat-unit">ms</span><span class="stat-trend trend-up-bad">+23ms</span></div>
|
||
|
|
<div class="stat-detail">SLA: <300ms · <strong style="color: var(--warning);">CLOSE</strong></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Filter bar -->
|
||
|
|
<div class="filter-section animate-in delay-1">
|
||
|
|
<div class="filter-row">
|
||
|
|
<div class="filter-input-wrap">
|
||
|
|
<span class="fi-icon">🔎</span>
|
||
|
|
<input class="filter-input" type="text" placeholder="Search by Order ID, correlation ID, error message...">
|
||
|
|
</div>
|
||
|
|
<div class="filter-sep"></div>
|
||
|
|
<div class="filter-group">
|
||
|
|
<span class="filter-label">Status</span>
|
||
|
|
<span class="filter-pill active">All <span class="pill-count">3,241</span></span>
|
||
|
|
<span class="filter-pill"><span class="pill-dot" style="background: var(--success);"></span> OK <span class="pill-count">3,147</span></span>
|
||
|
|
<span class="filter-pill"><span class="pill-dot" style="background: var(--warning);"></span> Warn <span class="pill-count">56</span></span>
|
||
|
|
<span class="filter-pill"><span class="pill-dot" style="background: var(--error);"></span> Error <span class="pill-count">38</span></span>
|
||
|
|
<span class="filter-pill"><span class="pill-dot" style="background: var(--running);"></span> Running <span class="pill-count">9</span></span>
|
||
|
|
</div>
|
||
|
|
<div class="filter-sep"></div>
|
||
|
|
<div class="filter-group">
|
||
|
|
<span class="filter-label">Time</span>
|
||
|
|
<span class="filter-pill">15m</span>
|
||
|
|
<span class="filter-pill">1h</span>
|
||
|
|
<span class="filter-pill active">Shift</span>
|
||
|
|
<span class="filter-pill">24h</span>
|
||
|
|
<span class="filter-pill">7d</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="active-filters">
|
||
|
|
<span class="filter-tag">time: since 06:00 (shift) <button class="filter-tag-remove">×</button></span>
|
||
|
|
<span class="filter-tag">app: order-service <button class="filter-tag-remove">×</button></span>
|
||
|
|
<span class="filter-tag">sort: newest first <button class="filter-tag-remove">×</button></span>
|
||
|
|
<button class="clear-all">Clear all</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Execution table -->
|
||
|
|
<div class="table-section animate-in delay-2">
|
||
|
|
<div class="table-header">
|
||
|
|
<span class="table-title">Recent Executions</span>
|
||
|
|
<div class="table-right">
|
||
|
|
<span class="table-meta">Showing 1-20 of 3,241</span>
|
||
|
|
<button class="live-btn"><span class="live-dot"></span> LIVE</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="table-scroll">
|
||
|
|
<table>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th style="width: 85px">Status</th>
|
||
|
|
<th>Route</th>
|
||
|
|
<th>Order ID</th>
|
||
|
|
<th>Customer</th>
|
||
|
|
<th class="sorted">Started <span class="sort-arrow">▼</span></th>
|
||
|
|
<th>Duration</th>
|
||
|
|
<th>Agent</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
<tr class="row-success">
|
||
|
|
<td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td>
|
||
|
|
<td><div class="route-name">order-intake</div><div class="route-group">order-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-92184</div><div class="biz-id-secondary">SAP-DE</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-44210</span></td>
|
||
|
|
<td><span class="time-relative">2 min ago</span><span class="time-absolute">09:12:04</span></td>
|
||
|
|
<td><span class="duration dur-fast">87ms</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td>
|
||
|
|
</tr>
|
||
|
|
<tr class="row-success">
|
||
|
|
<td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td>
|
||
|
|
<td><div class="route-name">payment-validate</div><div class="route-group">payment-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-92183</div><div class="biz-id-secondary">WEB-EU</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-18773</span></td>
|
||
|
|
<td><span class="time-relative">3 min ago</span><span class="time-absolute">09:11:22</span></td>
|
||
|
|
<td><span class="duration dur-normal">164ms</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-2</span></td>
|
||
|
|
</tr>
|
||
|
|
<tr class="row-running">
|
||
|
|
<td><span class="status-badge status-running"><span class="status-dot" style="animation: pulse 1.5s ease-in-out infinite;"></span>RUN</span></td>
|
||
|
|
<td><div class="route-name">order-enrichment</div><div class="route-group">order-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-92185</div><div class="biz-id-secondary">EDI-US</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-67501</span></td>
|
||
|
|
<td><span class="time-relative">30s ago</span><span class="time-absolute">09:13:44</span></td>
|
||
|
|
<td><span class="duration" style="color: var(--running);">~30s</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td>
|
||
|
|
</tr>
|
||
|
|
<tr class="row-warning">
|
||
|
|
<td><span class="status-badge status-warning"><span class="status-dot"></span>WARN</span></td>
|
||
|
|
<td><div class="route-name">shipment-dispatch</div><div class="route-group">shipment-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-92180</div><div class="biz-id-secondary">SAP-DE</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-55019</span></td>
|
||
|
|
<td><span class="time-relative">5 min ago</span><span class="time-absolute">09:09:47</span></td>
|
||
|
|
<td><span class="duration dur-slow">248ms</span> <span class="sla-tag">SLA</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-3</span></td>
|
||
|
|
</tr>
|
||
|
|
<!-- ERROR with inline preview -->
|
||
|
|
<tr class="row-error selected">
|
||
|
|
<td><span class="status-badge status-error"><span class="status-dot"></span>ERR</span></td>
|
||
|
|
<td><div class="route-name">payment-process</div><div class="route-group">payment-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-88421</div><div class="biz-id-secondary">WEB-EU</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-31094</span></td>
|
||
|
|
<td><span class="time-relative">8 min ago</span><span class="time-absolute">09:06:11</span></td>
|
||
|
|
<td><span class="duration dur-breach">412ms</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-2</span></td>
|
||
|
|
</tr>
|
||
|
|
<tr class="error-preview-row">
|
||
|
|
<td colspan="7">
|
||
|
|
<div class="error-preview">
|
||
|
|
<span class="error-preview-icon">⚠</span>
|
||
|
|
<div>
|
||
|
|
<div class="error-preview-text">org.apache.camel.CamelExecutionException: Payment gateway timeout after 5000ms — POST https://pay.provider.com/v2/charge returned HTTP 504. Retry exhausted (3/3).</div>
|
||
|
|
<div class="error-expand-hint">Click to view full stack trace and exchange snapshot</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<!-- ERROR 2 -->
|
||
|
|
<tr class="row-error">
|
||
|
|
<td><span class="status-badge status-error"><span class="status-dot"></span>ERR</span></td>
|
||
|
|
<td><div class="route-name">order-enrichment</div><div class="route-group">order-flow</div></td>
|
||
|
|
<td><div class="biz-id">OP-88419</div><div class="biz-id-secondary">EDI-US</div></td>
|
||
|
|
<td><span class="biz-id-secondary">CUST-72841</span></td>
|
||
|
|
<td><span class="time-relative">12 min ago</span><span class="time-absolute">09:02:38</span></td>
|
||
|
|
<td><span class="duration dur-breach">1,247ms</span></td>
|
||
|
|
<td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td>
|
||
|
|
</tr>
|
||
|
|
<tr class="error-preview-row">
|
||
|
|
<td colspan="7">
|
||
|
|
<div class="error-preview">
|
||
|
|
<span class="error-preview-icon">⚠</span>
|
||
|
|
<div>
|
||
|
|
<div class="error-preview-text">java.sql.SQLTransientConnectionException: HikariPool-1 - Connection not available, request timed out after 1000ms. (pool: 10, active: 10, idle: 0, waiting: 3)</div>
|
||
|
|
<div class="error-expand-hint">Click to view full stack trace and exchange snapshot</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">order-intake</div><div class="route-group">order-flow</div></td><td><div class="biz-id">OP-92179</div><div class="biz-id-secondary">WEB-EU</div></td><td><span class="biz-id-secondary">CUST-90123</span></td><td><span class="time-relative">14 min ago</span><span class="time-absolute">09:00:15</span></td><td><span class="duration dur-fast">62ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-3</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">payment-validate</div><div class="route-group">payment-flow</div></td><td><div class="biz-id">OP-92178</div><div class="biz-id-secondary">SAP-DE</div></td><td><span class="biz-id-secondary">CUST-44210</span></td><td><span class="time-relative">16 min ago</span><span class="time-absolute">08:58:33</span></td><td><span class="duration dur-normal">131ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">shipment-track</div><div class="route-group">shipment-flow</div></td><td><div class="biz-id">OP-92175</div><div class="biz-id-secondary">EDI-US</div></td><td><span class="biz-id-secondary">CUST-67892</span></td><td><span class="time-relative">21 min ago</span><span class="time-absolute">08:53:07</span></td><td><span class="duration dur-fast">94ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-4</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">order-intake</div><div class="route-group">order-flow</div></td><td><div class="biz-id">OP-92174</div><div class="biz-id-secondary">WEB-EU</div></td><td><span class="biz-id-secondary">CUST-15293</span></td><td><span class="time-relative">24 min ago</span><span class="time-absolute">08:50:41</span></td><td><span class="duration dur-fast">73ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">payment-process</div><div class="route-group">payment-flow</div></td><td><div class="biz-id">OP-92173</div><div class="biz-id-secondary">SAP-DE</div></td><td><span class="biz-id-secondary">CUST-88104</span></td><td><span class="time-relative">28 min ago</span><span class="time-absolute">08:46:19</span></td><td><span class="duration dur-normal">198ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-2</span></td></tr>
|
||
|
|
<tr class="row-warning"><td><span class="status-badge status-warning"><span class="status-dot"></span>WARN</span></td><td><div class="route-name">order-enrichment</div><div class="route-group">order-flow</div></td><td><div class="biz-id">OP-92170</div><div class="biz-id-secondary">EDI-US</div></td><td><span class="biz-id-secondary">CUST-50321</span></td><td><span class="time-relative">35 min ago</span><span class="time-absolute">08:39:52</span></td><td><span class="duration dur-slow">267ms</span> <span class="sla-tag">SLA</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">shipment-dispatch</div><div class="route-group">shipment-flow</div></td><td><div class="biz-id">OP-92168</div><div class="biz-id-secondary">WEB-EU</div></td><td><span class="biz-id-secondary">CUST-29104</span></td><td><span class="time-relative">42 min ago</span><span class="time-absolute">08:32:28</span></td><td><span class="duration dur-fast">55ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-3</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">order-intake</div><div class="route-group">order-flow</div></td><td><div class="biz-id">OP-92165</div><div class="biz-id-secondary">SAP-DE</div></td><td><span class="biz-id-secondary">CUST-77618</span></td><td><span class="time-relative">51 min ago</span><span class="time-absolute">08:23:14</span></td><td><span class="duration dur-fast">81ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-4</span></td></tr>
|
||
|
|
<tr class="row-error"><td><span class="status-badge status-error"><span class="status-dot"></span>ERR</span></td><td><div class="route-name">payment-process</div><div class="route-group">payment-flow</div></td><td><div class="biz-id">OP-91844</div><div class="biz-id-secondary">WEB-EU</div></td><td><span class="biz-id-secondary">CUST-10082</span></td><td><span class="time-relative">5 hours ago</span><span class="time-absolute">04:12:55</span></td><td><span class="duration dur-breach">timeout</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-2</span></td></tr>
|
||
|
|
<tr class="row-success"><td><span class="status-badge status-success"><span class="status-dot"></span>OK</span></td><td><div class="route-name">order-intake</div><div class="route-group">order-flow</div></td><td><div class="biz-id">OP-91840</div><div class="biz-id-secondary">EDI-US</div></td><td><span class="biz-id-secondary">CUST-38291</span></td><td><span class="time-relative">5 hours ago</span><span class="time-absolute">04:10:22</span></td><td><span class="duration dur-fast">78ms</span></td><td><span class="agent-badge"><span class="agent-badge-dot health-live"></span>prod-1</span></td></tr>
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
<div class="table-footer">
|
||
|
|
<span class="mono" style="font-size: 11px;">20 rows per page</span>
|
||
|
|
<div class="pagination">
|
||
|
|
<button class="page-btn active">1</button>
|
||
|
|
<button class="page-btn">2</button>
|
||
|
|
<button class="page-btn">3</button>
|
||
|
|
<button class="page-btn">...</button>
|
||
|
|
<button class="page-btn">162</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- Metrics panel -->
|
||
|
|
<div class="metrics-row animate-in delay-3">
|
||
|
|
<div class="metric-card">
|
||
|
|
<div class="metric-card-header">
|
||
|
|
<span class="metric-card-title">Throughput (1h)</span>
|
||
|
|
<span class="metric-card-value">47.2<span style="font-size:11px; font-weight:400; color: var(--text-muted)"> msg/s</span></span>
|
||
|
|
</div>
|
||
|
|
<div class="metric-chart">
|
||
|
|
<svg width="100%" height="100%" viewBox="0 0 300 65" preserveAspectRatio="none">
|
||
|
|
<line x1="0" y1="16" x2="300" y2="16" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="32" x2="300" y2="32" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="48" x2="300" y2="48" class="chart-grid-line"/>
|
||
|
|
<path d="M0,50 L25,47 50,43 75,45 100,40 125,37 150,39 175,35 200,33 225,35 250,37 275,34 300,33 L300,65 L0,65 Z" fill="#22D3EE" class="chart-area"/>
|
||
|
|
<path d="M0,50 L25,47 50,43 75,45 100,40 125,37 150,39 175,35 200,33 225,35 250,37 275,34 300,33" stroke="#22D3EE" class="chart-line"/>
|
||
|
|
<text x="0" y="63" class="chart-label">08:15</text>
|
||
|
|
<text x="145" y="63" class="chart-label">08:45</text>
|
||
|
|
<text x="282" y="63" class="chart-label">09:14</text>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="metric-card">
|
||
|
|
<div class="metric-card-header">
|
||
|
|
<span class="metric-card-title">Latency p99 (1h)</span>
|
||
|
|
<span class="metric-card-value" style="color: var(--warning);">287<span style="font-size:11px; font-weight:400; color: var(--text-muted)">ms</span> <span style="font-size:12px; color: var(--error);">↗</span></span>
|
||
|
|
</div>
|
||
|
|
<div class="metric-chart">
|
||
|
|
<svg width="100%" height="100%" viewBox="0 0 300 65" preserveAspectRatio="none">
|
||
|
|
<line x1="0" y1="16" x2="300" y2="16" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="32" x2="300" y2="32" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="48" x2="300" y2="48" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="10" x2="300" y2="10" class="sla-line"/>
|
||
|
|
<text x="4" y="8" class="sla-label-text">SLA 300ms</text>
|
||
|
|
<rect x="0" y="0" width="300" height="10" fill="rgba(244, 63, 94, 0.04)"/>
|
||
|
|
<path d="M0,42 L25,40 50,37 75,35 100,33 125,30 150,27 175,23 200,20 225,18 250,16 275,14 300,13 L300,65 L0,65 Z" fill="#F0B429" class="chart-area"/>
|
||
|
|
<path d="M0,42 L25,40 50,37 75,35 100,33 125,30 150,27 175,23 200,20 225,18 250,16 275,14 300,13" stroke="#F0B429" class="chart-line"/>
|
||
|
|
<path d="M0,52 L25,53 50,52 75,50 100,52 125,51 150,50 175,52 200,50 225,49 250,50 275,48 300,47" stroke="#22D3EE" stroke-width="1" opacity="0.4" fill="none" stroke-dasharray="4 3"/>
|
||
|
|
<text x="0" y="63" class="chart-label">08:15</text>
|
||
|
|
<text x="145" y="63" class="chart-label">08:45</text>
|
||
|
|
<text x="282" y="63" class="chart-label">09:14</text>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="metric-card">
|
||
|
|
<div class="metric-card-header">
|
||
|
|
<span class="metric-card-title">Error Rate (1h)</span>
|
||
|
|
<span class="metric-card-value" style="color: var(--error);">2.9<span style="font-size:11px; font-weight:400; color: var(--text-muted)">%</span> <span style="font-size:12px;">↗</span></span>
|
||
|
|
</div>
|
||
|
|
<div class="metric-chart">
|
||
|
|
<svg width="100%" height="100%" viewBox="0 0 300 65" preserveAspectRatio="none">
|
||
|
|
<line x1="0" y1="16" x2="300" y2="16" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="32" x2="300" y2="32" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="48" x2="300" y2="48" class="chart-grid-line"/>
|
||
|
|
<line x1="0" y1="16" x2="300" y2="16" class="sla-line"/>
|
||
|
|
<text x="4" y="14" class="sla-label-text">SLA 5%</text>
|
||
|
|
<rect x="2" y="54" width="18" height="11" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="24" y="56" width="18" height="9" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="46" y="58" width="18" height="7" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="68" y="55" width="18" height="10" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="90" y="52" width="18" height="13" rx="2" fill="rgba(244, 63, 94, 0.3)"/>
|
||
|
|
<rect x="112" y="56" width="18" height="9" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="134" y="59" width="18" height="6" rx="2" fill="rgba(244, 63, 94, 0.25)"/>
|
||
|
|
<rect x="156" y="50" width="18" height="15" rx="2" fill="rgba(244, 63, 94, 0.35)"/>
|
||
|
|
<rect x="178" y="45" width="18" height="20" rx="2" fill="rgba(244, 63, 94, 0.5)"/>
|
||
|
|
<rect x="200" y="42" width="18" height="23" rx="2" fill="rgba(244, 63, 94, 0.55)"/>
|
||
|
|
<rect x="222" y="38" width="18" height="27" rx="2" fill="rgba(244, 63, 94, 0.6)"/>
|
||
|
|
<rect x="244" y="36" width="18" height="29" rx="2" fill="rgba(244, 63, 94, 0.65)"/>
|
||
|
|
<rect x="266" y="34" width="18" height="31" rx="2" fill="rgba(244, 63, 94, 0.75)"/>
|
||
|
|
<text x="0" y="63" class="chart-label">08:15</text>
|
||
|
|
<text x="145" y="63" class="chart-label">08:45</text>
|
||
|
|
<text x="282" y="63" class="chart-label">09:14</text>
|
||
|
|
</svg>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</div><!-- /content -->
|
||
|
|
|
||
|
|
<!-- DETAIL PANEL -->
|
||
|
|
<div class="detail-panel open">
|
||
|
|
<div class="detail-header">
|
||
|
|
<div class="detail-breadcrumb">
|
||
|
|
<span>order-service</span>
|
||
|
|
<span class="bc-sep">▸</span>
|
||
|
|
<span>payment-process</span>
|
||
|
|
<span class="bc-sep">▸</span>
|
||
|
|
<span class="bc-current">OP-88421</span>
|
||
|
|
</div>
|
||
|
|
<button class="detail-close" title="Close (Esc)">×</button>
|
||
|
|
</div>
|
||
|
|
<div class="detail-tabs">
|
||
|
|
<button class="detail-tab active">Overview</button>
|
||
|
|
<button class="detail-tab">Processors</button>
|
||
|
|
<button class="detail-tab">Exchange</button>
|
||
|
|
<button class="detail-tab">Error</button>
|
||
|
|
</div>
|
||
|
|
<div class="detail-body">
|
||
|
|
<div class="detail-section">
|
||
|
|
<div class="detail-section-title">Execution Details</div>
|
||
|
|
<div class="detail-grid">
|
||
|
|
<span class="detail-key">Status</span>
|
||
|
|
<span class="detail-val"><span class="status-badge status-error" style="font-size:10px"><span class="status-dot"></span>FAILED</span></span>
|
||
|
|
<span class="detail-key">Order ID</span>
|
||
|
|
<span class="detail-val" style="color: var(--cyan);">OP-88421</span>
|
||
|
|
<span class="detail-key">Customer</span>
|
||
|
|
<span class="detail-val">CUST-31094</span>
|
||
|
|
<span class="detail-key">Source</span>
|
||
|
|
<span class="detail-val">WEB-EU</span>
|
||
|
|
<span class="detail-key">Correlation ID</span>
|
||
|
|
<span class="detail-val">c7e2a1f0-9b3d-4e1a-8f2c-5d6e7f8a9b0c</span>
|
||
|
|
<span class="detail-key">Application</span>
|
||
|
|
<span class="detail-val">order-service</span>
|
||
|
|
<span class="detail-key">Route</span>
|
||
|
|
<span class="detail-val link">payment-process</span>
|
||
|
|
<span class="detail-key">Agent</span>
|
||
|
|
<span class="detail-val">prod-2</span>
|
||
|
|
<span class="detail-key">Started</span>
|
||
|
|
<span class="detail-val">2026-03-17T09:06:11.341Z</span>
|
||
|
|
<span class="detail-key">Duration</span>
|
||
|
|
<span class="detail-val error-text">412ms</span>
|
||
|
|
<span class="detail-key">Processors</span>
|
||
|
|
<span class="detail-val">7 (5 ok, 1 failed, 1 skipped)</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="detail-section">
|
||
|
|
<div class="detail-section-title">Processor Timeline</div>
|
||
|
|
<div class="processor-timeline">
|
||
|
|
<div class="proc-row"><span class="proc-name">unmarshal</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-ok" style="left:0;width:8%">12ms</div></div><span class="proc-dur">12ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name">validate</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-ok" style="left:8%;width:5%">8ms</div></div><span class="proc-dur">8ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name">enrich(inventory)</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-slow" style="left:13%;width:20%">85ms</div></div><span class="proc-dur">85ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name">transform</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-ok" style="left:33%;width:3%">5ms</div></div><span class="proc-dur">5ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name">to(payment-api)</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-fail" style="left:36%;width:58%">280ms</div></div><span class="proc-dur">280ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name">log</span><div class="proc-bar-bg"><div class="proc-bar-fill proc-ok" style="left:94%;width:2%">2ms</div></div><span class="proc-dur">2ms</span></div>
|
||
|
|
<div class="proc-row"><span class="proc-name" style="color: var(--text-faint);">marshal</span><div class="proc-bar-bg" style="opacity:0.3"></div><span class="proc-dur" style="color: var(--text-faint);">skip</span></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="detail-section">
|
||
|
|
<div class="detail-section-title">Error</div>
|
||
|
|
<div class="error-block">
|
||
|
|
<div class="error-class">org.apache.camel.http.base.HttpOperationFailedException</div>
|
||
|
|
<div class="error-message-detail">
|
||
|
|
HTTP operation failed invoking https://pay.provider.com/v2/charge<br>
|
||
|
|
with statusCode: 504 Gateway Timeout<br>
|
||
|
|
Retry exhausted (3/3 attempts)<br>
|
||
|
|
at processor: to(payment-api) [step 5/7]
|
||
|
|
</div>
|
||
|
|
<button class="error-expand">▸ Show full stack trace</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="detail-actions">
|
||
|
|
<button class="action-btn primary">View Route Diagram</button>
|
||
|
|
<button class="action-btn secondary">Copy ID</button>
|
||
|
|
<button class="action-btn secondary">Re-process</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="shortcuts-bar">
|
||
|
|
<div class="shortcut-hint"><kbd>Ctrl</kbd>+<kbd>K</kbd> Search</div>
|
||
|
|
<div class="shortcut-hint"><kbd>↑</kbd><kbd>↓</kbd> Navigate</div>
|
||
|
|
<div class="shortcut-hint"><kbd>Enter</kbd> Detail</div>
|
||
|
|
<div class="shortcut-hint"><kbd>Esc</kbd> Close</div>
|
||
|
|
<div class="shortcut-hint"><kbd>?</kbd> Shortcuts</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
</body>
|
||
|
|
</html>
|