fix: Runtime tab respects selected environment
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m21s
CI / docker (push) Successful in 1m5s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 41s

- Add environment parameter to AgentEventsController, AgentEventService,
  and ClickHouseAgentEventRepository (filters agent_events by environment)
- Wire selectedEnv to useAgents and useAgentEvents in both AgentHealth
  and AgentInstance pages
- Wire selectedEnv to useStatsTimeseries in AgentInstance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 16:12:33 +02:00
parent cb36d7936f
commit 69dcce2a8f
7 changed files with 29 additions and 8 deletions

View File

@@ -32,6 +32,7 @@ public class AgentEventsController {
public ResponseEntity<List<AgentEventResponse>> getEvents(
@RequestParam(required = false) String appId,
@RequestParam(required = false) String agentId,
@RequestParam(required = false) String environment,
@RequestParam(required = false) String from,
@RequestParam(required = false) String to,
@RequestParam(defaultValue = "50") int limit) {
@@ -39,7 +40,7 @@ public class AgentEventsController {
Instant fromInstant = from != null ? Instant.parse(from) : null;
Instant toInstant = to != null ? Instant.parse(to) : null;
var events = agentEventService.queryEvents(appId, agentId, fromInstant, toInstant, limit)
var events = agentEventService.queryEvents(appId, agentId, environment, fromInstant, toInstant, limit)
.stream()
.map(AgentEventResponse::from)
.toList();

View File

@@ -38,6 +38,11 @@ public class ClickHouseAgentEventRepository implements AgentEventRepository {
@Override
public List<AgentEventRecord> query(String applicationId, String instanceId, Instant from, Instant to, int limit) {
return query(applicationId, instanceId, null, from, to, limit);
}
@Override
public List<AgentEventRecord> query(String applicationId, String instanceId, String environment, Instant from, Instant to, int limit) {
var sql = new StringBuilder(SELECT_BASE);
var params = new ArrayList<Object>();
params.add(tenantId);
@@ -50,6 +55,10 @@ public class ClickHouseAgentEventRepository implements AgentEventRepository {
sql.append(" AND instance_id = ?");
params.add(instanceId);
}
if (environment != null) {
sql.append(" AND environment = ?");
params.add(environment);
}
if (from != null) {
sql.append(" AND timestamp >= ?");
params.add(Timestamp.from(from));

View File

@@ -8,4 +8,6 @@ public interface AgentEventRepository {
void insert(String instanceId, String applicationId, String eventType, String detail);
List<AgentEventRecord> query(String applicationId, String instanceId, Instant from, Instant to, int limit);
List<AgentEventRecord> query(String applicationId, String instanceId, String environment, Instant from, Instant to, int limit);
}

View File

@@ -24,4 +24,8 @@ public class AgentEventService {
public List<AgentEventRecord> queryEvents(String applicationId, String instanceId, Instant from, Instant to, int limit) {
return repository.query(applicationId, instanceId, from, to, limit);
}
public List<AgentEventRecord> queryEvents(String applicationId, String instanceId, String environment, Instant from, Instant to, int limit) {
return repository.query(applicationId, instanceId, environment, from, to, limit);
}
}

View File

@@ -27,15 +27,16 @@ export function useAgents(status?: string, application?: string, environment?: s
});
}
export function useAgentEvents(appId?: string, agentId?: string, limit = 50, toOverride?: string) {
export function useAgentEvents(appId?: string, agentId?: string, limit = 50, toOverride?: string, environment?: string) {
const refetchInterval = useRefreshInterval(15_000);
return useQuery({
queryKey: ['agents', 'events', appId, agentId, limit, toOverride],
queryKey: ['agents', 'events', appId, agentId, limit, toOverride, environment],
queryFn: async () => {
const token = useAuthStore.getState().accessToken;
const params = new URLSearchParams();
if (appId) params.set('appId', appId);
if (agentId) params.set('agentId', agentId);
if (environment) params.set('environment', environment);
if (toOverride) params.set('to', toOverride);
params.set('limit', String(limit));
const res = await fetch(`${config.apiBaseUrl}/agents/events-log?${params}`, {

View File

@@ -12,6 +12,7 @@ import logStyles from '../../styles/log-panel.module.css';
import { useAgents, useAgentEvents } from '../../api/queries/agents';
import { useApplicationLogs } from '../../api/queries/logs';
import { useApplicationConfig, useUpdateApplicationConfig } from '../../api/queries/commands';
import { useEnvironmentStore } from '../../api/environment-store';
import type { ConfigUpdateResponse } from '../../api/queries/commands';
import type { AgentInstance } from '../../api/types';
import { timeAgo } from '../../utils/format-utils';
@@ -91,7 +92,8 @@ export default function AgentHealth() {
const { appId } = useParams();
const navigate = useNavigate();
const { toast } = useToast();
const { data: agents } = useAgents(undefined, appId);
const selectedEnv = useEnvironmentStore((s) => s.environment);
const { data: agents } = useAgents(undefined, appId, selectedEnv);
const { data: appConfig } = useApplicationConfig(appId);
const updateConfig = useUpdateApplicationConfig();
@@ -131,7 +133,7 @@ export default function AgentHealth() {
}, [appConfig, configDraft, updateConfig, toast, appId]);
const [eventSortAsc, setEventSortAsc] = useState(false);
const [eventRefreshTo, setEventRefreshTo] = useState<string | undefined>();
const { data: events } = useAgentEvents(appId, undefined, 50, eventRefreshTo);
const { data: events } = useAgentEvents(appId, undefined, 50, eventRefreshTo, selectedEnv);
const [logSearch, setLogSearch] = useState('');
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());

View File

@@ -15,6 +15,7 @@ import { useApplicationLogs } from '../../api/queries/logs';
import { useStatsTimeseries } from '../../api/queries/executions';
import { useAgentMetrics } from '../../api/queries/agent-metrics';
import { formatUptime, mapLogLevel, eventSeverity, eventIcon } from '../../utils/agent-utils';
import { useEnvironmentStore } from '../../api/environment-store';
const LOG_LEVEL_ITEMS: ButtonGroupItem[] = [
{ value: 'error', label: 'Error', color: 'var(--error)' },
@@ -36,9 +37,10 @@ export default function AgentInstance() {
const timeFrom = timeRange.start.toISOString();
const timeTo = timeRange.end.toISOString();
const { data: agents, isLoading } = useAgents(undefined, appId);
const { data: events } = useAgentEvents(appId, instanceId, 50, eventRefreshTo);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);
const selectedEnv = useEnvironmentStore((s) => s.environment);
const { data: agents, isLoading } = useAgents(undefined, appId, selectedEnv);
const { data: events } = useAgentEvents(appId, instanceId, 50, eventRefreshTo, selectedEnv);
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId, selectedEnv);
const agent = useMemo(
() => (agents || []).find((a: any) => a.instanceId === instanceId) as any,