diff --git a/console/src/api/materialize/MaterializeWebsocket.ts b/console/src/api/materialize/MaterializeWebsocket.ts index d09437e871f5c..f8d406b932906 100644 --- a/console/src/api/materialize/MaterializeWebsocket.ts +++ b/console/src/api/materialize/MaterializeWebsocket.ts @@ -39,6 +39,8 @@ export class MaterializeWebsocket implements Connectable { onMessage: MessageCallback | undefined; onClose: CloseCallback | undefined; onOpen: OpenCallback | undefined; + /** Optional diagnostic label for console logging. */ + debugLabel: string | undefined; constructor(options: { httpAddress: string; @@ -47,6 +49,7 @@ export class MaterializeWebsocket implements Connectable { onMessage?: MessageCallback; onClose?: CloseCallback; onOpen?: OpenCallback; + debugLabel?: string; }) { this.httpAddress = options.httpAddress; this.sessionVariables = options.sessionVariables ?? {}; @@ -54,12 +57,20 @@ export class MaterializeWebsocket implements Connectable { this.onMessage = options.onMessage; this.onClose = options.onClose; this.onOpen = options.onOpen; + this.debugLabel = options.debugLabel; } connect(httpAddress?: string, sessionVariables?: SessionVariables) { this.httpAddress = httpAddress ?? this.httpAddress; this.sessionVariables = sessionVariables ?? this.sessionVariables; + const priorState = this.socket?.readyState; this.disconnect(); + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[ws:${this.debugLabel}] connect (priorReadyState=${priorState}) -> ${this.httpAddress}`, + ); + } this.socket = new WebSocket( `${apiClient.mzWebsocketUrlScheme}://${this.httpAddress}/api/experimental/sql`, ); @@ -70,6 +81,12 @@ export class MaterializeWebsocket implements Connectable { } disconnect() { + if (this.debugLabel && this.socket) { + // eslint-disable-next-line no-console + console.log( + `[ws:${this.debugLabel}] disconnect (readyState=${this.socket.readyState})`, + ); + } this.setState({ readyForQuery: false, error: undefined, @@ -159,6 +176,10 @@ export class MaterializeWebsocket implements Connectable { } private handleOpen = (event: Event) => { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log(`[ws:${this.debugLabel}] open`); + } this.onOpen?.(event); // Notify open listeners (used by WebsocketConnectionManager to update state) for (const callback of this.openListeners) { @@ -187,6 +208,10 @@ export class MaterializeWebsocket implements Connectable { }; private handleError = () => { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log(`[ws:${this.debugLabel}] error event (readyState=${this.socket?.readyState})`); + } this.setState({ error: "Socket error", }); @@ -196,6 +221,12 @@ export class MaterializeWebsocket implements Connectable { }; private handleClose = (event: CloseEvent) => { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[ws:${this.debugLabel}] close code=${event.code} wasClean=${event.wasClean} reason=${event.reason || "(none)"}`, + ); + } this.setState({ readyForQuery: false, error: "Connection closed unexpectedly", diff --git a/console/src/api/materialize/SubscribeManager.ts b/console/src/api/materialize/SubscribeManager.ts index b47ac2bd0cbbc..e43119aa15425 100644 --- a/console/src/api/materialize/SubscribeManager.ts +++ b/console/src/api/materialize/SubscribeManager.ts @@ -63,6 +63,11 @@ export interface SubscribeManagerOptions< flushInterval?: number; upsert?: UpsertSubscribeOptions; select?: SelectFunction; + /** + * If set, every raw WebSocket message and every buffer flush is logged to + * the console, prefixed with this label. Intended for diagnostics only. + */ + debugLabel?: string; } export type SelectFunction = (row: SubscribeRow) => R; @@ -104,8 +109,18 @@ export class SubscribeManager implements Connectable { private flushIntervalHandle: NodeJS.Timeout | undefined; private flushInterval: number = 16; + /** Optional diagnostic label exposed so external hooks (e.g. + * useAutomaticallyConnectSocket) can correlate logs. */ + debugLabel: string | undefined; constructor(options: SubscribeManagerOptions) { + this.debugLabel = options.debugLabel; + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] constructed (hasRequest=${!!options.request})`, + ); + } this.socket = new MaterializeWebsocket({ httpAddress: options.httpAddress, sessionVariables: buildSessionVariables({ @@ -115,6 +130,7 @@ export class SubscribeManager implements Connectable { onMessage: this.onMessage, onClose: this.onClose, onOpen: this.onOpen, + debugLabel: options.debugLabel, }); this.upsert = options.upsert; this.closeSocketOnComplete = options.closeSocketOnComplete ?? false; @@ -182,6 +198,12 @@ export class SubscribeManager implements Connectable { } reset = () => { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] reset (snapshotComplete -> false)`, + ); + } this.columns = []; this.querySent = false; this.closedTimestampBuffer = []; @@ -216,10 +238,31 @@ export class SubscribeManager implements Connectable { }; private setState(update: Partial>>) { + const prevSnapshotComplete = this.currentState.snapshotComplete; + const prevDataLen = this.currentState.data.length; this.currentState = { ...this.currentState, ...update, }; + if ( + this.debugLabel && + prevSnapshotComplete !== this.currentState.snapshotComplete + ) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] snapshotComplete: ${prevSnapshotComplete} -> ${this.currentState.snapshotComplete} (data.length=${this.currentState.data.length}, listeners=${this.listeners.size})`, + ); + } + if ( + this.debugLabel && + prevDataLen !== this.currentState.data.length && + this.currentState.snapshotComplete + ) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] data.length: ${prevDataLen} -> ${this.currentState.data.length}`, + ); + } // We need to have the snapshot state as a separate object and not just a derived copy of this.currentState because // React.useSyncExternalStore requires a stable reference of the snapshot state, otherwise it will enter an infinite render loop. this.snapshotState = { @@ -235,16 +278,34 @@ export class SubscribeManager implements Connectable { private onReadyForQuery = () => { if (this.querySent && this.closeSocketOnComplete) { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] onReadyForQuery: closing (closeSocketOnComplete)`, + ); + } this.socket.disconnect(); return; } if (this.sqlRequest) { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] onReadyForQuery: sending SUBSCRIBE (querySent->true)`, + ); + } this.socket.send(this.sqlRequest); this.querySent = true; } }; private onClose = (event: CloseEvent) => { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] onClose code=${event.code}`, + ); + } this.setState({ error: { code: SUBSCRIBE_ERROR_CODE.CONNECTION_CLOSED, @@ -254,6 +315,16 @@ export class SubscribeManager implements Connectable { }; private onMessage = (message: WebSocketResult) => { + if (this.debugLabel && message.type !== "Row") { + // Row messages get logged in detail inside onRow as state-machine steps; + // everything else (Error, Rows-with-columns, ReadyForQuery, etc.) is logged here. + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] msg`, + message.type, + message.payload, + ); + } if (message.type === "Error") { captureException( new Error(`Subscribe error: ${JSON.stringify(message.payload)}`), @@ -276,31 +347,69 @@ export class SubscribeManager implements Connectable { private onRow = (payload: unknown[]) => { // If querySent is false, it means we are still getting results from a previous // query, ignore the data. - if (!this.querySent) return; + if (!this.querySent) { + if (this.debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] onRow skipped (querySent=false)`, + ); + } + return; + } const meta = extractSubscribeMetadata(payload, this.columns); + const before = { + currentTimestamp: this.currentTimestamp, + currentTimestampType: typeof this.currentTimestamp, + snapshotComplete: this.currentState.snapshotComplete, + }; + const trace: string[] = []; + if (this.currentTimestamp && meta.mzTimestamp > this.currentTimestamp) { // this timestamp is complete, flush it const updates = this.currentTimestampBuffer.get(this.currentTimestamp); if (updates) { this.closedTimestampBuffer.push(...updates); this.currentTimestampBuffer.delete(this.currentTimestamp); + trace.push( + `advance(${this.currentTimestamp}->${meta.mzTimestamp}): flushed ${updates.length} to closed`, + ); + } else { + trace.push( + `advance(${this.currentTimestamp}->${meta.mzTimestamp}): no buffer for prev`, + ); } + } else if (this.debugLabel && this.currentTimestamp) { + // Helpful when timestamps are equal or compare wrong (e.g. string-compare bug): + trace.push( + `noadvance: cmp(${this.currentTimestamp} ${typeof this.currentTimestamp}, ${meta.mzTimestamp} ${typeof meta.mzTimestamp}) -> ${meta.mzTimestamp > this.currentTimestamp}`, + ); + } else if (this.debugLabel) { + trace.push(`noadvance: currentTimestamp not set`); } // Once we've received a second progress message, we know we've received // the initial snapshot. + const snapshotGateChecked = + meta.mzProgressed && !this.currentState.snapshotComplete; if ( meta.mzProgressed && this.currentTimestamp && !this.currentState.snapshotComplete ) { // Eagerly flush the buffer to make the snapshot available. + trace.push(`snapshotGate: FIRING (flushing+setting snapshotComplete)`); this.flushSocketBuffer(); this.setState({ snapshotComplete: true, }); + } else if (snapshotGateChecked) { + // mzProgressed && !snapshotComplete but currentTimestamp falsy -> gate blocked + trace.push( + `snapshotGate: BLOCKED (currentTimestamp=${String(this.currentTimestamp)})`, + ); } + // Track the new currently open timestamp. this.currentTimestamp = meta.mzTimestamp; const row = mapRowToObject(payload, this.columns, [ @@ -314,11 +423,65 @@ export class SubscribeManager implements Connectable { data: row, }); this.currentTimestampBuffer.set(meta.mzTimestamp, updates); + + if (this.debugLabel) { + // Only log onRow at interesting transitions, not for every progress tick: + // - before snapshot completes (every row is potentially relevant) + // - when mzState is non-null (real data: upsert/delete/key_violation) + // - when the snapshot-completion gate is firing or blocked + const interesting = + !before.snapshotComplete || + meta.mzState !== null || + trace.some((t) => t.startsWith("snapshotGate")); + if (interesting) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] onRow`, + { + mzTimestamp: meta.mzTimestamp, + mzProgressed: meta.mzProgressed, + mzState: meta.mzState, + }, + "before=", + before, + "after=", + { + currentTimestamp: this.currentTimestamp, + snapshotComplete: this.currentState.snapshotComplete, + }, + trace.length ? trace : undefined, + ); + } + } }; private flushSocketBuffer = () => { if (this.closedTimestampBuffer.length === 0) return; + if (this.debugLabel) { + const stateCounts = this.closedTimestampBuffer.reduce< + Record + >((acc, r) => { + const k = String(r.mzState); + acc[k] = (acc[k] ?? 0) + 1; + return acc; + }, {}); + const hasRealData = this.closedTimestampBuffer.some( + (r) => r.mzState !== null, + ); + if (hasRealData || !this.currentState.snapshotComplete) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${this.debugLabel}] flush`, + this.closedTimestampBuffer.length, + "rows by mz_state=", + stateCounts, + "snapshotComplete=", + this.currentState.snapshotComplete, + ); + } + } + const clearBuffer = () => { this.closedTimestampBuffer = []; }; diff --git a/console/src/api/materialize/useSubscribe.ts b/console/src/api/materialize/useSubscribe.ts index 8fc625cef59e5..de518314184a9 100644 --- a/console/src/api/materialize/useSubscribe.ts +++ b/console/src/api/materialize/useSubscribe.ts @@ -34,6 +34,11 @@ export type UseSubscribeOptions = { closeSocketOnComplete?: boolean; clusterName?: string; select?: SelectFunction; + /** + * If set, every raw WebSocket message and buffer flush for this subscribe + * is logged to the console, prefixed with this label. Diagnostics only. + */ + debugLabel?: string; }; export type UseSubscribeReturn = { @@ -65,18 +70,20 @@ export function useSubscribe>( const httpAddress = useCurrentEnvironmentHttpAddress(); const request = useSubscribeRequest(options.subscribe); const [subscribe] = React.useState( - new SubscribeManager({ - request, - httpAddress, - upsert: { - key: options.upsertKey, - }, - select: options.select, - sessionVariables: { - cluster: options.clusterName, - }, - closeSocketOnComplete: options.closeSocketOnComplete, - }), + () => + new SubscribeManager({ + request, + httpAddress, + upsert: { + key: options.upsertKey, + }, + select: options.select, + sessionVariables: { + cluster: options.clusterName, + }, + closeSocketOnComplete: options.closeSocketOnComplete, + debugLabel: options.debugLabel, + }), ); useAutomaticallyConnectSocket({ target: subscribe, @@ -119,18 +126,20 @@ export function useGlobalUpsertSubscribe>( const httpAddress = useCurrentEnvironmentHttpAddress(); const request = useSubscribeRequest(options.subscribe); const [subscribe] = React.useState( - new SubscribeManager({ - request, - httpAddress, - upsert: { - key: options.upsertKey, - }, - sessionVariables: { - cluster: options?.clusterName, - }, - closeSocketOnComplete: options?.closeSocketOnComplete, - select: options.select, - }), + () => + new SubscribeManager({ + request, + httpAddress, + upsert: { + key: options.upsertKey, + }, + sessionVariables: { + cluster: options?.clusterName, + }, + closeSocketOnComplete: options?.closeSocketOnComplete, + select: options.select, + debugLabel: options.debugLabel, + }), ); useAutomaticallyConnectSocket({ target: subscribe, @@ -138,15 +147,44 @@ export function useGlobalUpsertSubscribe>( request, }); + const debugLabel = options.debugLabel; React.useEffect(() => { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${debugLabel}] atom-listener attached`, + ); + } const cleanup = subscribe.onChange(() => { const snapshot = subscribe.getSnapshot(); - if (getStore().get(options.atom) === snapshot) return; + if (getStore().get(options.atom) === snapshot) { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${debugLabel}] atom-set SKIPPED (reference unchanged)`, + ); + } + return; + } + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${debugLabel}] atom-set snapshotComplete=${snapshot.snapshotComplete} data.length=${(snapshot.data as unknown[]).length} error=${snapshot.error ? snapshot.error.code : "none"}`, + ); + } setValue(snapshot); }); - return cleanup; - }, [options.atom, setValue, subscribe]); + return () => { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[subscribe:${debugLabel}] atom-listener detached`, + ); + } + cleanup(); + }; + }, [options.atom, setValue, subscribe, debugLabel]); return { subscribe, @@ -170,15 +208,16 @@ export function useSubscribeManager>({ const httpAddress = useCurrentEnvironmentHttpAddress(); const request = useSubscribeRequest(subscribe); const [subscribeInstance] = React.useState( - new SubscribeManager({ - request, - httpAddress, - sessionVariables: { - cluster: options?.clusterName, - }, - closeSocketOnComplete: options?.closeSocketOnComplete, - select: options?.select, - }), + () => + new SubscribeManager({ + request, + httpAddress, + sessionVariables: { + cluster: options?.clusterName, + }, + closeSocketOnComplete: options?.closeSocketOnComplete, + select: options?.select, + }), ); useAutomaticallyConnectSocket({ target: subscribeInstance, diff --git a/console/src/hooks/useAutomaticallyConnectSocket.ts b/console/src/hooks/useAutomaticallyConnectSocket.ts index b1626797911ae..9ceab4cf82cdb 100644 --- a/console/src/hooks/useAutomaticallyConnectSocket.ts +++ b/console/src/hooks/useAutomaticallyConnectSocket.ts @@ -56,9 +56,14 @@ export const useAutomaticallyConnectSocket = ({ const reconnectionState = useAtomValue(reconnectionStateAtom); const managerRef = useRef(null); const getSessionVariablesRef = useLatestRef(getSessionVariables); + const debugLabel = subscribe?.debugLabel; // Manager lifecycle - create on mount/target change, destroy on cleanup React.useEffect(() => { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log(`[uacs:${debugLabel}] effect-mgr: creating WebsocketConnectionManager`); + } managerRef.current = new WebsocketConnectionManager( target, store, @@ -69,20 +74,63 @@ export const useAutomaticallyConnectSocket = ({ ); return () => { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log(`[uacs:${debugLabel}] effect-mgr: destroying WebsocketConnectionManager`); + } managerRef.current?.destroy(); managerRef.current = null; }; - }, [target, store, getSessionVariablesRef]); + }, [target, store, getSessionVariablesRef, debugLabel]); // Handle request changes for subscribe queries const currentEnvironment = useAtomValue(currentEnvironmentState); const previousRequest = usePrevious(request); React.useEffect(() => { - if (!subscribe || !request) return; - if (previousRequest === request) return; - if (currentEnvironment?.state !== "enabled") return; + if (!subscribe || !request) { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[uacs:${debugLabel}] effect-req: skip (subscribe=${!!subscribe} request=${!!request})`, + ); + } + return; + } + if (previousRequest === request) { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log(`[uacs:${debugLabel}] effect-req: skip (request unchanged)`); + } + return; + } + // On first mount previousRequest is undefined; the manager's constructor + // already initiates a connect using the request captured at construction + // time. Re-connecting here would race with that and tear the still- + // CONNECTING socket down. + if (previousRequest === undefined) { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[uacs:${debugLabel}] effect-req: skip (first mount; manager handles initial connect)`, + ); + } + return; + } + if (currentEnvironment?.state !== "enabled") { + if (debugLabel) { + // eslint-disable-next-line no-console + console.log( + `[uacs:${debugLabel}] effect-req: skip (env state=${currentEnvironment?.state})`, + ); + } + return; + } + if (debugLabel) { + // eslint-disable-next-line no-console + console.log(`[uacs:${debugLabel}] effect-req: calling subscribe.connect()`); + } subscribe.connect( request, currentEnvironment.httpAddress, @@ -94,6 +142,7 @@ export const useAutomaticallyConnectSocket = ({ previousRequest, currentEnvironment, getSessionVariablesRef, + debugLabel, ]); return { reconnectionState }; diff --git a/console/src/platform/object-explorer/ObjectExplorer.tsx b/console/src/platform/object-explorer/ObjectExplorer.tsx index 7aa39a134b4e8..e46b3c0cccdca 100644 --- a/console/src/platform/object-explorer/ObjectExplorer.tsx +++ b/console/src/platform/object-explorer/ObjectExplorer.tsx @@ -138,6 +138,22 @@ export const ObjectExplorer = () => { snapshotComplete: objectSnapshotComplete, isError: isObjectError, } = useAllObjects(); + // eslint-disable-next-line no-console + console.log( + "[object-explorer] render gating:", + "schemaSnapshotComplete=", + schemaSnapshotComplete, + "objectSnapshotComplete=", + objectSnapshotComplete, + "isSchemaError=", + isSchemaError, + "isObjectError=", + isObjectError, + "schemas.length=", + schemas.length, + "objects.length=", + objects.length, + ); const location = useLocation(); const { colors } = useTheme(); const params = useParams(); diff --git a/console/src/platform/object-explorer/allNamespaces.ts b/console/src/platform/object-explorer/allNamespaces.ts index 365ddafc86ed3..0a5da47426b54 100644 --- a/console/src/platform/object-explorer/allNamespaces.ts +++ b/console/src/platform/object-explorer/allNamespaces.ts @@ -48,6 +48,7 @@ export function useSubscribeToAllNamespaces() { databaseId: row.data.databaseId, schemaId: row.data.schemaId, }), + debugLabel: "object-explorer:allNamespaces", }); } diff --git a/console/src/platform/object-explorer/queries.ts b/console/src/platform/object-explorer/queries.ts index bc38c63a5c68a..fd202d48ff677 100644 --- a/console/src/platform/object-explorer/queries.ts +++ b/console/src/platform/object-explorer/queries.ts @@ -40,6 +40,26 @@ import { } from "~/api/materialize/object-explorer/schemaDetails"; import { fetchIsOwner, IsOwnerParameters } from "~/api/materialize/objects"; +/** Diagnostic helper: logs the resolved value of a fetch and rethrows on error. */ +const logObjectExplorerResponse = async ( + label: string, + params: unknown, + promise: Promise, +): Promise => { + // eslint-disable-next-line no-console + console.log(`[object-explorer:${label}] request`, params); + try { + const result = await promise; + // eslint-disable-next-line no-console + console.log(`[object-explorer:${label}] response`, result); + return result; + } catch (err) { + // eslint-disable-next-line no-console + console.log(`[object-explorer:${label}] error`, err); + throw err; + } +}; + export const objectExplorerQueryKeys = { all: () => buildRegionQueryKey("object-explorer"), columns: (params: ObjectExplorerColumnsParameters) => @@ -85,11 +105,15 @@ export const useDatabaseDetails = (params: DatabaseDetailsParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - const result = await fetchDatabaseDetails({ - queryKey, + const result = await logObjectExplorerResponse( + "databaseDetails", parameters, - requestOptions: { signal }, - }); + fetchDatabaseDetails({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); assertExactlyOneRow(result.rows.length, { skipQueryRetry: true }); return result; }, @@ -103,11 +127,15 @@ export const useSchemaDetails = (params: SchemaDetailsParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - const result = await fetchSchemaDetails({ - queryKey, + const result = await logObjectExplorerResponse( + "schemaDetails", parameters, - requestOptions: { signal }, - }); + fetchSchemaDetails({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); assertExactlyOneRow(result.rows.length, { skipQueryRetry: true }); return result; }, @@ -121,11 +149,15 @@ export const useObjectDetails = (params: ObjectExplorerDetailsParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - const result = await fetchObjectDetails({ - queryKey, + const result = await logObjectExplorerResponse( + "objectDetails", parameters, - requestOptions: { signal }, - }); + fetchObjectDetails({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); assertExactlyOneRow(result.rows.length, { skipQueryRetry: true }); return result; }, @@ -139,11 +171,15 @@ export const useObjectColumns = (params: ObjectExplorerColumnsParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - return fetchObjectColumns({ - queryKey, + return logObjectExplorerResponse( + "objectColumns", parameters, - requestOptions: { signal }, - }); + fetchObjectColumns({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); }, }); }; @@ -154,11 +190,15 @@ export const useObjectIndexes = (params: ObjectIndexesParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - return fetchObjectIndexes({ - queryKey, + return logObjectExplorerResponse( + "objectIndexes", parameters, - requestOptions: { signal }, - }); + fetchObjectIndexes({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); }, }); }; @@ -169,11 +209,15 @@ export const useIsOwner = (params: IsOwnerParameters) => { queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - const result = await fetchIsOwner({ - queryKey, + const result = await logObjectExplorerResponse( + "isOwner", parameters, - requestOptions: { signal }, - }); + fetchIsOwner({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); assertExactlyOneRow(result.rows.length, { skipQueryRetry: true }); return result.rows[0].isOwner; }, @@ -188,11 +232,15 @@ export const useConnectionDependencies = ( queryFn: async ({ queryKey, signal }) => { const [, parameters] = queryKey; - return fetchConnectionDependencies({ - queryKey, + return logObjectExplorerResponse( + "connectionDependencies", parameters, - requestOptions: { signal }, - }); + fetchConnectionDependencies({ + queryKey, + parameters, + requestOptions: { signal }, + }), + ); }, select: (data) => data.rows, }); diff --git a/console/src/store/allObjects.ts b/console/src/store/allObjects.ts index 549e56365a804..e04061790d1a6 100644 --- a/console/src/store/allObjects.ts +++ b/console/src/store/allObjects.ts @@ -36,6 +36,7 @@ export function useSubscribeToAllObjects() { subscribe, select: (row) => row.data, upsertKey: (row) => row.data.id, + debugLabel: "object-explorer:allObjects", }); }