fix: add groupName to ExecutionSummary, locale format stat values, inspect column, fix duplicate keys
- Added groupName field to ExecutionSummary Java record and OpenSearch mapper - Dashboard stat cards use locale-formatted numbers (en-US) - Added inspect column (↗) linking directly to exchange detail page - Fixed duplicate React key warning from two columns sharing executionId key Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -323,6 +323,7 @@ public class OpenSearchIndex implements SearchIndex {
|
|||||||
(String) src.get("execution_id"),
|
(String) src.get("execution_id"),
|
||||||
(String) src.get("route_id"),
|
(String) src.get("route_id"),
|
||||||
(String) src.get("agent_id"),
|
(String) src.get("agent_id"),
|
||||||
|
(String) src.get("group_name"),
|
||||||
(String) src.get("status"),
|
(String) src.get("status"),
|
||||||
src.get("start_time") != null ? Instant.parse((String) src.get("start_time")) : null,
|
src.get("start_time") != null ? Instant.parse((String) src.get("start_time")) : null,
|
||||||
src.get("end_time") != null ? Instant.parse((String) src.get("end_time")) : null,
|
src.get("end_time") != null ? Instant.parse((String) src.get("end_time")) : null,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public record ExecutionSummary(
|
|||||||
String executionId,
|
String executionId,
|
||||||
String routeId,
|
String routeId,
|
||||||
String agentId,
|
String agentId,
|
||||||
|
String groupName,
|
||||||
String status,
|
String status,
|
||||||
Instant startTime,
|
Instant startTime,
|
||||||
Instant endTime,
|
Instant endTime,
|
||||||
|
|||||||
@@ -83,6 +83,24 @@
|
|||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspectLink {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: color 0.15s, background 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inspectLink:hover {
|
||||||
|
color: var(--accent, #c6820e);
|
||||||
|
background: var(--bg-hover);
|
||||||
|
}
|
||||||
|
|
||||||
.openDetailLink {
|
.openDetailLink {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
@@ -84,6 +84,17 @@ export default function Dashboard() {
|
|||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: '_inspect' as any, header: '', width: '36px',
|
||||||
|
render: (_v, row) => (
|
||||||
|
<a
|
||||||
|
href={`/exchanges/${row.executionId}`}
|
||||||
|
onClick={(e) => { e.stopPropagation(); e.preventDefault(); navigate(`/exchanges/${row.executionId}`); }}
|
||||||
|
className={styles.inspectLink}
|
||||||
|
title="Open full details"
|
||||||
|
>↗</a>
|
||||||
|
),
|
||||||
|
},
|
||||||
{ key: 'routeId', header: 'Route', sortable: true, render: (v) => <span>{String(v)}</span> },
|
{ key: 'routeId', header: 'Route', sortable: true, render: (v) => <span>{String(v)}</span> },
|
||||||
{ key: 'groupName', header: 'Application', sortable: true, render: (v) => <span>{String(v ?? '')}</span> },
|
{ key: 'groupName', header: 'Application', sortable: true, render: (v) => <span>{String(v ?? '')}</span> },
|
||||||
{ key: 'executionId', header: 'Exchange ID', sortable: true, render: (v) => <MonoText size="xs">{String(v)}</MonoText> },
|
{ key: 'executionId', header: 'Exchange ID', sortable: true, render: (v) => <MonoText size="xs">{String(v)}</MonoText> },
|
||||||
@@ -193,7 +204,7 @@ export default function Dashboard() {
|
|||||||
<div className={styles.healthStrip}>
|
<div className={styles.healthStrip}>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Exchanges"
|
label="Exchanges"
|
||||||
value={totalCount.toLocaleString()}
|
value={totalCount.toLocaleString('en-US')}
|
||||||
detail={`${successRate.toFixed(1)}% success rate`}
|
detail={`${successRate.toFixed(1)}% success rate`}
|
||||||
trend={exchangeTrend > 0 ? 'up' : exchangeTrend < 0 ? 'down' : 'neutral'}
|
trend={exchangeTrend > 0 ? 'up' : exchangeTrend < 0 ? 'down' : 'neutral'}
|
||||||
trendValue={exchangeTrend > 0 ? `+${exchangeTrend.toFixed(0)}%` : `${exchangeTrend.toFixed(0)}%`}
|
trendValue={exchangeTrend > 0 ? `+${exchangeTrend.toFixed(0)}%` : `${exchangeTrend.toFixed(0)}%`}
|
||||||
@@ -203,7 +214,7 @@ export default function Dashboard() {
|
|||||||
<StatCard
|
<StatCard
|
||||||
label="Success Rate"
|
label="Success Rate"
|
||||||
value={`${successRate.toFixed(1)}%`}
|
value={`${successRate.toFixed(1)}%`}
|
||||||
detail={`${(totalCount - failedCount).toLocaleString()} ok / ${failedCount} error`}
|
detail={`${(totalCount - failedCount).toLocaleString('en-US')} ok / ${failedCount} error`}
|
||||||
trend={successRateDelta >= 0 ? 'up' : 'down'}
|
trend={successRateDelta >= 0 ? 'up' : 'down'}
|
||||||
trendValue={`${successRateDelta >= 0 ? '+' : ''}${successRateDelta.toFixed(1)}%`}
|
trendValue={`${successRateDelta >= 0 ? '+' : ''}${successRateDelta.toFixed(1)}%`}
|
||||||
accent="success"
|
accent="success"
|
||||||
@@ -226,8 +237,8 @@ export default function Dashboard() {
|
|||||||
/>
|
/>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Latency p99"
|
label="Latency p99"
|
||||||
value={stats?.p99LatencyMs ?? 0}
|
value={(stats?.p99LatencyMs ?? 0).toLocaleString('en-US')}
|
||||||
detail={`${stats?.p99LatencyMs ?? 0}ms`}
|
detail={`${(stats?.p99LatencyMs ?? 0).toLocaleString('en-US')}ms`}
|
||||||
sparkline={sparkLatency}
|
sparkline={sparkLatency}
|
||||||
accent="warning"
|
accent="warning"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user