fix: match SET_TRACED_PROCESSORS payload to agent protocol
Some checks failed
CI / build (push) Successful in 1m28s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 55s
CI / deploy-feature (push) Has been cancelled
CI / deploy (push) Has been cancelled

Payload now sends {processors: {id: "BOTH"}} map instead of
{routeId, processorIds[]} array. Tracing state keyed by application
name (global, not per-route) matching agent behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-24 22:43:55 +01:00
parent f4dd2b3415
commit 581d53a33e
2 changed files with 23 additions and 19 deletions

View File

@@ -164,26 +164,26 @@ export default function ExchangeDetail() {
const { toast } = useToast() const { toast } = useToast()
const tracingStore = useTracingStore() const tracingStore = useTracingStore()
const sendCommand = useSendGroupCommand() const sendCommand = useSendGroupCommand()
const appRoute = detail ? `${detail.applicationName}:${detail.routeId}` : '' const app = detail?.applicationName ?? ''
const handleToggleTracing = useCallback((processorId: string) => { const handleToggleTracing = useCallback((processorId: string) => {
if (!processorId || !detail?.applicationName || !detail?.routeId) return if (!processorId || !detail?.applicationName) return
const newSet = tracingStore.toggleProcessor(appRoute, processorId) const newMap = tracingStore.toggleProcessor(app, processorId)
sendCommand.mutate({ sendCommand.mutate({
group: detail.applicationName, group: detail.applicationName,
type: 'set-traced-processors', type: 'set-traced-processors',
payload: { routeId: detail.routeId, processorIds: Array.from(newSet) }, payload: { processors: newMap },
}, { }, {
onSuccess: (data) => { onSuccess: (data) => {
const action = newSet.has(processorId) ? 'enabled' : 'disabled' const action = processorId in newMap ? 'enabled' : 'disabled'
toast({ title: `Tracing ${action}`, description: `${processorId} — sent to ${data?.targetCount ?? 0} agent(s)`, variant: 'success' }) toast({ title: `Tracing ${action}`, description: `${processorId} — sent to ${data?.targetCount ?? 0} agent(s)`, variant: 'success' })
}, },
onError: () => { onError: () => {
tracingStore.toggleProcessor(appRoute, processorId) tracingStore.toggleProcessor(app, processorId)
toast({ title: 'Command failed', description: 'Could not send tracing command', variant: 'error' }) toast({ title: 'Command failed', description: 'Could not send tracing command', variant: 'error' })
}, },
}) })
}, [detail, appRoute, tracingStore, sendCommand, toast]) }, [detail, app, tracingStore, sendCommand, toast])
// Correlation chain // Correlation chain
const correlatedExchanges = useMemo(() => { const correlatedExchanges = useMemo(() => {
@@ -346,7 +346,7 @@ export default function ExchangeDetail() {
const pid = processorIds[index] const pid = processorIds[index]
if (!pid || !detail?.applicationName) return [] if (!pid || !detail?.applicationName) return []
return [{ return [{
label: tracingStore.isTraced(appRoute, pid) ? 'Disable Tracing' : 'Enable Tracing', label: tracingStore.isTraced(app, pid) ? 'Disable Tracing' : 'Enable Tracing',
onClick: () => handleToggleTracing(pid), onClick: () => handleToggleTracing(pid),
disabled: sendCommand.isPending, disabled: sendCommand.isPending,
}] }]
@@ -365,7 +365,7 @@ export default function ExchangeDetail() {
const pid = flowProcessorIds[index] const pid = flowProcessorIds[index]
if (!pid || !detail?.applicationName) return [] if (!pid || !detail?.applicationName) return []
return [{ return [{
label: tracingStore.isTraced(appRoute, pid) ? 'Disable Tracing' : 'Enable Tracing', label: tracingStore.isTraced(app, pid) ? 'Disable Tracing' : 'Enable Tracing',
onClick: () => handleToggleTracing(pid), onClick: () => handleToggleTracing(pid),
disabled: sendCommand.isPending, disabled: sendCommand.isPending,
}] }]

View File

@@ -1,23 +1,27 @@
import { create } from 'zustand' import { create } from 'zustand'
type CaptureMode = 'NONE' | 'INPUT' | 'OUTPUT' | 'BOTH'
interface TracingState { interface TracingState {
tracedProcessors: Record<string, Set<string>> /** Key: applicationName → { processorId: captureMode } */
isTraced: (appRoute: string, processorId: string) => boolean tracedProcessors: Record<string, Record<string, CaptureMode>>
toggleProcessor: (appRoute: string, processorId: string) => Set<string> isTraced: (app: string, processorId: string) => boolean
/** Toggle processor tracing (BOTH on, remove on off). Returns the full map for the app. */
toggleProcessor: (app: string, processorId: string) => Record<string, CaptureMode>
} }
export const useTracingStore = create<TracingState>((set, get) => ({ export const useTracingStore = create<TracingState>((set, get) => ({
tracedProcessors: {}, tracedProcessors: {},
isTraced: (appRoute, processorId) => isTraced: (app, processorId) =>
get().tracedProcessors[appRoute]?.has(processorId) ?? false, processorId in (get().tracedProcessors[app] ?? {}),
toggleProcessor: (appRoute, processorId) => { toggleProcessor: (app, processorId) => {
const current = new Set(get().tracedProcessors[appRoute] ?? []) const current = { ...(get().tracedProcessors[app] ?? {}) }
if (current.has(processorId)) current.delete(processorId) if (processorId in current) delete current[processorId]
else current.add(processorId) else current[processorId] = 'BOTH'
set((state) => ({ set((state) => ({
tracedProcessors: { ...state.tracedProcessors, [appRoute]: current }, tracedProcessors: { ...state.tracedProcessors, [app]: current },
})) }))
return current return current
}, },