Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/features/monitoring/accountOverviewState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export type MonitoringPageSizes = {

const MONITORING_TIME_RANGE_VALUES: readonly MonitoringTimeRange[] = [
'today',
'yesterday',
'7d',
'14d',
'30d',
Expand Down
13 changes: 13 additions & 0 deletions src/features/monitoring/hooks/useMonitoringData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
buildMonitoringFilterFacetsFromSummary,
buildRangeFilteredRows,
buildMonitoringAuthMetaMap,
getRangeBounds,
type MonitoringEventRow,
} from './useMonitoringData';
import { sha256Hex } from '@/utils/apiKeyHash';
Expand Down Expand Up @@ -58,6 +59,18 @@ const createMonitoringEventRow = (
searchText: overrides.searchText ?? 'amount myth resend',
});

describe('getRangeBounds', () => {
it('returns the previous local day for yesterday', () => {
const nowMs = new Date(2026, 4, 9, 12, 34, 56, 789).getTime();
const bounds = getRangeBounds('yesterday', nowMs);

expect(bounds).toEqual({
startMs: new Date(2026, 4, 8, 0, 0, 0, 0).getTime(),
endMs: new Date(2026, 4, 9, 0, 0, 0, 0).getTime(),
});
});
});

describe('buildAccountRows', () => {
it('keeps raw auth indices for account-level auth file linking', () => {
const rows = buildAccountRows([
Expand Down
25 changes: 9 additions & 16 deletions src/features/monitoring/hooks/useMonitoringData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ export const getRangeBounds = (
switch (range) {
case 'today':
return { startMs: todayStart, endMs: nowMs };
case 'yesterday':
return { startMs: todayStart - 24 * 60 * 60 * 1000, endMs: todayStart };
case '7d':
return { startMs: todayStart - 6 * 24 * 60 * 60 * 1000, endMs: nowMs };
case '14d':
Expand All @@ -85,6 +87,7 @@ const shouldUseHourlyTimeline = (
customRange?: MonitoringCustomTimeRange | null
) =>
range === 'today' ||
range === 'yesterday' ||
(range === 'custom' &&
isValidCustomTimeRange(customRange) &&
buildLocalDayKey(customRange.startMs) === buildLocalDayKey(customRange.endMs));
Expand Down Expand Up @@ -291,7 +294,7 @@ type MonitoringAuthMeta = {
updatedAt: string;
};

export type MonitoringTimeRange = 'today' | '7d' | '14d' | '30d' | 'all' | 'custom';
export type MonitoringTimeRange = 'today' | 'yesterday' | '7d' | '14d' | '30d' | 'all' | 'custom';

export type MonitoringCustomTimeRange = {
startMs: number;
Expand Down Expand Up @@ -1860,9 +1863,7 @@ const buildEventRows = (
Number(detail.__streamFailureCountToEvent) || 0,
0
);
const serverStreamRecentPatternToEvent = Array.isArray(
detail.__streamRecentPatternToEvent
)
const serverStreamRecentPatternToEvent = Array.isArray(detail.__streamRecentPatternToEvent)
? detail.__streamRecentPatternToEvent.map((value) => value === true).slice(-10)
: undefined;
const dayKey = buildLocalDayKey(timestampMs);
Expand Down Expand Up @@ -1915,10 +1916,8 @@ const buildEventRows = (
totalCost,
serverStreamKey: serverStreamTotalCalls > 0 ? serverStreamKey || undefined : undefined,
serverStreamTotalCalls: serverStreamTotalCalls > 0 ? serverStreamTotalCalls : undefined,
serverStreamSuccessCalls:
serverStreamTotalCalls > 0 ? serverStreamSuccessCalls : undefined,
serverStreamFailureCalls:
serverStreamTotalCalls > 0 ? serverStreamFailureCalls : undefined,
serverStreamSuccessCalls: serverStreamTotalCalls > 0 ? serverStreamSuccessCalls : undefined,
serverStreamFailureCalls: serverStreamTotalCalls > 0 ? serverStreamFailureCalls : undefined,
serverStreamRecentPattern,
serverStreamRequestCount:
serverStreamRequestCount > 0 ? serverStreamRequestCount : undefined,
Expand Down Expand Up @@ -2006,9 +2005,7 @@ const buildAccountRowsFromPageItems = (
const latencySum = readPageNumber(item, 'latency_sum_ms', 'latencySumMs');
const rawRecentPattern = item.recent_pattern ?? item.recentPattern;
const recentPattern = Array.isArray(rawRecentPattern)
? rawRecentPattern
.map((value: unknown) => value === true)
.filter((_, index) => index < 10)
? rawRecentPattern.map((value: unknown) => value === true).filter((_, index) => index < 10)
: [];
return {
id: account,
Expand Down Expand Up @@ -2132,11 +2129,7 @@ const buildRealtimeRowsFromPageItems = (
success_count: item.failed === true ? 0 : 1,
failure_count: item.failed === true ? 1 : 0,
__streamKey: readString(item.stream_key ?? item.streamKey),
__streamTotalRequests: readPageNumber(
item,
'stream_total_requests',
'streamTotalRequests'
),
__streamTotalRequests: readPageNumber(item, 'stream_total_requests', 'streamTotalRequests'),
__streamSuccessCount: readPageNumber(item, 'stream_success_count', 'streamSuccessCount'),
__streamFailureCount: readPageNumber(item, 'stream_failure_count', 'streamFailureCount'),
__streamRecentPattern: streamRecentPattern,
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,7 @@
"realtime_console_eyebrow": "Realtime Runtime Monitor",
"console_subtitle": "Track call volume, success and failure, token structure, and spend by account within the selected time range, with a live table that behaves more like a request log console.",
"range_today": "Today",
"range_yesterday": "Yesterday",
"range_7d": "7d",
"range_14d": "14d",
"range_30d": "30d",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,7 @@
"realtime_console_eyebrow": "Realtime Runtime Monitor",
"console_subtitle": "Отслеживайте объём вызовов, успехи и ошибки, структуру token и расходы по аккаунтам в выбранном диапазоне времени, с живой таблицей в стиле request log.",
"range_today": "Сегодня",
"range_yesterday": "Вчера",
"range_7d": "7д",
"range_14d": "14д",
"range_30d": "30д",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,7 @@
"realtime_console_eyebrow": "实时运行监控",
"console_subtitle": "按账号和时间范围追踪调用规模、成功失败、Token 结构和花费,并提供接近请求日志的实时监控表。",
"range_today": "今天",
"range_yesterday": "昨天",
"range_7d": "7 天",
"range_14d": "14 天",
"range_30d": "30 天",
Expand Down
1 change: 1 addition & 0 deletions src/i18n/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,7 @@
"realtime_console_eyebrow": "即時運行監控",
"console_subtitle": "按帳號與時間範圍追蹤呼叫規模、成功失敗、Token 結構與花費,並提供接近請求日誌的即時監控表。",
"range_today": "今天",
"range_yesterday": "昨天",
"range_7d": "7 天",
"range_14d": "14 天",
"range_30d": "30 天",
Expand Down
2 changes: 1 addition & 1 deletion src/pages/MonitoringCenterPage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@

.filterGrid {
display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr));
grid-template-columns: repeat(6, minmax(0, 1fr));
align-items: start;
gap: 12px;

Expand Down
28 changes: 21 additions & 7 deletions src/pages/MonitoringCenterPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
useRef,
useState,
type ChangeEvent,
type MouseEvent,
type ReactNode,
} from 'react';
import { Link } from 'react-router-dom';
Expand Down Expand Up @@ -120,6 +121,7 @@

const TIME_RANGE_OPTIONS: Array<{ value: MonitoringTimeRange; labelKey: string }> = [
{ value: 'today', labelKey: 'monitoring.range_today' },
{ value: 'yesterday', labelKey: 'monitoring.range_yesterday' },
{ value: '7d', labelKey: 'monitoring.range_7d' },
{ value: '14d', labelKey: 'monitoring.range_14d' },
{ value: '30d', labelKey: 'monitoring.range_30d' },
Expand Down Expand Up @@ -476,7 +478,7 @@
},
];

export const buildRealtimeLogRows = (rows: MonitoringEventRow[]): RealtimeLogRow[] => {

Check warning on line 481 in src/pages/MonitoringCenterPage.tsx

View workflow job for this annotation

GitHub Actions / Frontend

Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components
const sortedAsc = [...rows].sort(
(left, right) => left.timestampMs - right.timestampMs || left.id.localeCompare(right.id)
);
Expand Down Expand Up @@ -2284,8 +2286,7 @@
);

const syncPriceModels = useMemo(
() =>
buildModelPriceCandidateModels(filterFacets.models, filteredRows, modelPrices),
() => buildModelPriceCandidateModels(filterFacets.models, filteredRows, modelPrices),
[filterFacets.models, filteredRows, modelPrices]
);

Expand Down Expand Up @@ -2808,6 +2809,17 @@
setCustomDraftEndInput(event.target.value);
}, []);

const openDateTimePicker = useCallback((event: MouseEvent<HTMLInputElement>) => {
const input = event.currentTarget;
input.focus();
try {
input.showPicker?.();
} catch {
// Some browsers only allow showPicker during trusted user gestures.
// Keeping focus preserves the native fallback behavior.
}
}, []);

const applyCustomTimeRange = useCallback(() => {
if (customDraftTimeRangeError) return;
setCustomStartInput(customDraftStartInput);
Expand Down Expand Up @@ -3860,11 +3872,6 @@
extra={
<div className={styles.accountOverviewHeaderActions}>
<div className={styles.accountOverviewToolbarRow}>
<div className={styles.inlineMetrics}>
<span>
{t('monitoring.api_key_summary_keys_count', { count: apiKeyTotalCount })}
</span>
</div>
<div className={styles.accountOverviewSortBar}>
<Select
className={styles.accountOverviewSortSelect}
Expand All @@ -3876,6 +3883,11 @@
fullWidth={false}
/>
</div>
<div className={styles.inlineMetrics}>
<span>
{t('monitoring.api_key_summary_keys_count', { count: apiKeyTotalCount })}
</span>
</div>
</div>
</div>
}
Expand Down Expand Up @@ -4176,6 +4188,7 @@
label={t('monitoring.custom_range_start')}
value={customDraftStartInput}
onChange={handleCustomDraftStartChange}
onClick={openDateTimePicker}
className={styles.customRangeInput}
aria-invalid={Boolean(customDraftTimeRangeError)}
/>
Expand All @@ -4184,6 +4197,7 @@
label={t('monitoring.custom_range_end')}
value={customDraftEndInput}
onChange={handleCustomDraftEndChange}
onClick={openDateTimePicker}
className={styles.customRangeInput}
aria-invalid={Boolean(customDraftTimeRangeError)}
/>
Expand Down
Loading