feat: add log source filter (app/agent) to runtime log viewers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ export interface LogEntryResponse {
|
||||
instanceId: string | null;
|
||||
application: string | null;
|
||||
mdc: Record<string, string> | null;
|
||||
source: string | null;
|
||||
}
|
||||
|
||||
export interface LogSearchPageResponse {
|
||||
@@ -29,6 +30,7 @@ export interface LogSearchParams {
|
||||
level?: string;
|
||||
application?: string;
|
||||
agentId?: string;
|
||||
source?: string;
|
||||
exchangeId?: string;
|
||||
logger?: string;
|
||||
from?: string;
|
||||
@@ -45,6 +47,7 @@ async function fetchLogs(params: LogSearchParams): Promise<LogSearchPageResponse
|
||||
if (params.level) urlParams.set('level', params.level);
|
||||
if (params.application) urlParams.set('application', params.application);
|
||||
if (params.agentId) urlParams.set('agentId', params.agentId);
|
||||
if (params.source) urlParams.set('source', params.source);
|
||||
if (params.exchangeId) urlParams.set('exchangeId', params.exchangeId);
|
||||
if (params.logger) urlParams.set('logger', params.logger);
|
||||
if (params.from) urlParams.set('from', params.from);
|
||||
@@ -89,7 +92,7 @@ export function useLogs(
|
||||
export function useApplicationLogs(
|
||||
application?: string,
|
||||
agentId?: string,
|
||||
options?: { limit?: number; toOverride?: string; exchangeId?: string },
|
||||
options?: { limit?: number; toOverride?: string; exchangeId?: string; source?: string },
|
||||
) {
|
||||
const refetchInterval = useRefreshInterval(15_000);
|
||||
const { timeRange } = useGlobalFilters();
|
||||
@@ -99,6 +102,7 @@ export function useApplicationLogs(
|
||||
const params: LogSearchParams = {
|
||||
application: application || undefined,
|
||||
agentId: agentId || undefined,
|
||||
source: options?.source || undefined,
|
||||
exchangeId: options?.exchangeId || undefined,
|
||||
from: useTimeRange ? timeRange.start.toISOString() : undefined,
|
||||
to: useTimeRange ? to : undefined,
|
||||
@@ -109,7 +113,7 @@ export function useApplicationLogs(
|
||||
queryKey: ['logs', 'compat', application, agentId,
|
||||
useTimeRange ? timeRange.start.toISOString() : null,
|
||||
useTimeRange ? to : null,
|
||||
options?.limit, options?.exchangeId],
|
||||
options?.limit, options?.exchangeId, options?.source],
|
||||
queryFn: () => fetchLogs(params),
|
||||
enabled: !!application,
|
||||
placeholderData: (prev) => prev,
|
||||
|
||||
@@ -87,6 +87,11 @@ const LOG_LEVEL_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'trace', label: 'Trace', color: 'var(--text-muted)' },
|
||||
];
|
||||
|
||||
const LOG_SOURCE_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'app', label: 'App' },
|
||||
{ value: 'agent', label: 'Agent' },
|
||||
];
|
||||
|
||||
// ── AgentHealth page ─────────────────────────────────────────────────────────
|
||||
|
||||
export default function AgentHealth() {
|
||||
@@ -138,9 +143,10 @@ export default function AgentHealth() {
|
||||
|
||||
const [logSearch, setLogSearch] = useState('');
|
||||
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());
|
||||
const [logSource, setLogSource] = useState<string>(''); // '' = all, 'app', 'agent'
|
||||
const [logSortAsc, setLogSortAsc] = useState(false);
|
||||
const [logRefreshTo, setLogRefreshTo] = useState<string | undefined>();
|
||||
const { data: rawLogs } = useApplicationLogs(appId, undefined, { toOverride: logRefreshTo });
|
||||
const { data: rawLogs } = useApplicationLogs(appId, undefined, { toOverride: logRefreshTo, source: logSource || undefined });
|
||||
const logEntries = useMemo<LogEntry[]>(() => {
|
||||
const mapped = (rawLogs || []).map((l) => ({
|
||||
timestamp: l.timestamp ?? '',
|
||||
@@ -554,6 +560,11 @@ export default function AgentHealth() {
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<ButtonGroup
|
||||
items={LOG_SOURCE_ITEMS}
|
||||
value={logSource ? new Set([logSource]) : new Set()}
|
||||
onChange={(v) => setLogSource(v.size === 0 ? '' : [...v][0])}
|
||||
/>
|
||||
<ButtonGroup items={LOG_LEVEL_ITEMS} value={logLevels} onChange={setLogLevels} />
|
||||
{logLevels.size > 0 && (
|
||||
<Button variant="ghost" size="sm" onClick={() => setLogLevels(new Set())}>
|
||||
|
||||
@@ -26,11 +26,17 @@ const LOG_LEVEL_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'trace', label: 'Trace', color: 'var(--text-muted)' },
|
||||
];
|
||||
|
||||
const LOG_SOURCE_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'app', label: 'App' },
|
||||
{ value: 'agent', label: 'Agent' },
|
||||
];
|
||||
|
||||
export default function AgentInstance() {
|
||||
const { appId, instanceId } = useParams();
|
||||
const { timeRange } = useGlobalFilters();
|
||||
const [logSearch, setLogSearch] = useState('');
|
||||
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());
|
||||
const [logSource, setLogSource] = useState<string>(''); // '' = all, 'app', 'agent'
|
||||
const [logSortAsc, setLogSortAsc] = useState(false);
|
||||
const [eventSortAsc, setEventSortAsc] = useState(false);
|
||||
const [logRefreshTo, setLogRefreshTo] = useState<string | undefined>();
|
||||
@@ -136,7 +142,7 @@ export default function AgentInstance() {
|
||||
);
|
||||
|
||||
// Application logs
|
||||
const { data: rawLogs } = useApplicationLogs(appId, instanceId, { toOverride: logRefreshTo });
|
||||
const { data: rawLogs } = useApplicationLogs(appId, instanceId, { toOverride: logRefreshTo, source: logSource || undefined });
|
||||
const logEntries = useMemo<LogEntry[]>(() => {
|
||||
const mapped = (rawLogs || []).map((l) => ({
|
||||
timestamp: l.timestamp ?? '',
|
||||
@@ -435,6 +441,11 @@ export default function AgentInstance() {
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<ButtonGroup
|
||||
items={LOG_SOURCE_ITEMS}
|
||||
value={logSource ? new Set([logSource]) : new Set()}
|
||||
onChange={(v) => setLogSource(v.size === 0 ? '' : [...v][0])}
|
||||
/>
|
||||
<ButtonGroup items={LOG_LEVEL_ITEMS} value={logLevels} onChange={setLogLevels} />
|
||||
{logLevels.size > 0 && (
|
||||
<button className={logStyles.logClearFilters} onClick={() => setLogLevels(new Set())}>
|
||||
|
||||
Reference in New Issue
Block a user