Skip to content

Commit 3f3c572

Browse files
authored
Merge pull request #46 from viamrobotics/add-debugger
Add optional query logger
2 parents 67294b2 + 052f96b commit 3f3c572

13 files changed

+308
-27
lines changed

.changeset/flat-candles-cry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@viamrobotics/svelte-sdk': patch
3+
---
4+
5+
Add configurable query logging.

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,40 @@ let { partID, name }: Props = $props();
264264
/>
265265
```
266266

267+
## Debugging
268+
269+
### Query Logger
270+
271+
Enables query and mutation logs to the browser console. It can be set at with the `<ViamProvider />` or with `window` functions:
272+
273+
```svelte
274+
<!-- enable query logging -->
275+
<ViamProvider
276+
{dialConfigs}
277+
logQueries
278+
>
279+
{@render children()}
280+
</ViamProvider>
281+
282+
<!-- enable verbose query logging -->
283+
<ViamProvider
284+
{dialConfigs}
285+
logQueries={{ enabled: true, verbose: true }}
286+
>
287+
{@render children()}
288+
</ViamProvider>
289+
```
290+
291+
```js
292+
// enable/disable query logging
293+
window.enableQueryLogging();
294+
window.disableQueryLogging();
295+
296+
// enable/disable verbose query logging
297+
window.enableVerboseQueryLogging();
298+
window.disableVerboseQueryLogging();
299+
```
300+
267301
## Developing
268302

269303
First install dependencies with `pnpm install`, then start a development server:

src/app.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ declare global {
88
// interface PageState {}
99
// interface Platform {}
1010
}
11+
12+
interface Window {
13+
enableQueryLogging?: () => unknown;
14+
disableQueryLogging?: () => unknown;
15+
enableVerboseQueryLogging?: () => unknown;
16+
disableVerboseQueryLogging?: () => unknown;
17+
}
1118
}
1219

1320
export {};

src/lib/components/provider.svelte

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,57 @@ import type { Snippet } from 'svelte';
33
import { QueryClientProvider, QueryClient } from '@tanstack/svelte-query';
44
import type { DialConf } from '@viamrobotics/sdk';
55
import InternalProvider from './internal-provider.svelte';
6+
import {
7+
enableQueryLogging,
8+
disableQueryLogging,
9+
enableVerboseQueryLogging,
10+
disableVerboseQueryLogging,
11+
} from '../query-logger';
612
713
interface Props {
814
dialConfigs: Record<string, DialConf>;
915
client?: QueryClient;
1016
machineStatusRefetchInterval?: number;
17+
logQueries?:
18+
| boolean
19+
| {
20+
enabled: boolean;
21+
verbose?: boolean;
22+
};
1123
children: Snippet;
1224
}
1325
1426
let {
1527
dialConfigs,
1628
client = new QueryClient(),
1729
machineStatusRefetchInterval,
30+
logQueries,
1831
children,
1932
}: Props = $props();
33+
34+
$effect(() => {
35+
if (typeof logQueries === 'boolean') {
36+
logQueries = { enabled: logQueries };
37+
}
38+
39+
if (logQueries?.enabled) {
40+
enableQueryLogging();
41+
} else {
42+
disableQueryLogging();
43+
}
44+
});
45+
46+
$effect(() => {
47+
if (typeof logQueries === 'boolean') {
48+
return;
49+
}
50+
51+
if (logQueries?.verbose) {
52+
enableVerboseQueryLogging();
53+
} else {
54+
disableVerboseQueryLogging();
55+
}
56+
});
2057
</script>
2158

2259
<QueryClientProvider {client}>

src/lib/hooks/create-resource-mutation.svelte.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
ResolvedReturnType,
77
} from './create-resource-query.svelte';
88
import { fromStore, toStore } from 'svelte/store';
9+
import { useQueryLogger } from '$lib/query-logger';
910

1011
export const createResourceMutation = <T extends Resource, K extends keyof T>(
1112
client: { current: T | undefined },
@@ -14,14 +15,19 @@ export const createResourceMutation = <T extends Resource, K extends keyof T>(
1415
type MutArgs = ArgumentsType<T[K]>;
1516
type MutReturn = ResolvedReturnType<T[K]>;
1617

18+
const debug = useQueryLogger();
19+
20+
const name = $derived(client.current?.name);
21+
const methodName = $derived(String(method));
22+
1723
const mutationOptions = $derived({
1824
mutationKey: [
1925
'viam-svelte-sdk',
2026
'partID',
2127
(client.current as T & { partID: string })?.partID,
2228
'resource',
23-
client.current?.name,
24-
String(method),
29+
name,
30+
methodName,
2531
],
2632
mutationFn: async (request) => {
2733
const clientFunc = client.current?.[method];
@@ -32,7 +38,21 @@ export const createResourceMutation = <T extends Resource, K extends keyof T>(
3238
);
3339
}
3440

35-
return clientFunc.apply(client.current, request) as Promise<MutReturn>;
41+
const logger = debug.createLogger();
42+
logger('REQ', name, methodName, request);
43+
44+
try {
45+
const response = (await clientFunc.apply(
46+
client.current,
47+
request
48+
)) as Promise<MutReturn>;
49+
50+
logger('RES', name, methodName, response);
51+
return response;
52+
} catch (error) {
53+
logger('ERR', name, methodName, error);
54+
throw error;
55+
}
3656
},
3757
} satisfies MutationOptions<MutReturn, Error, MutArgs>);
3858

src/lib/hooks/create-resource-query.svelte.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import type { Resource } from '@viamrobotics/sdk';
77
import { toStore, fromStore } from 'svelte/store';
88
import { usePolling } from './use-polling.svelte';
9+
import { useQueryLogger } from '../query-logger';
910

1011
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1112
export type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
@@ -34,6 +35,8 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
3435
]
3536
| [options?: (() => QueryOptions) | QueryOptions]
3637
): { current: QueryObserverResult<ResolvedReturnType<T[K]>> } => {
38+
const debug = useQueryLogger();
39+
3740
let [args, options] = additional;
3841

3942
if (options === undefined && args !== undefined) {
@@ -45,6 +48,8 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
4548
typeof options === 'function' ? options() : options
4649
);
4750
const _args = $derived(typeof args === 'function' ? args() : args);
51+
const name = $derived(client.current?.name);
52+
const methodName = $derived(String(method));
4853

4954
const queryOptions = $derived(
5055
createQueryOptions({
@@ -53,8 +58,8 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
5358
'partID',
5459
(client.current as T & { partID: string })?.partID,
5560
'resource',
56-
client.current?.name,
57-
String(method),
61+
name,
62+
methodName,
5863
...(_args ? [_args] : []),
5964
],
6065
enabled: client.current !== undefined && _options?.enabled !== false,
@@ -68,9 +73,21 @@ export const createResourceQuery = <T extends Resource, K extends keyof T>(
6873
);
6974
}
7075

71-
return clientFunc?.apply(client.current, _args) as Promise<
72-
ResolvedReturnType<T[K]>
73-
>;
76+
const logger = debug.createLogger();
77+
logger('REQ', name, methodName, _args);
78+
79+
try {
80+
const response = (await clientFunc?.apply(
81+
client.current,
82+
_args
83+
)) as Promise<ResolvedReturnType<T[K]>>;
84+
85+
logger('RES', name, methodName, response);
86+
return response;
87+
} catch (error) {
88+
logger('ERR', name, methodName, error);
89+
throw error;
90+
}
7491
},
7592
..._options,
7693
refetchInterval: false,

src/lib/hooks/create-robot-mutation.svelte.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
ResolvedReturnType,
77
} from './create-resource-query.svelte';
88
import { fromStore, toStore } from 'svelte/store';
9+
import { useQueryLogger } from '$lib/query-logger';
910

1011
export const createRobotMutation = <T extends RobotClient, K extends keyof T>(
1112
client: { current: T | undefined },
@@ -14,13 +15,17 @@ export const createRobotMutation = <T extends RobotClient, K extends keyof T>(
1415
type MutArgs = ArgumentsType<T[K]>;
1516
type MutReturn = ResolvedReturnType<T[K]>;
1617

18+
const debug = useQueryLogger();
19+
20+
const methodName = $derived(String(method));
21+
1722
const mutationOptions = $derived({
1823
mutationKey: [
1924
'viam-svelte-sdk',
2025
'partID',
2126
(client.current as T & { partID: string })?.partID,
2227
'robotClient',
23-
String(method),
28+
methodName,
2429
],
2530
mutationFn: async (request) => {
2631
const clientFunc = client.current?.[method];
@@ -31,7 +36,21 @@ export const createRobotMutation = <T extends RobotClient, K extends keyof T>(
3136
);
3237
}
3338

34-
return clientFunc.apply(client.current, request) as Promise<MutReturn>;
39+
const logger = debug.createLogger();
40+
logger('REQ', 'robot', methodName, request);
41+
42+
try {
43+
const response = (await clientFunc.apply(
44+
client.current,
45+
request
46+
)) as Promise<MutReturn>;
47+
48+
logger('RES', 'robot', methodName, response);
49+
return response;
50+
} catch (error) {
51+
logger('ERR', 'robot', methodName, error);
52+
throw error;
53+
}
3554
},
3655
} satisfies MutationOptions<MutReturn, Error, MutArgs>);
3756

src/lib/hooks/create-robot-query.svelte.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import type { RobotClient } from '@viamrobotics/sdk';
88
import { toStore, fromStore } from 'svelte/store';
99
import { usePolling } from './use-polling.svelte';
10+
import { useQueryLogger } from '$lib/query-logger';
1011

1112
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1213
export type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
@@ -35,6 +36,7 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
3536
]
3637
| [options?: (() => QueryOptions) | QueryOptions]
3738
): { current: QueryObserverResult<ResolvedReturnType<T[K]>> } => {
39+
const debug = useQueryLogger();
3840
let [args, options] = additional;
3941

4042
if (options === undefined && args !== undefined) {
@@ -46,6 +48,7 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
4648
typeof options === 'function' ? options() : options
4749
);
4850
const _args = $derived(typeof args === 'function' ? args() : args);
51+
const methodName = $derived(String(method));
4952

5053
const queryOptions = $derived(
5154
createQueryOptions({
@@ -54,7 +57,7 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
5457
'partID',
5558
(client.current as T & { partID: string })?.partID,
5659
'robotClient',
57-
String(method),
60+
methodName,
5861
...(_args ? [_args] : []),
5962
],
6063
enabled: client.current !== undefined && _options?.enabled !== false,
@@ -68,10 +71,21 @@ export const createRobotQuery = <T extends RobotClient, K extends keyof T>(
6871
);
6972
}
7073

71-
// Call entity.resource.func(args).
72-
return clientFunc?.apply(client.current, _args) as Promise<
73-
ResolvedReturnType<T[K]>
74-
>;
74+
const logger = debug.createLogger();
75+
logger('REQ', 'robot', methodName, _args);
76+
77+
try {
78+
const response = (await clientFunc?.apply(
79+
client.current,
80+
_args
81+
)) as Promise<ResolvedReturnType<T[K]>>;
82+
83+
logger('RES', 'robot', methodName, response);
84+
return response;
85+
} catch (error) {
86+
logger('ERR', 'robot', methodName, error);
87+
throw error;
88+
}
7589
},
7690
..._options,
7791
refetchInterval: false,

0 commit comments

Comments
 (0)