fix: refresh buttons use "now" as to-date for queries
Instead of calling refetch() with stale time params, the refresh buttons now set a toOverride state to new Date().toISOString(). This flows into the query key, triggering a fresh fetch with the current time as the upper bound. Both useApplicationLogs and useAgentEvents hooks accept an optional toOverride parameter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,15 +19,16 @@ export function useAgents(status?: string, application?: string) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useAgentEvents(appId?: string, agentId?: string, limit = 50) {
|
export function useAgentEvents(appId?: string, agentId?: string, limit = 50, toOverride?: string) {
|
||||||
const refetchInterval = useRefreshInterval(15_000);
|
const refetchInterval = useRefreshInterval(15_000);
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['agents', 'events', appId, agentId, limit],
|
queryKey: ['agents', 'events', appId, agentId, limit, toOverride],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const token = useAuthStore.getState().accessToken;
|
const token = useAuthStore.getState().accessToken;
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (appId) params.set('appId', appId);
|
if (appId) params.set('appId', appId);
|
||||||
if (agentId) params.set('agentId', agentId);
|
if (agentId) params.set('agentId', agentId);
|
||||||
|
if (toOverride) params.set('to', toOverride);
|
||||||
params.set('limit', String(limit));
|
params.set('limit', String(limit));
|
||||||
const res = await fetch(`${config.apiBaseUrl}/agents/events-log?${params}`, {
|
const res = await fetch(`${config.apiBaseUrl}/agents/events-log?${params}`, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -16,20 +16,21 @@ export interface LogEntryResponse {
|
|||||||
export function useApplicationLogs(
|
export function useApplicationLogs(
|
||||||
application?: string,
|
application?: string,
|
||||||
agentId?: string,
|
agentId?: string,
|
||||||
options?: { limit?: number },
|
options?: { limit?: number; toOverride?: string },
|
||||||
) {
|
) {
|
||||||
const refetchInterval = useRefreshInterval(15_000);
|
const refetchInterval = useRefreshInterval(15_000);
|
||||||
const { timeRange } = useGlobalFilters();
|
const { timeRange } = useGlobalFilters();
|
||||||
|
const to = options?.toOverride ?? timeRange.end.toISOString();
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ['logs', application, agentId, timeRange.start.toISOString(), timeRange.end.toISOString(), options?.limit],
|
queryKey: ['logs', application, agentId, timeRange.start.toISOString(), to, options?.limit],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const token = useAuthStore.getState().accessToken;
|
const token = useAuthStore.getState().accessToken;
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
params.set('application', application!);
|
params.set('application', application!);
|
||||||
if (agentId) params.set('agentId', agentId);
|
if (agentId) params.set('agentId', agentId);
|
||||||
params.set('from', timeRange.start.toISOString());
|
params.set('from', timeRange.start.toISOString());
|
||||||
params.set('to', timeRange.end.toISOString());
|
params.set('to', to);
|
||||||
if (options?.limit) params.set('limit', String(options.limit));
|
if (options?.limit) params.set('limit', String(options.limit));
|
||||||
const res = await fetch(`${config.apiBaseUrl}/logs?${params}`, {
|
const res = await fetch(`${config.apiBaseUrl}/logs?${params}`, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -223,8 +223,9 @@ function AgentPerformanceContent({ agent }: { agent: AgentInstance }) {
|
|||||||
export default function AgentHealth() {
|
export default function AgentHealth() {
|
||||||
const { appId } = useParams();
|
const { appId } = useParams();
|
||||||
const { data: agents } = useAgents(undefined, appId);
|
const { data: agents } = useAgents(undefined, appId);
|
||||||
const { data: events, refetch: refetchEvents } = useAgentEvents(appId);
|
|
||||||
const [eventSortAsc, setEventSortAsc] = useState(false);
|
const [eventSortAsc, setEventSortAsc] = useState(false);
|
||||||
|
const [eventRefreshTo, setEventRefreshTo] = useState<string | undefined>();
|
||||||
|
const { data: events } = useAgentEvents(appId, undefined, 50, eventRefreshTo);
|
||||||
|
|
||||||
const [selectedInstance, setSelectedInstance] = useState<AgentInstance | null>(null);
|
const [selectedInstance, setSelectedInstance] = useState<AgentInstance | null>(null);
|
||||||
const [panelOpen, setPanelOpen] = useState(false);
|
const [panelOpen, setPanelOpen] = useState(false);
|
||||||
@@ -509,7 +510,7 @@ export default function AgentHealth() {
|
|||||||
<button className={styles.sortBtn} onClick={() => setEventSortAsc((v) => !v)} title={eventSortAsc ? 'Oldest first' : 'Newest first'}>
|
<button className={styles.sortBtn} onClick={() => setEventSortAsc((v) => !v)} title={eventSortAsc ? 'Oldest first' : 'Newest first'}>
|
||||||
{eventSortAsc ? '\u2191' : '\u2193'}
|
{eventSortAsc ? '\u2191' : '\u2193'}
|
||||||
</button>
|
</button>
|
||||||
<button className={styles.refreshBtn} onClick={() => refetchEvents()} title="Refresh">
|
<button className={styles.refreshBtn} onClick={() => setEventRefreshTo(new Date().toISOString())} title="Refresh">
|
||||||
↻
|
↻
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,11 +35,13 @@ export default function AgentInstance() {
|
|||||||
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());
|
const [logLevels, setLogLevels] = useState<Set<string>>(new Set());
|
||||||
const [logSortAsc, setLogSortAsc] = useState(false);
|
const [logSortAsc, setLogSortAsc] = useState(false);
|
||||||
const [eventSortAsc, setEventSortAsc] = useState(false);
|
const [eventSortAsc, setEventSortAsc] = useState(false);
|
||||||
|
const [logRefreshTo, setLogRefreshTo] = useState<string | undefined>();
|
||||||
|
const [eventRefreshTo, setEventRefreshTo] = useState<string | undefined>();
|
||||||
const timeFrom = timeRange.start.toISOString();
|
const timeFrom = timeRange.start.toISOString();
|
||||||
const timeTo = timeRange.end.toISOString();
|
const timeTo = timeRange.end.toISOString();
|
||||||
|
|
||||||
const { data: agents, isLoading } = useAgents(undefined, appId);
|
const { data: agents, isLoading } = useAgents(undefined, appId);
|
||||||
const { data: events, refetch: refetchEvents } = useAgentEvents(appId, instanceId);
|
const { data: events } = useAgentEvents(appId, instanceId, 50, eventRefreshTo);
|
||||||
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);
|
const { data: timeseries } = useStatsTimeseries(timeFrom, timeTo, undefined, appId);
|
||||||
|
|
||||||
const agent = useMemo(
|
const agent = useMemo(
|
||||||
@@ -137,7 +139,7 @@ export default function AgentInstance() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Application logs from OpenSearch
|
// Application logs from OpenSearch
|
||||||
const { data: rawLogs, refetch: refetchLogs } = useApplicationLogs(appId, instanceId);
|
const { data: rawLogs } = useApplicationLogs(appId, instanceId, { toOverride: logRefreshTo });
|
||||||
const logEntries = useMemo<LogEntry[]>(() => {
|
const logEntries = useMemo<LogEntry[]>(() => {
|
||||||
const mapped = (rawLogs || []).map((l) => ({
|
const mapped = (rawLogs || []).map((l) => ({
|
||||||
timestamp: l.timestamp ?? '',
|
timestamp: l.timestamp ?? '',
|
||||||
@@ -402,7 +404,7 @@ export default function AgentInstance() {
|
|||||||
<button className={styles.sortBtn} onClick={() => setLogSortAsc((v) => !v)} title={logSortAsc ? 'Oldest first' : 'Newest first'}>
|
<button className={styles.sortBtn} onClick={() => setLogSortAsc((v) => !v)} title={logSortAsc ? 'Oldest first' : 'Newest first'}>
|
||||||
{logSortAsc ? '\u2191' : '\u2193'}
|
{logSortAsc ? '\u2191' : '\u2193'}
|
||||||
</button>
|
</button>
|
||||||
<button className={styles.refreshBtn} onClick={() => refetchLogs()} title="Refresh">
|
<button className={styles.refreshBtn} onClick={() => setLogRefreshTo(new Date().toISOString())} title="Refresh">
|
||||||
↻
|
↻
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -452,7 +454,7 @@ export default function AgentInstance() {
|
|||||||
<button className={styles.sortBtn} onClick={() => setEventSortAsc((v) => !v)} title={eventSortAsc ? 'Oldest first' : 'Newest first'}>
|
<button className={styles.sortBtn} onClick={() => setEventSortAsc((v) => !v)} title={eventSortAsc ? 'Oldest first' : 'Newest first'}>
|
||||||
{eventSortAsc ? '\u2191' : '\u2193'}
|
{eventSortAsc ? '\u2191' : '\u2193'}
|
||||||
</button>
|
</button>
|
||||||
<button className={styles.refreshBtn} onClick={() => refetchEvents()} title="Refresh">
|
<button className={styles.refreshBtn} onClick={() => setEventRefreshTo(new Date().toISOString())} title="Refresh">
|
||||||
↻
|
↻
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user