Rename Java packages from com.cameleer3 to com.cameleer, module directories from cameleer3-* to cameleer-*, and all references throughout workflows, Dockerfiles, docs, migrations, and pom.xml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1946 lines
67 KiB
HTML
1946 lines
67 KiB
HTML
<!--
|
|
============================================================================
|
|
CAMELEER v3 — Exchange / Message Inspector (Light Theme)
|
|
============================================================================
|
|
|
|
DESIGN NOTES
|
|
============
|
|
|
|
PURPOSE:
|
|
This is the deepest drill-down view in Cameleer — the Exchange Inspector.
|
|
A developer arrives here after clicking a failed execution row in the
|
|
Operations Dashboard (mock-v2). The page answers the #1 question:
|
|
"What happened to my message as it flowed through the route?"
|
|
|
|
LAYOUT:
|
|
Two-region layout inside the standard sidebar + main shell:
|
|
1. Exchange Header Card — identity, status, timing at a glance
|
|
2. Processor Timeline — Gantt-style horizontal bars showing where time was spent
|
|
3. Processor Detail Panel — split IN / OUT columns with headers, body, diffs
|
|
4. Properties & Correlation — collapsible bottom section
|
|
|
|
DATA SCENARIO:
|
|
Order OP-88421 entered via direct:order-intake, passed validation, DB insert,
|
|
priority check, then FAILED at http:payment-api/charge with a 503 timeout
|
|
after 2m 18s. The payment-api processor consumed 94% of total wall time.
|
|
|
|
DESIGN SYSTEM:
|
|
Inherits 100% from mock-v2-light.html — same CSS variables, fonts, sidebar,
|
|
topbar. No new colors or typefaces introduced.
|
|
|
|
OPTIMIZED FOR: 1920x1080, Chrome/Firefox/Edge
|
|
|
|
============================================================================
|
|
-->
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=1920">
|
|
<title>Cameleer — Exchange OP-88421</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 (identical to mock-v2)
|
|
========================================================================== */
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
:root {
|
|
/* Surface palette (warm parchment) */
|
|
--bg-body: #F5F2ED;
|
|
--bg-surface: #FFFFFF;
|
|
--bg-raised: #FAF8F5;
|
|
--bg-inset: #F0EDE8;
|
|
--bg-hover: #F5F0EA;
|
|
|
|
/* Sidebar (warm charcoal) */
|
|
--sidebar-bg: #2C2520;
|
|
--sidebar-hover: #3A322C;
|
|
--sidebar-active: #4A3F38;
|
|
--sidebar-text: #BFB5A8;
|
|
--sidebar-muted: #7A6F63;
|
|
|
|
/* Text */
|
|
--text-primary: #1A1612;
|
|
--text-secondary: #5C5347;
|
|
--text-muted: #9C9184;
|
|
--text-faint: #C4BAB0;
|
|
|
|
/* Borders */
|
|
--border: #E4DFD8;
|
|
--border-subtle: #EDE9E3;
|
|
|
|
/* Brand accent (amber-gold) */
|
|
--amber: #C6820E;
|
|
--amber-light: #F0D9A8;
|
|
--amber-bg: #FDF6E9;
|
|
--amber-deep: #8B5A06;
|
|
|
|
/* Status colors (warm) */
|
|
--success: #3D7C47;
|
|
--success-bg: #EFF7F0;
|
|
--success-border: #C2DFC6;
|
|
--warning: #C27516;
|
|
--warning-bg: #FEF5E7;
|
|
--warning-border: #F0D9A8;
|
|
--error: #C0392B;
|
|
--error-bg: #FDF0EE;
|
|
--error-border: #F0C4BE;
|
|
--running: #1A7F8E;
|
|
--running-bg: #E8F5F7;
|
|
--running-border: #B0DDE4;
|
|
|
|
/* Typography */
|
|
--font-body: 'DM Sans', system-ui, -apple-system, sans-serif;
|
|
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
|
|
|
/* Spacing & Radii */
|
|
--radius-sm: 5px;
|
|
--radius-md: 8px;
|
|
--radius-lg: 12px;
|
|
|
|
/* Shadows */
|
|
--shadow-sm: 0 1px 2px rgba(44, 37, 32, 0.06);
|
|
--shadow-md: 0 2px 8px rgba(44, 37, 32, 0.08);
|
|
--shadow-lg: 0 4px 16px rgba(44, 37, 32, 0.10);
|
|
--shadow-card: 0 1px 3px rgba(44, 37, 32, 0.04), 0 0 0 1px rgba(44, 37, 32, 0.04);
|
|
}
|
|
|
|
html { font-size: 14px; }
|
|
body {
|
|
font-family: var(--font-body);
|
|
background: var(--bg-body);
|
|
color: var(--text-primary);
|
|
line-height: 1.5;
|
|
min-height: 100vh;
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
|
|
::-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-faint); }
|
|
|
|
/* ==========================================================================
|
|
ANIMATIONS
|
|
========================================================================== */
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
@keyframes errorPulse {
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(192, 57, 43, 0.2); }
|
|
50% { box-shadow: 0 0 0 4px rgba(192, 57, 43, 0); }
|
|
}
|
|
.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; }
|
|
.delay-5 { animation-delay: 0.20s; }
|
|
|
|
/* ==========================================================================
|
|
LAYOUT
|
|
========================================================================== */
|
|
.app {
|
|
display: flex;
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
SIDEBAR (220px, warm charcoal — identical to mock-v2)
|
|
========================================================================== */
|
|
.sidebar {
|
|
width: 220px;
|
|
flex-shrink: 0;
|
|
background: var(--sidebar-bg);
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.sidebar-logo {
|
|
padding: 16px 18px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
border-bottom: 1px solid rgba(255,255,255,0.06);
|
|
}
|
|
|
|
.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: rgba(255,255,255,0.06);
|
|
border: 1px solid rgba(255,255,255,0.08);
|
|
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: rgba(198, 130, 14, 0.4); }
|
|
|
|
.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: #E8DFD4; }
|
|
.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: #5DB866; box-shadow: 0 0 6px rgba(93, 184, 102, 0.4); }
|
|
.health-stale { background: var(--warning); }
|
|
|
|
.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: rgba(255,255,255,0.06);
|
|
padding: 1px 6px;
|
|
border-radius: 10px;
|
|
}
|
|
.sidebar-item.active .item-count { background: rgba(198, 130, 14, 0.2); color: var(--amber-light); }
|
|
|
|
.sidebar-divider {
|
|
height: 1px;
|
|
background: rgba(255,255,255,0.06);
|
|
margin: 6px 12px;
|
|
}
|
|
|
|
.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: rgba(93, 184, 102, 0.15);
|
|
color: #5DB866;
|
|
}
|
|
|
|
.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; }
|
|
.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 rgba(255,255,255,0.06);
|
|
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: var(--bg-surface);
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
.topbar-breadcrumb {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.topbar-breadcrumb .crumb-link {
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
transition: color 0.12s;
|
|
}
|
|
.topbar-breadcrumb .crumb-link:hover { color: var(--amber); }
|
|
.topbar-breadcrumb .crumb-active { color: var(--text-primary); font-weight: 600; }
|
|
.topbar-breadcrumb .crumb-sep { color: var(--text-faint); font-size: 11px; }
|
|
|
|
.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-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 var(--amber-light);
|
|
}
|
|
|
|
/* Content scroll container */
|
|
.content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 20px 24px 40px;
|
|
min-width: 0;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
STATUS BADGES (reused from mock-v2)
|
|
========================================================================== */
|
|
.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-error { background: var(--error-bg); color: var(--error); border: 1px solid var(--error-border); }
|
|
|
|
.status-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
|
|
|
|
/* ==========================================================================
|
|
EXCHANGE HEADER CARD
|
|
========================================================================== */
|
|
.exchange-header {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
padding: 18px 22px;
|
|
box-shadow: var(--shadow-card);
|
|
margin-bottom: 16px;
|
|
border-left: 4px solid var(--error);
|
|
}
|
|
|
|
.exchange-header-top {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.exchange-title-area {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.exchange-route {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.exchange-status-lg {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 4px 14px;
|
|
border-radius: 16px;
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: 0.3px;
|
|
text-transform: uppercase;
|
|
background: var(--error-bg);
|
|
color: var(--error);
|
|
border: 1px solid var(--error-border);
|
|
animation: errorPulse 2.5s ease-in-out infinite;
|
|
}
|
|
|
|
.exchange-status-lg .status-dot { width: 6px; height: 6px; }
|
|
|
|
.exchange-actions {
|
|
display: flex;
|
|
gap: 6px;
|
|
}
|
|
|
|
.action-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 5px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-surface);
|
|
color: var(--text-secondary);
|
|
font-family: var(--font-body);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.12s;
|
|
}
|
|
|
|
.action-btn:hover {
|
|
border-color: var(--text-faint);
|
|
background: var(--bg-raised);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.action-btn.primary {
|
|
background: var(--amber-bg);
|
|
border-color: var(--amber-light);
|
|
color: var(--amber-deep);
|
|
}
|
|
|
|
.action-btn.primary:hover {
|
|
background: var(--amber-light);
|
|
}
|
|
|
|
.exchange-meta-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 0;
|
|
border-top: 1px solid var(--border-subtle);
|
|
padding-top: 14px;
|
|
}
|
|
|
|
.meta-item {
|
|
padding: 0 16px;
|
|
border-right: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.meta-item:first-child { padding-left: 0; }
|
|
.meta-item:last-child { border-right: none; }
|
|
|
|
.meta-label {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.6px;
|
|
color: var(--text-muted);
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
.meta-value {
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.meta-value.mono-sm {
|
|
font-size: 11px;
|
|
color: var(--text-secondary);
|
|
word-break: break-all;
|
|
}
|
|
|
|
.meta-value .biz-tag {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 1px 8px;
|
|
border-radius: 10px;
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
margin-right: 6px;
|
|
}
|
|
|
|
.biz-tag.order { background: var(--running-bg); color: var(--running); border: 1px solid var(--running-border); }
|
|
.biz-tag.customer { background: var(--amber-bg); color: var(--amber-deep); border: 1px solid var(--amber-light); }
|
|
|
|
.meta-value .duration-lg {
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
color: var(--error);
|
|
}
|
|
|
|
.meta-value .duration-label {
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
font-weight: 400;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.meta-sub {
|
|
font-size: 10px;
|
|
color: var(--text-muted);
|
|
font-family: var(--font-mono);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
PROCESSOR TIMELINE (Gantt-style)
|
|
========================================================================== */
|
|
.timeline-section {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-card);
|
|
margin-bottom: 16px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.timeline-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 18px;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.timeline-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.timeline-title .proc-count {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
padding: 1px 8px;
|
|
border-radius: 10px;
|
|
background: var(--bg-inset);
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.timeline-legend {
|
|
display: flex;
|
|
gap: 14px;
|
|
font-size: 11px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.legend-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.legend-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.legend-dot.l-success { background: var(--success); }
|
|
.legend-dot.l-error { background: var(--error); }
|
|
.legend-dot.l-slow { background: var(--warning); }
|
|
|
|
.timeline-body {
|
|
padding: 6px 0;
|
|
}
|
|
|
|
.timeline-row {
|
|
display: grid;
|
|
grid-template-columns: 260px 1fr 80px 32px;
|
|
align-items: center;
|
|
padding: 6px 18px;
|
|
gap: 12px;
|
|
cursor: pointer;
|
|
transition: background 0.08s;
|
|
border-left: 3px solid transparent;
|
|
}
|
|
|
|
.timeline-row:hover { background: var(--bg-hover); }
|
|
.timeline-row.selected { background: var(--amber-bg); border-left-color: var(--amber); }
|
|
.timeline-row.row-error { border-left-color: var(--error); }
|
|
.timeline-row.row-error.selected { border-left-color: var(--error); background: var(--error-bg); }
|
|
|
|
.proc-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 12px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.proc-index {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
color: var(--text-faint);
|
|
width: 18px;
|
|
text-align: right;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.proc-type {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
padding: 1px 6px;
|
|
border-radius: 3px;
|
|
background: var(--bg-inset);
|
|
color: var(--text-muted);
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.proc-type.type-from { background: var(--running-bg); color: var(--running); }
|
|
.proc-type.type-to { background: var(--amber-bg); color: var(--amber-deep); }
|
|
.proc-type.type-process { background: var(--success-bg); color: var(--success); }
|
|
.proc-type.type-choice { background: #F3EFF8; color: #6B4FA0; }
|
|
|
|
.proc-name {
|
|
font-weight: 500;
|
|
color: var(--text-primary);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.proc-bar-area {
|
|
position: relative;
|
|
height: 20px;
|
|
background: var(--bg-inset);
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.proc-bar {
|
|
height: 100%;
|
|
border-radius: 3px;
|
|
min-width: 3px;
|
|
transition: width 0.3s ease;
|
|
position: relative;
|
|
}
|
|
|
|
.proc-bar.bar-success { background: linear-gradient(90deg, var(--success), #5DB866); }
|
|
.proc-bar.bar-error { background: linear-gradient(90deg, var(--error), #E74C3C); }
|
|
.proc-bar.bar-slow { background: linear-gradient(90deg, var(--warning), #E8A838); }
|
|
|
|
.proc-bar .bar-pct {
|
|
position: absolute;
|
|
right: 6px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
font-weight: 600;
|
|
color: white;
|
|
text-shadow: 0 1px 2px rgba(0,0,0,0.3);
|
|
}
|
|
|
|
.proc-duration {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
color: var(--text-secondary);
|
|
text-align: right;
|
|
}
|
|
|
|
.proc-duration.dur-error { color: var(--error); font-weight: 600; }
|
|
|
|
.proc-status-icon {
|
|
font-size: 14px;
|
|
text-align: center;
|
|
}
|
|
|
|
.proc-status-icon.icon-ok { color: var(--success); }
|
|
.proc-status-icon.icon-fail { color: var(--error); }
|
|
|
|
/* Bottleneck callout */
|
|
.bottleneck-callout {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin: 4px 18px 10px;
|
|
padding: 8px 14px;
|
|
background: var(--error-bg);
|
|
border: 1px solid var(--error-border);
|
|
border-left: 3px solid var(--error);
|
|
border-radius: var(--radius-sm);
|
|
font-size: 12px;
|
|
color: var(--error);
|
|
}
|
|
|
|
.bottleneck-callout strong { font-weight: 700; }
|
|
.bottleneck-pct {
|
|
font-family: var(--font-mono);
|
|
font-weight: 700;
|
|
font-size: 14px;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
PROCESSOR DETAIL PANEL (split IN / OUT)
|
|
========================================================================== */
|
|
.detail-split {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 16px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.detail-panel {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-card);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.detail-panel.panel-error {
|
|
border-color: var(--error-border);
|
|
}
|
|
|
|
.detail-panel-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 10px 16px;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
background: var(--bg-raised);
|
|
}
|
|
|
|
.detail-panel.panel-error .detail-panel-header {
|
|
background: var(--error-bg);
|
|
border-bottom-color: var(--error-border);
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.panel-title .arrow-in { color: var(--success); }
|
|
.panel-title .arrow-out { color: var(--error); }
|
|
|
|
.panel-tag {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
padding: 1px 6px;
|
|
border-radius: 8px;
|
|
background: var(--bg-inset);
|
|
color: var(--text-muted);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.detail-panel-body {
|
|
padding: 14px 16px;
|
|
}
|
|
|
|
/* Headers section */
|
|
.headers-section { margin-bottom: 16px; }
|
|
|
|
.section-label {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.6px;
|
|
color: var(--text-muted);
|
|
margin-bottom: 8px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
|
|
.section-label .count {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
padding: 0 5px;
|
|
border-radius: 8px;
|
|
background: var(--bg-inset);
|
|
color: var(--text-faint);
|
|
}
|
|
|
|
.header-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 3px;
|
|
}
|
|
|
|
.header-row {
|
|
display: grid;
|
|
grid-template-columns: 180px 1fr;
|
|
gap: 8px;
|
|
padding: 3px 8px;
|
|
border-radius: 3px;
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
transition: background 0.08s;
|
|
}
|
|
|
|
.header-row:hover { background: var(--bg-hover); }
|
|
|
|
.header-row.h-added { background: var(--success-bg); }
|
|
.header-row.h-removed { background: var(--error-bg); text-decoration: line-through; }
|
|
|
|
.header-key {
|
|
color: var(--text-secondary);
|
|
font-weight: 500;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.header-value {
|
|
color: var(--text-primary);
|
|
word-break: break-all;
|
|
}
|
|
|
|
.header-row.h-added .header-key { color: var(--success); }
|
|
.header-row.h-added .header-value { color: var(--success); }
|
|
.header-row.h-removed .header-key { color: var(--error); opacity: 0.7; }
|
|
.header-row.h-removed .header-value { color: var(--error); opacity: 0.7; }
|
|
|
|
.diff-badge {
|
|
font-family: var(--font-mono);
|
|
font-size: 9px;
|
|
font-weight: 600;
|
|
padding: 0 5px;
|
|
border-radius: 8px;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.diff-badge.added { background: var(--success-bg); color: var(--success); border: 1px solid var(--success-border); }
|
|
.diff-badge.removed { background: var(--error-bg); color: var(--error); border: 1px solid var(--error-border); }
|
|
|
|
/* Body section */
|
|
.body-section { margin-bottom: 0; }
|
|
|
|
.body-toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.body-size {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
color: var(--text-muted);
|
|
}
|
|
|
|
.body-format-tag {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
padding: 1px 6px;
|
|
border-radius: 8px;
|
|
background: var(--running-bg);
|
|
color: var(--running);
|
|
border: 1px solid var(--running-border);
|
|
}
|
|
|
|
.body-toggle {
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
padding: 2px 8px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--bg-surface);
|
|
color: var(--text-muted);
|
|
cursor: pointer;
|
|
transition: all 0.12s;
|
|
margin-left: auto;
|
|
}
|
|
|
|
.body-toggle:hover { border-color: var(--text-faint); color: var(--text-secondary); }
|
|
.body-toggle.active { background: var(--amber-bg); border-color: var(--amber-light); color: var(--amber-deep); }
|
|
|
|
.body-content {
|
|
background: var(--bg-inset);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-sm);
|
|
padding: 12px;
|
|
overflow-x: auto;
|
|
max-height: 280px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.body-content pre {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
line-height: 1.6;
|
|
color: var(--text-primary);
|
|
margin: 0;
|
|
white-space: pre;
|
|
}
|
|
|
|
/* JSON syntax highlighting */
|
|
.json-key { color: #6B4FA0; }
|
|
.json-str { color: var(--success); }
|
|
.json-num { color: var(--amber-deep); }
|
|
.json-bool { color: var(--running); }
|
|
.json-null { color: var(--text-muted); }
|
|
.json-brace { color: var(--text-secondary); }
|
|
|
|
/* ==========================================================================
|
|
ERROR DISPLAY
|
|
========================================================================== */
|
|
.error-section {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.error-badge-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.error-class {
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: var(--error);
|
|
}
|
|
|
|
.error-http-badge {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
padding: 2px 10px;
|
|
border-radius: 10px;
|
|
background: var(--error-bg);
|
|
color: var(--error);
|
|
border: 1px solid var(--error-border);
|
|
}
|
|
|
|
.error-message-box {
|
|
background: var(--error-bg);
|
|
border: 1px solid var(--error-border);
|
|
border-left: 3px solid var(--error);
|
|
border-radius: var(--radius-sm);
|
|
padding: 10px 14px;
|
|
margin-bottom: 12px;
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
color: var(--error);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.error-detail-grid {
|
|
display: grid;
|
|
grid-template-columns: 100px 1fr;
|
|
gap: 4px 12px;
|
|
margin-bottom: 14px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.error-detail-key {
|
|
font-weight: 600;
|
|
color: var(--text-muted);
|
|
text-align: right;
|
|
}
|
|
|
|
.error-detail-val {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
color: var(--text-primary);
|
|
word-break: break-all;
|
|
}
|
|
|
|
.stack-section { }
|
|
|
|
.stack-toggle {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
padding: 4px 0;
|
|
margin-bottom: 6px;
|
|
background: none;
|
|
border: none;
|
|
font-family: var(--font-body);
|
|
}
|
|
|
|
.stack-toggle:hover { color: var(--text-primary); }
|
|
|
|
.stack-content {
|
|
background: var(--sidebar-bg);
|
|
border-radius: var(--radius-sm);
|
|
padding: 12px 14px;
|
|
overflow-x: auto;
|
|
max-height: 220px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.stack-content pre {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
line-height: 1.7;
|
|
color: #D4C8B8;
|
|
margin: 0;
|
|
white-space: pre;
|
|
}
|
|
|
|
.stack-content .stack-highlight {
|
|
color: #F0C4BE;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.stack-content .stack-cause {
|
|
color: #E8A838;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.stack-content .stack-at {
|
|
color: #8B9DAF;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
PROPERTIES & CORRELATION
|
|
========================================================================== */
|
|
.props-section {
|
|
background: var(--bg-surface);
|
|
border: 1px solid var(--border-subtle);
|
|
border-radius: var(--radius-lg);
|
|
box-shadow: var(--shadow-card);
|
|
overflow: hidden;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.props-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 10px 18px;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
cursor: pointer;
|
|
transition: background 0.08s;
|
|
}
|
|
|
|
.props-header:hover { background: var(--bg-hover); }
|
|
|
|
.props-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.props-chevron {
|
|
color: var(--text-faint);
|
|
font-size: 12px;
|
|
transition: transform 0.2s;
|
|
}
|
|
|
|
.props-body {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 0;
|
|
padding: 16px 18px;
|
|
}
|
|
|
|
.props-column {
|
|
padding: 0 16px;
|
|
border-right: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.props-column:first-child { padding-left: 0; }
|
|
.props-column:last-child { border-right: none; }
|
|
|
|
.props-col-title {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.6px;
|
|
color: var(--text-muted);
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.prop-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 4px;
|
|
padding: 3px 0;
|
|
border-bottom: 1px solid var(--border-subtle);
|
|
font-size: 11px;
|
|
}
|
|
|
|
.prop-row:last-child { border-bottom: none; }
|
|
|
|
.prop-key {
|
|
font-weight: 500;
|
|
color: var(--text-muted);
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.prop-val {
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
color: var(--text-primary);
|
|
word-break: break-all;
|
|
}
|
|
|
|
/* Correlation chain */
|
|
.correlation-chain {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0;
|
|
margin-top: 16px;
|
|
padding: 12px 18px;
|
|
border-top: 1px solid var(--border-subtle);
|
|
}
|
|
|
|
.chain-label {
|
|
font-size: 10px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.6px;
|
|
color: var(--text-muted);
|
|
margin-right: 14px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.chain-node {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 4px 12px;
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-sm);
|
|
font-family: var(--font-mono);
|
|
font-size: 11px;
|
|
font-weight: 500;
|
|
color: var(--text-secondary);
|
|
cursor: pointer;
|
|
transition: all 0.12s;
|
|
background: var(--bg-surface);
|
|
}
|
|
|
|
.chain-node:hover { border-color: var(--amber); color: var(--amber); }
|
|
.chain-node.current { background: var(--amber-bg); border-color: var(--amber-light); color: var(--amber-deep); font-weight: 600; }
|
|
.chain-node.chain-error { border-color: var(--error-border); color: var(--error); }
|
|
|
|
.chain-arrow {
|
|
color: var(--text-faint);
|
|
font-size: 14px;
|
|
margin: 0 6px;
|
|
}
|
|
|
|
/* ==========================================================================
|
|
KEYBOARD HINTS
|
|
========================================================================== */
|
|
.keyboard-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 220px;
|
|
right: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 16px;
|
|
padding: 6px 24px;
|
|
background: var(--sidebar-bg);
|
|
border-top: 1px solid rgba(255,255,255,0.06);
|
|
z-index: 100;
|
|
}
|
|
|
|
.kb-hint {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
font-size: 11px;
|
|
color: var(--sidebar-muted);
|
|
}
|
|
|
|
.kb-key {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
padding: 1px 5px;
|
|
border-radius: 3px;
|
|
background: rgba(255,255,255,0.08);
|
|
color: var(--sidebar-text);
|
|
border: 1px solid rgba(255,255,255,0.1);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="app">
|
|
<!-- ====================================================================
|
|
SIDEBAR (identical structure to mock-v2)
|
|
==================================================================== -->
|
|
<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:#C6820E" 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.2834,-13.56192 41.5,-17.32336 3.85,-1.1854 7.9,-2.55654 9,-3.04699 6.0644,-2.70386 29.8837,-6.94397 39.0685,-6.95465 16.5354,-0.0192 29.4209,10.53866 32.4491,26.58755 1.5763,8.35375 1.0812,11.63345 -4.5147,29.90655 -10.1916,33.28037 -13.3229,61.96134 -10.0442,92 3.2262,29.55737 10.5673,53.87028 23.6898,78.45848 11.023,20.65405 21.7624,35.21113 38.7623,52.54152 17.2909,17.62693 24.0427,25.40931 30.3653,35 26.0619,39.5327 33.1081,82.6442 23.6173,144.5 -1.6936,11.0379 -7.1852,37.5413 -10.412,50.25 l -0.6982,2.75 h 11.041 c 9.6675,0 11.1002,-0.2177 11.5165,-1.75 0.2615,-0.9625 1.1691,-4.9 2.0169,-8.75 4.2214,-19.1689 6.8202,-30.513 8.1326,-35.5 1.361,-5.1717 9.3524,-39.8413 18.5555,-80.5 2.2408,-9.9 5.3554,-23.4 6.9213,-30 4.9646,-20.9246 5.3189,-23.3077 4.1531,-27.9371 -0.5856,-2.32595 -4.0498,-10.49161 -7.6981,-18.14594 -9.222,-19.34804 -12.2871,-26.05688 -14.0769,-30.8114 -5.3001,-14.07878 -9.5733,-27.65251 -11.9961,-38.10556 -2.5547,-11.02237 -2.7797,-13.62939 -2.7612,-32 0.019,-19.36303 0.1714,-20.85991 4.7729,-47 6.161,-34.99931 7.6003,-48.16042 7.6003,-69.5 -10e-5,-33.76835 -6.5703,-63.86472 -19.8286,-90.82854 -6.3511,-12.91659 -11.7543,-20.74668 -21.037,-30.48614 -12.8375,-13.46928 -22.9472,-20.76621 -47.0954,-33.9923 -11.7394,-6.42975 -28.8576,-17.82564 -36.5,-24.2987 -10.6672,-9.03504 -17.2351,-15.91058 -32.8553,-34.39432 -16.848,-19.93653 -31.9446,-35.04489 -42.6447,-42.67772 -10.3431,-7.37816 -15.6552,-10.10769 -28,-14.38707 -9.1747,-3.18048 -10.0479,-3.29466 -25.5,-3.33475 -15.5657,-0.0404 -16.2561,0.0478 -25.4354,3.24965 -23.091,8.0544 -33.3943,15.26018 -59.5646,41.65777 -30.5973,30.86299 -38.6661,35.8414 -77,47.50846 -16.2269,4.93872 -34.1287,15.69697 -44.617,26.81301 -10.992,11.6499 -13.307,14.35965 -22.3589,26.17065 -19.0735,24.88726 -27.0799,33.14259 -41.0241,42.29946 -10.0586,6.60527 -20.3327,9.75956 -33.9507,10.42334 -37.2243,1.81441 -62.5379,-17.55119 -76.1054,-58.2228 -11.652,-34.92922 -16.8948,-93.36051 -12.158,-135.5 5.892,-52.41494 5.8488,-63.62373 -0.3099,-80.57433 -4.7448,-13.05916 -4.7675,-12.96705 5.716,-23.17933 5.7642,-5.61509 9.7601,-10.45668 11.1613,-13.52373 2.7419,-6.00142 5.1126,-15.9207 5.1319,-21.47261 L 1198,352 l -5.9651,0 c -11.169,0 -21.7558,5.31928 -28.8986,14.51992 -5.5094,7.09667 -9.8889,9.41118 -14.4261,7.62413 -22.7413,-8.95689 -39.8334,-10.59845 -57.5511,-5.52733 -3.1125,0.89085 -11.6238,4.5155 -18.9141,8.05478 -15.4059,7.47927 -22.5958,9.28006 -37.245,9.32847 -31.9108,0.10543 -56.25892,6.94953 -67.17127,18.88141 -8.24539,9.01574 -18.57001,32.98439 -17.63456,40.9387 0.20038,1.70385 1.68501,3.56683 4.30583,5.40313 6.15036,4.30931 11.64453,4.02586 24.53725,-1.26587 9.37877,-3.84945 11.49879,-4.33904 20.46275,-4.7256 12.5127,-0.5396 16.1351,0.57224 41.5,12.73763 28.326,13.58558 38.6034,16.26339 54.7762,14.27212 10.7814,-1.32746 19.6601,-4.77604 26.9813,-10.47981 10.8957,-8.48862 12.7264,-9.11418 18.2752,-6.24475 3.4802,1.79966 5.9673,6.17527 5.9673,10.49833 0,5.2273 -12.3619,16.07427 -24.373,21.38616 -8.3575,3.69608 -19.5481,6.59858 -25.4408,6.59858 -2.8524,0 -5.1862,0.40847 -5.1862,0.90771 0,0.49925 1.1261,3.08675 2.5024,5.75 7.4849,14.48347 10.3469,40.93277 8.5814,79.30477 -1.8809,40.87852 -1.063,65.17107 3.0314,90.03752 1.9205,11.66347 7.4026,31.07934 11.5058,40.75 3.6541,8.61199 4.8919,11.32366 8.5592,18.75 7.5496,15.28823 16.3315,27.16362 30.7439,41.57393 20.487,20.48403 39.3629,32.17675 72.4974,44.90876 32.2544,12.39381 46.3332,19.15119 64.0627,30.7482 24.2965,15.89251 40.6199,31.86253 55.9811,54.76911 15.3367,22.87022 26.7091,49.93352 35.5759,84.66142 7.4833,29.30908 14.5942,79.14828 16.5733,116.15948 0.3771,7.0514 0.7727,14.0264 0.879,15.5 0.1064,1.4735 0.2639,17.1916 0.35,34.9291 L 1403,1185 h 10.5 10.5 z m 109.6148,-166.12974 c 32.3584,-3.61532 59.7448,-11.3892 85.9116,-24.38672 13.8501,-6.87965 33.6049,-18.83328 37.1094,-22.455 0.7986,-0.82533 0.878,-3.10315 0.2676,-7.67374 -0.4775,-3.575 -0.9114,-15.05 -0.9643,-25.5 -0.1555,-30.74924 3.0015,-49.74257 13.6751,-82.27105 3.3477,-10.20267 3.1984,-15.57022 -0.5373,-19.30587 -2.563,-2.563 -3.6408,-2.92269 -8.75,-2.91989 -17.9704,0.01 -50.057,9.8542 -78.4604,24.07205 -31.505,15.77045 -56.5528,33.57164 -78.5866,55.85076 -22.9969,23.25282 -37.4392,45.78809 -46.737,72.92624 -3.3375,9.74165 -8.0905,29.93345 -7.2451,30.77886 2.3874,2.38739 64.9877,3.04398 84.317,0.88436 z"/>
|
|
</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-node-01</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-node-02</div>
|
|
<div class="agent-detail">order-service 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-node-03</div>
|
|
<div class="agent-detail">payment-svc v3.2.1</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-node-04</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 — Exchange Detail
|
|
==================================================================== -->
|
|
<div class="main">
|
|
<!-- Top bar -->
|
|
<div class="topbar">
|
|
<div class="topbar-breadcrumb">
|
|
<span class="crumb-link">order-service</span>
|
|
<span class="crumb-sep">/</span>
|
|
<span class="crumb-link">order-processing</span>
|
|
<span class="crumb-sep">/</span>
|
|
<span class="crumb-active">Exchange OP-88421</span>
|
|
</div>
|
|
|
|
<div class="topbar-right">
|
|
<span class="topbar-env">PRODUCTION</span>
|
|
<div class="topbar-user">
|
|
<span>hendrik</span>
|
|
<div class="topbar-avatar">H</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scrollable content -->
|
|
<div class="content" style="padding-bottom: 60px;">
|
|
|
|
<!-- ============================================================
|
|
1. EXCHANGE HEADER CARD
|
|
============================================================ -->
|
|
<div class="exchange-header animate-in">
|
|
<div class="exchange-header-top">
|
|
<div class="exchange-title-area">
|
|
<span class="exchange-route">order-processing</span>
|
|
<span class="exchange-status-lg">
|
|
<span class="status-dot"></span>
|
|
FAILED
|
|
</span>
|
|
</div>
|
|
<div class="exchange-actions">
|
|
<button class="action-btn" title="Copy Exchange ID">📋 Copy ID</button>
|
|
<button class="action-btn" title="Copy full trace as JSON">📄 Export JSON</button>
|
|
<button class="action-btn primary" title="Retry this exchange">↻ Retry</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="exchange-meta-grid">
|
|
<div class="meta-item">
|
|
<div class="meta-label">Business IDs</div>
|
|
<div class="meta-value">
|
|
<span class="biz-tag order">Order: OP-88421</span>
|
|
<span class="biz-tag customer">Customer: DE-40912</span>
|
|
</div>
|
|
</div>
|
|
<div class="meta-item">
|
|
<div class="meta-label">Duration</div>
|
|
<div class="meta-value">
|
|
<span class="duration-lg">2m 33s</span>
|
|
<span class="duration-label">total</span>
|
|
</div>
|
|
<div class="meta-sub">Started 09:14:22 (2 min ago)</div>
|
|
</div>
|
|
<div class="meta-item">
|
|
<div class="meta-label">Exchange ID</div>
|
|
<div class="meta-value mono-sm">ID-20260317-091422-prod02-88421</div>
|
|
<div class="meta-sub">Breadcrumb: BC-88421-001</div>
|
|
</div>
|
|
<div class="meta-item">
|
|
<div class="meta-label">Agent</div>
|
|
<div class="meta-value" style="display: flex; align-items: center; gap: 6px;">
|
|
<span style="width: 6px; height: 6px; border-radius: 50%; background: #5DB866; display: inline-block;"></span>
|
|
prod-node-02
|
|
</div>
|
|
<div class="meta-sub">order-service v3.2.1</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================
|
|
2. PROCESSOR TIMELINE (Gantt-style)
|
|
============================================================ -->
|
|
<div class="timeline-section animate-in delay-1">
|
|
<div class="timeline-header">
|
|
<div class="timeline-title">
|
|
Processor Timeline
|
|
<span class="proc-count">5 processors</span>
|
|
</div>
|
|
<div class="timeline-legend">
|
|
<div class="legend-item"><span class="legend-dot l-success"></span> Success</div>
|
|
<div class="legend-item"><span class="legend-dot l-error"></span> Failed</div>
|
|
<div class="legend-item"><span class="legend-dot l-slow"></span> Slow (> SLA)</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timeline-body">
|
|
<!-- Row 1: from(direct:order-intake) — 12ms -->
|
|
<div class="timeline-row" onclick="selectRow(this, 0)">
|
|
<div class="proc-label">
|
|
<span class="proc-index">1</span>
|
|
<span class="proc-type type-from">from</span>
|
|
<span class="proc-name">direct:order-intake</span>
|
|
</div>
|
|
<div class="proc-bar-area">
|
|
<div class="proc-bar bar-success" style="width: 0.8%;"></div>
|
|
</div>
|
|
<div class="proc-duration">12ms</div>
|
|
<div class="proc-status-icon icon-ok">✓</div>
|
|
</div>
|
|
|
|
<!-- Row 2: process(OrderValidator) — 45ms -->
|
|
<div class="timeline-row" onclick="selectRow(this, 1)">
|
|
<div class="proc-label">
|
|
<span class="proc-index">2</span>
|
|
<span class="proc-type type-process">process</span>
|
|
<span class="proc-name">OrderValidator</span>
|
|
</div>
|
|
<div class="proc-bar-area">
|
|
<div class="proc-bar bar-success" style="width: 2.9%;"></div>
|
|
</div>
|
|
<div class="proc-duration">45ms</div>
|
|
<div class="proc-status-icon icon-ok">✓</div>
|
|
</div>
|
|
|
|
<!-- Row 3: to(sql:INSERT INTO orders) — 89ms -->
|
|
<div class="timeline-row" onclick="selectRow(this, 2)">
|
|
<div class="proc-label">
|
|
<span class="proc-index">3</span>
|
|
<span class="proc-type type-to">to</span>
|
|
<span class="proc-name">sql:INSERT INTO orders</span>
|
|
</div>
|
|
<div class="proc-bar-area">
|
|
<div class="proc-bar bar-success" style="width: 5.8%;"></div>
|
|
</div>
|
|
<div class="proc-duration">89ms</div>
|
|
<div class="proc-status-icon icon-ok">✓</div>
|
|
</div>
|
|
|
|
<!-- Row 4: choice(priority check) — 2ms -->
|
|
<div class="timeline-row" onclick="selectRow(this, 3)">
|
|
<div class="proc-label">
|
|
<span class="proc-index">4</span>
|
|
<span class="proc-type type-choice">choice</span>
|
|
<span class="proc-name">priority-check</span>
|
|
</div>
|
|
<div class="proc-bar-area">
|
|
<div class="proc-bar bar-success" style="width: 0.3%;"></div>
|
|
</div>
|
|
<div class="proc-duration">2ms</div>
|
|
<div class="proc-status-icon icon-ok">✓</div>
|
|
</div>
|
|
|
|
<!-- Row 5: to(http:payment-api/charge) — 2m 18s — FAILED -->
|
|
<div class="timeline-row row-error selected" onclick="selectRow(this, 4)">
|
|
<div class="proc-label">
|
|
<span class="proc-index">5</span>
|
|
<span class="proc-type type-to">to</span>
|
|
<span class="proc-name" style="color: var(--error); font-weight: 600;">http:payment-api/charge</span>
|
|
</div>
|
|
<div class="proc-bar-area">
|
|
<div class="proc-bar bar-error" style="width: 94%;">
|
|
<span class="bar-pct">94%</span>
|
|
</div>
|
|
</div>
|
|
<div class="proc-duration dur-error">2m 18s</div>
|
|
<div class="proc-status-icon icon-fail">✗</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bottleneck callout -->
|
|
<div class="bottleneck-callout">
|
|
<span style="font-size: 16px;">⚠</span>
|
|
<span><strong>Bottleneck detected:</strong> Processor #5 <code style="font-family: var(--font-mono); font-size: 11px; background: rgba(192,57,43,0.1); padding: 1px 4px; border-radius: 3px;">http:payment-api/charge</code> consumed</span>
|
|
<span class="bottleneck-pct">94%</span>
|
|
<span>of total execution time (2m 18s of 2m 33s). 503 Service Unavailable after 30s timeout with 4 retries.</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================
|
|
3. PROCESSOR DETAIL PANEL (split IN / OUT)
|
|
Selected: #5 http:payment-api/charge (FAILED)
|
|
============================================================ -->
|
|
<div class="detail-split animate-in delay-2">
|
|
|
|
<!-- LEFT: Message IN (at entry to this processor) -->
|
|
<div class="detail-panel">
|
|
<div class="detail-panel-header">
|
|
<div class="panel-title">
|
|
<span class="arrow-in" style="font-size: 16px;">→</span>
|
|
Message IN
|
|
<span class="panel-tag">at processor #5 entry</span>
|
|
</div>
|
|
</div>
|
|
<div class="detail-panel-body">
|
|
|
|
<!-- Headers at entry -->
|
|
<div class="headers-section">
|
|
<div class="section-label">
|
|
Headers <span class="count">9</span>
|
|
</div>
|
|
<div class="header-list">
|
|
<div class="header-row">
|
|
<span class="header-key">breadcrumbId</span>
|
|
<span class="header-value">BC-88421-001</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">CamelHttpMethod</span>
|
|
<span class="header-value">POST</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">Content-Type</span>
|
|
<span class="header-value">application/json</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">orderId</span>
|
|
<span class="header-value">OP-88421</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">customerId</span>
|
|
<span class="header-value">DE-40912</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">correlationId</span>
|
|
<span class="header-value">corr-a7f3e9d1-88421</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">orderPriority</span>
|
|
<span class="header-value">HIGH</span>
|
|
</div>
|
|
<div class="header-row h-added">
|
|
<span class="header-key">orderDbId <span class="diff-badge added">+added</span></span>
|
|
<span class="header-value">48291</span>
|
|
</div>
|
|
<div class="header-row h-added">
|
|
<span class="header-key">priorityTier <span class="diff-badge added">+added</span></span>
|
|
<span class="header-value">express</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Body at entry -->
|
|
<div class="body-section">
|
|
<div class="section-label">Body</div>
|
|
<div class="body-toolbar">
|
|
<span class="body-format-tag">JSON</span>
|
|
<span class="body-size">1.2 KB</span>
|
|
<button class="body-toggle">Show diff from #4</button>
|
|
</div>
|
|
<div class="body-content">
|
|
<pre><span class="json-brace">{</span>
|
|
<span class="json-key">"orderId"</span>: <span class="json-str">"OP-88421"</span>,
|
|
<span class="json-key">"customerId"</span>: <span class="json-str">"DE-40912"</span>,
|
|
<span class="json-key">"timestamp"</span>: <span class="json-str">"2026-03-17T09:14:22.184Z"</span>,
|
|
<span class="json-key">"items"</span>: <span class="json-brace">[</span>
|
|
<span class="json-brace">{</span>
|
|
<span class="json-key">"sku"</span>: <span class="json-str">"WDG-4420-BLK"</span>,
|
|
<span class="json-key">"name"</span>: <span class="json-str">"Industrial Pressure Valve DN50"</span>,
|
|
<span class="json-key">"quantity"</span>: <span class="json-num">12</span>,
|
|
<span class="json-key">"unitPrice"</span>: <span class="json-num">284.50</span>,
|
|
<span class="json-key">"currency"</span>: <span class="json-str">"EUR"</span>
|
|
<span class="json-brace">}</span>,
|
|
<span class="json-brace">{</span>
|
|
<span class="json-key">"sku"</span>: <span class="json-str">"FLG-1180-SS"</span>,
|
|
<span class="json-key">"name"</span>: <span class="json-str">"Stainless Steel Flange PN16"</span>,
|
|
<span class="json-key">"quantity"</span>: <span class="json-num">24</span>,
|
|
<span class="json-key">"unitPrice"</span>: <span class="json-num">67.90</span>,
|
|
<span class="json-key">"currency"</span>: <span class="json-str">"EUR"</span>
|
|
<span class="json-brace">}</span>
|
|
<span class="json-brace">]</span>,
|
|
<span class="json-key">"totalAmount"</span>: <span class="json-num">5043.60</span>,
|
|
<span class="json-key">"shippingAddress"</span>: <span class="json-brace">{</span>
|
|
<span class="json-key">"street"</span>: <span class="json-str">"Industriestr. 42"</span>,
|
|
<span class="json-key">"city"</span>: <span class="json-str">"Stuttgart"</span>,
|
|
<span class="json-key">"zip"</span>: <span class="json-str">"70178"</span>,
|
|
<span class="json-key">"country"</span>: <span class="json-str">"DE"</span>
|
|
<span class="json-brace">}</span>,
|
|
<span class="json-key">"priority"</span>: <span class="json-str">"HIGH"</span>,
|
|
<span class="json-key">"paymentMethod"</span>: <span class="json-str">"invoice_30d"</span>
|
|
<span class="json-brace">}</span></pre>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RIGHT: Message OUT / Error -->
|
|
<div class="detail-panel panel-error">
|
|
<div class="detail-panel-header">
|
|
<div class="panel-title">
|
|
<span class="arrow-out" style="font-size: 16px;">✗</span>
|
|
Error at Processor #5
|
|
<span class="panel-tag" style="background: var(--error-bg); color: var(--error); border: 1px solid var(--error-border);">FAILED</span>
|
|
</div>
|
|
</div>
|
|
<div class="detail-panel-body">
|
|
|
|
<!-- Error info -->
|
|
<div class="error-section">
|
|
<div class="error-badge-row">
|
|
<span class="error-http-badge">503</span>
|
|
<span class="error-class">java.net.http.HttpTimeoutException</span>
|
|
</div>
|
|
|
|
<div class="error-message-box">
|
|
request timed out after 30000ms — HTTP POST http://payment-api:8080/v2/charge returned 503 Service Unavailable after 4 retry attempts (backoff: 1s, 2s, 4s, 8s)
|
|
</div>
|
|
|
|
<div class="error-detail-grid">
|
|
<span class="error-detail-key">Endpoint</span>
|
|
<span class="error-detail-val">http://payment-api:8080/v2/charge</span>
|
|
|
|
<span class="error-detail-key">HTTP Method</span>
|
|
<span class="error-detail-val">POST</span>
|
|
|
|
<span class="error-detail-key">HTTP Status</span>
|
|
<span class="error-detail-val" style="color: var(--error); font-weight: 600;">503 Service Unavailable</span>
|
|
|
|
<span class="error-detail-key">Timeout</span>
|
|
<span class="error-detail-val">30,000ms (configured)</span>
|
|
|
|
<span class="error-detail-key">Retries</span>
|
|
<span class="error-detail-val">4 of 4 (exhausted)</span>
|
|
|
|
<span class="error-detail-key">Last Attempt</span>
|
|
<span class="error-detail-val">09:16:55.412 (after 8s backoff)</span>
|
|
</div>
|
|
|
|
<!-- Stack trace -->
|
|
<div class="stack-section">
|
|
<button class="stack-toggle">
|
|
<span style="font-size: 9px;">▼</span>
|
|
Stack Trace (42 frames)
|
|
</button>
|
|
<div class="stack-content">
|
|
<pre><span class="stack-highlight">java.net.http.HttpTimeoutException: request timed out after 30000ms</span>
|
|
<span class="stack-at"> at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:586)</span>
|
|
<span class="stack-at"> at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:538)</span>
|
|
<span class="stack-at"> at org.apache.camel.component.http.HttpProducer.executeMethod(HttpProducer.java:347)</span>
|
|
<span class="stack-at"> at org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:198)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:172)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:614)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.errorhandler.RedeliveryErrorHandler.processErrorHandler(RedeliveryErrorHandler.java:258)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:399)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.Pipeline.process(Pipeline.java:184)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.Pipeline.process(Pipeline.java:74)</span>
|
|
<span class="stack-at"> at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.run(DefaultReactiveExecutor.java:182)</span>
|
|
<span class="stack-at"> at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:64)</span>
|
|
<span class="stack-at"> at org.apache.camel.processor.Pipeline.process(Pipeline.java:184)</span>
|
|
<span class="stack-at"> at org.apache.camel.spring.boot.SpringBootRoutesCollector.process(SpringBootRoutesCollector.java:89)</span>
|
|
<span class="stack-cause">Caused by: java.net.ConnectException: Connection refused: payment-api:8080</span>
|
|
<span class="stack-at"> at java.base/sun.nio.ch.Net.connect0(Native Method)</span>
|
|
<span class="stack-at"> at java.base/sun.nio.ch.Net.connect(Net.java:579)</span>
|
|
<span class="stack-at"> at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:726)</span>
|
|
<span class="stack-at"> at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:198)</span>
|
|
<span class="stack-at"> ... 8 more</span></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Response headers (from the 503) -->
|
|
<div class="headers-section" style="margin-top: 16px;">
|
|
<div class="section-label">
|
|
Response Headers <span class="count">4</span>
|
|
</div>
|
|
<div class="header-list">
|
|
<div class="header-row">
|
|
<span class="header-key">Date</span>
|
|
<span class="header-value">Mon, 17 Mar 2026 09:16:55 GMT</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">Content-Length</span>
|
|
<span class="header-value">0</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">Retry-After</span>
|
|
<span class="header-value">60</span>
|
|
</div>
|
|
<div class="header-row">
|
|
<span class="header-key">X-Request-Id</span>
|
|
<span class="header-value">pay-req-f42a8c91</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============================================================
|
|
4. PROPERTIES & CORRELATION
|
|
============================================================ -->
|
|
<div class="props-section animate-in delay-3">
|
|
<div class="props-header">
|
|
<span class="props-title">Exchange Properties & Context</span>
|
|
<span class="props-chevron">▼</span>
|
|
</div>
|
|
|
|
<div class="props-body">
|
|
<!-- Column 1: Exchange Properties -->
|
|
<div class="props-column">
|
|
<div class="props-col-title">Exchange Properties</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelCreatedTimestamp</span>
|
|
<span class="prop-val">2026-03-17T09:14:22.184Z</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelExternalRedelivered</span>
|
|
<span class="prop-val">false</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelToEndpoint</span>
|
|
<span class="prop-val">http://payment-api:8080/v2/charge</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelFailureEndpoint</span>
|
|
<span class="prop-val">http://payment-api:8080/v2/charge</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelRedeliveryCounter</span>
|
|
<span class="prop-val">4</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelRedelivered</span>
|
|
<span class="prop-val">true</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Column 2: Route Context -->
|
|
<div class="props-column">
|
|
<div class="props-col-title">Route Context</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">CamelContext</span>
|
|
<span class="prop-val">order-service-ctx</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Route ID</span>
|
|
<span class="prop-val">order-processing</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Route Version</span>
|
|
<span class="prop-val">3.2.1-20260315</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">From Endpoint</span>
|
|
<span class="prop-val">direct:order-intake</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Error Handler</span>
|
|
<span class="prop-val">DefaultErrorHandler</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Column 3: Environment -->
|
|
<div class="props-column">
|
|
<div class="props-col-title">Environment</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Agent ID</span>
|
|
<span class="prop-val">prod-node-02</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Hostname</span>
|
|
<span class="prop-val">order-svc-6f8d4b-xk2p9</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">JVM</span>
|
|
<span class="prop-val">Eclipse Temurin 17.0.10</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Camel Version</span>
|
|
<span class="prop-val">4.4.1</span>
|
|
</div>
|
|
<div class="prop-row">
|
|
<span class="prop-key">Heap Used</span>
|
|
<span class="prop-val">412 MB / 1024 MB</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Correlation chain -->
|
|
<div class="correlation-chain">
|
|
<span class="chain-label">Correlation Chain</span>
|
|
<span class="chain-node current chain-error">
|
|
<span style="width: 5px; height: 5px; border-radius: 50; background: var(--error); display: inline-block;"></span>
|
|
order-processing
|
|
</span>
|
|
<span class="chain-arrow">→</span>
|
|
<span class="chain-node">
|
|
payment-flow
|
|
</span>
|
|
<span class="chain-arrow">→</span>
|
|
<span class="chain-node">
|
|
notification-sender
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div><!-- /content -->
|
|
|
|
<!-- Keyboard hints bar -->
|
|
<div class="keyboard-bar">
|
|
<div class="kb-hint"><span class="kb-key">↑↓</span> Navigate processors</div>
|
|
<div class="kb-hint"><span class="kb-key">Enter</span> Select processor</div>
|
|
<div class="kb-hint"><span class="kb-key">D</span> Toggle diff</div>
|
|
<div class="kb-hint"><span class="kb-key">J</span> View raw JSON</div>
|
|
<div class="kb-hint"><span class="kb-key">R</span> Retry exchange</div>
|
|
<div class="kb-hint"><span class="kb-key">Esc</span> Back to list</div>
|
|
</div>
|
|
|
|
</div><!-- /main -->
|
|
</div><!-- /app -->
|
|
|
|
<script>
|
|
// Simple row selection for the timeline
|
|
function selectRow(el, index) {
|
|
document.querySelectorAll('.timeline-row').forEach(function(row) {
|
|
row.classList.remove('selected');
|
|
});
|
|
el.classList.add('selected');
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|