Skip to content

Commit 5403ae1

Browse files
authored
Pass more webview logs to the tauri backend (#810)
* use tauri log in more places * sort
1 parent b9e3fab commit 5403ae1

22 files changed

Lines changed: 243 additions & 95 deletions

File tree

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
33
"vcs": {
44
"enabled": false,
55
"clientKind": "git",

src/components/ApplicationUpdateManager/ApplicationUpdateManager.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { clientApi } from '../../pages/client/clientAPI/clientApi.ts';
66
import { useClientStore } from '../../pages/client/hooks/useClientStore';
77
import { TauriEventKey } from '../../pages/client/types';
88
import type { NewApplicationVersionInfo } from '../../shared/hooks/api/types';
9+
import { errorDetail } from '../../shared/utils/errorDetail';
910
import {
1011
type ApplicationUpdateStore,
1112
useApplicationUpdateStore,
@@ -83,7 +84,8 @@ export const ApplicationUpdateManager = () => {
8384
dismissed: false,
8485
});
8586
} catch (e) {
86-
error(`Failed to check latest app version: ${e}`);
87+
const detail = errorDetail(e);
88+
error(`Failed to check latest app version (current: ${appVersion}): ${detail}`);
8789
}
8890
};
8991

src/components/AutoProvisioningManager.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { ProvisioningConfig } from '../pages/client/clientAPI/types';
66
import { clientQueryKeys } from '../pages/client/query';
77
import { useToaster } from '../shared/defguard-ui/hooks/toasts/useToaster';
88
import useAddInstance from '../shared/hooks/useAddInstance';
9+
import { errorDetail } from '../shared/utils/errorDetail';
910

1011
const { getProvisioningConfig } = clientApi;
1112

@@ -26,8 +27,9 @@ export default function AutoProvisioningManager({ children }: PropsWithChildren)
2627
token: config.enrollment_token,
2728
});
2829
} catch (e) {
30+
const detail = errorDetail(e);
2931
error(
30-
`Failed to handle automatic client provisioning with ${JSON.stringify(config)}.\n Error: ${JSON.stringify(e)}`,
32+
`Failed to handle automatic client provisioning (url: ${config.enrollment_url}): ${detail}`,
3133
);
3234
toaster.error(
3335
'Automatic client provisioning failed, please contact your administrator.',

src/main.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1+
import { error } from '@tauri-apps/plugin-log';
12
import { StrictMode } from 'react';
23
import { createRoot } from 'react-dom/client';
34

45
import { App } from './components/App/App';
6+
import { errorDetail } from './shared/utils/errorDetail';
7+
8+
// Forward uncaught JS errors to the Tauri backend log
9+
window.onerror = (message, source, lineno, colno, err) => {
10+
const detail = err?.stack ?? `${message} (${source}:${lineno}:${colno})`;
11+
error(`[uncaught error] ${detail}`);
12+
// returning false lets the error propagate to the browser DevTools console
13+
return false;
14+
};
15+
16+
// Forward unhandled promise rejections to the Tauri backend log
17+
window.addEventListener('unhandledrejection', (event) => {
18+
error(`[unhandled rejection] ${errorDetail(event.reason)}`);
19+
});
520

621
const rootElement = document.getElementById('root') as HTMLElement;
722

src/pages/client/pages/ClientAddInstancePage/components/AddInstanceFormCard/components/AddInstanceDeviceForm/AddInstanceDeviceForm.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type {
2323
CreateDeviceResponse,
2424
} from '../../../../../../../../shared/hooks/api/types';
2525
import { routes } from '../../../../../../../../shared/routes';
26+
import { errorDetail } from '../../../../../../../../shared/utils/errorDetail';
2627
import { generateWGKeys } from '../../../../../../../../shared/utils/generateWGKeys';
2728
import { clientApi } from '../../../../../../clientAPI/clientApi';
2829
import { useClientStore } from '../../../../../../hooks/useClientStore';
@@ -134,6 +135,8 @@ export const AddInstanceDeviceForm = () => {
134135
navigate(routes.client.instancePage, { replace: true });
135136
})
136137
.catch((e) => {
138+
const detail = errorDetail(e);
139+
error(`Failed to save device config: ${detail}`);
137140
toaster.error(
138141
LL.common.messages.errorWithMessage({
139142
message: String(e),
@@ -144,7 +147,8 @@ export const AddInstanceDeviceForm = () => {
144147
});
145148
} catch (e) {
146149
setIsLoading(false);
147-
console.error(e);
150+
const detail = errorDetail(e);
151+
error(`Device form submit failed for proxy ${proxyUrl}: ${detail}`);
148152

149153
if (typeof e === 'string') {
150154
if (e.includes('Network Error')) {

src/pages/client/pages/ClientAddInstancePage/components/AddInstanceFormCard/components/AddInstanceInitForm/AddInstanceInitForm.tsx

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { useMemo, useState } from 'react';
99
import { type SubmitHandler, useForm } from 'react-hook-form';
1010
import { useNavigate } from 'react-router-dom';
1111
import { z } from 'zod';
12-
1312
import { useI18nContext } from '../../../../../../../../i18n/i18n-react';
1413
import { FormInput } from '../../../../../../../../shared/defguard-ui/components/Form/FormInput/FormInput';
1514
import { Button } from '../../../../../../../../shared/defguard-ui/components/Layout/Button/Button';
@@ -24,6 +23,7 @@ import type {
2423
EnrollmentStartResponse,
2524
} from '../../../../../../../../shared/hooks/api/types';
2625
import { routes } from '../../../../../../../../shared/routes';
26+
import { errorDetail } from '../../../../../../../../shared/utils/errorDetail';
2727
import { useEnrollmentStore } from '../../../../../../../enrollment/hooks/store/useEnrollmentStore';
2828
import { clientApi } from '../../../../../../clientAPI/clientApi';
2929
import { useClientStore } from '../../../../../../hooks/useClientStore';
@@ -96,7 +96,9 @@ export const AddInstanceInitForm = () => {
9696
.then(async (res: Response) => {
9797
if (!res.ok) {
9898
setIsLoading(false);
99-
error(JSON.stringify(res.status));
99+
error(
100+
`Enrollment start returned non-OK status ${res.status} for URL: ${endpointUrl}`,
101+
);
100102
const errorMessage = ((await res.json()) as EnrollmentError).error;
101103

102104
switch (errorMessage) {
@@ -120,9 +122,7 @@ export const AddInstanceInitForm = () => {
120122
if (!authCookie) {
121123
setIsLoading(false);
122124
error(
123-
LL.common.messages.errorWithMessage({
124-
message: LL.common.messages.noCookie(),
125-
}),
125+
`Enrollment start response for ${endpointUrl} is missing defguard_proxy set-cookie header`,
126126
);
127127
throw Error(
128128
LL.common.messages.errorWithMessage({
@@ -154,34 +154,57 @@ export const AddInstanceInitForm = () => {
154154
body: JSON.stringify({
155155
pubkey: instance.pubkey,
156156
}),
157-
}).then(async (res) => {
158-
invoke<void>('update_instance', {
159-
instanceId: instance.id,
160-
response: (await res.json()) as CreateDeviceResponse,
161-
})
162-
.then(() => {
163-
info('Configured device');
164-
toaster.success(
165-
LL.pages.enrollment.steps.deviceSetup.desktopSetup.messages.deviceConfigured(),
166-
);
167-
const _selectedInstance: SelectedInstance = {
168-
id: instance.id,
169-
type: ClientConnectionType.LOCATION,
170-
};
171-
setClientState({
172-
selectedInstance: _selectedInstance,
173-
});
174-
navigate(routes.client.base, { replace: true });
175-
})
176-
.catch((e) => {
177-
error(e);
157+
})
158+
.then(async (res) => {
159+
if (!res.ok) {
160+
const detail = `network_info returned status ${res.status} for instance ${instance.uuid}`;
161+
error(`Failed to fetch network info: ${detail}`);
178162
toaster.error(
179163
LL.common.messages.errorWithMessage({
180-
message: String(e),
164+
message: detail,
181165
}),
182166
);
183-
});
184-
});
167+
return;
168+
}
169+
invoke<void>('update_instance', {
170+
instanceId: instance.id,
171+
response: (await res.json()) as CreateDeviceResponse,
172+
})
173+
.then(() => {
174+
info('Configured device');
175+
toaster.success(
176+
LL.pages.enrollment.steps.deviceSetup.desktopSetup.messages.deviceConfigured(),
177+
);
178+
const _selectedInstance: SelectedInstance = {
179+
id: instance.id,
180+
type: ClientConnectionType.LOCATION,
181+
};
182+
setClientState({
183+
selectedInstance: _selectedInstance,
184+
});
185+
navigate(routes.client.base, { replace: true });
186+
})
187+
.catch((e) => {
188+
const detail = errorDetail(e);
189+
error(`Failed to save config during instance add: ${detail}`);
190+
toaster.error(
191+
LL.common.messages.errorWithMessage({
192+
message: String(e),
193+
}),
194+
);
195+
});
196+
})
197+
.catch((e) => {
198+
const detail = errorDetail(e);
199+
error(
200+
`Failed to reach network_info endpoint for instance ${instance.uuid}: ${detail}`,
201+
);
202+
toaster.error(
203+
LL.common.messages.errorWithMessage({
204+
message: String(e),
205+
}),
206+
);
207+
});
185208
}
186209
// register new instance
187210
// is user in need of full enrollment ?
@@ -220,6 +243,8 @@ export const AddInstanceInitForm = () => {
220243
})
221244
.catch((e) => {
222245
setIsLoading(false);
246+
const detail = errorDetail(e);
247+
error(`Failed to initialize instance: ${detail}`);
223248
if (typeof e === 'string') {
224249
if (e.includes('Network Error')) {
225250
toaster.error(LL.common.messages.networkError());

src/pages/client/pages/ClientEditTunnelPage/components/EditTunnelFormCard.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { zodResolver } from '@hookform/resolvers/zod';
2+
import { error } from '@tauri-apps/plugin-log';
23
import { useMemo, useState } from 'react';
34
import { type SubmitHandler, useForm } from 'react-hook-form';
45
import { useNavigate } from 'react-router-dom';
56
import { z } from 'zod';
6-
77
import { useI18nContext } from '../../../../../i18n/i18n-react';
88
import { FormInput } from '../../../../../shared/defguard-ui/components/Form/FormInput/FormInput';
99
import { ArrowSingle } from '../../../../../shared/defguard-ui/components/icons/ArrowSingle/ArrowSingle';
@@ -23,6 +23,7 @@ import {
2323
patternValidWireguardKey,
2424
} from '../../../../../shared/patterns';
2525
import { routes } from '../../../../../shared/routes';
26+
import { errorDetail } from '../../../../../shared/utils/errorDetail';
2627
import { validateIpOrDomainList } from '../../../../../shared/validators/tunnel';
2728
import { clientApi } from '../../../clientAPI/clientApi';
2829
import type { Tunnel } from '../../../types';
@@ -197,9 +198,11 @@ export const EditTunnelFormCard = ({ tunnel, submitRef }: Props) => {
197198
navigate(routes.client.base, { replace: true });
198199
toaster.success(LL.pages.client.pages.editTunnelPage.messages.editSuccess());
199200
})
200-
.catch(() =>
201-
toaster.error(LL.pages.client.pages.editTunnelPage.messages.editError()),
202-
);
201+
.catch((e) => {
202+
const detail = errorDetail(e);
203+
error(`Failed to update tunnel: ${detail}`);
204+
toaster.error(LL.pages.client.pages.editTunnelPage.messages.editError());
205+
});
203206
};
204207

205208
const { handleSubmit, control } = useForm<Tunnel>({

src/pages/client/pages/ClientEditTunnelPage/modals/DeleteTunnelModal/DeleteTunnelModal.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { useMutation, useQueryClient } from '@tanstack/react-query';
2+
import { error } from '@tauri-apps/plugin-log';
23
import { isUndefined } from 'lodash-es';
34
import { useNavigate } from 'react-router-dom';
45
import { shallow } from 'zustand/shallow';
5-
66
import { useI18nContext } from '../../../../../../i18n/i18n-react';
77
import { ConfirmModal } from '../../../../../../shared/defguard-ui/components/Layout/modals/ConfirmModal/ConfirmModal';
88
import { ConfirmModalType } from '../../../../../../shared/defguard-ui/components/Layout/modals/ConfirmModal/types';
99
import { useToaster } from '../../../../../../shared/defguard-ui/hooks/toasts/useToaster';
1010
import { routes } from '../../../../../../shared/routes';
11+
import { errorDetail } from '../../../../../../shared/utils/errorDetail';
1112
import { clientApi } from '../../../../clientAPI/clientApi';
1213
import { useClientStore } from '../../../../hooks/useClientStore';
1314
import { clientQueryKeys } from '../../../../query';
@@ -59,7 +60,8 @@ export const DeleteTunnelModal = () => {
5960
message: String(e),
6061
}),
6162
);
62-
console.error(e);
63+
const detail = errorDetail(e);
64+
error(`Failed to delete tunnel "${tunnel?.name}" (id: ${tunnel?.id}): ${detail}`);
6365
},
6466
});
6567

src/pages/client/pages/ClientInstancePage/components/LocationsList/components/LocationCardConnectButton/LocationCardConnectButton.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import './style.scss';
33
import { error } from '@tauri-apps/plugin-log';
44
import classNames from 'classnames';
55
import { useState } from 'react';
6-
76
import { useI18nContext } from '../../../../../../../../i18n/i18n-react';
87
import SvgIconCheckmarkSmall from '../../../../../../../../shared/components/svg/IconCheckmarkSmall';
98
import { Button } from '../../../../../../../../shared/defguard-ui/components/Layout/Button/Button';
@@ -13,6 +12,7 @@ import {
1312
} from '../../../../../../../../shared/defguard-ui/components/Layout/Button/types';
1413
import SvgIconX from '../../../../../../../../shared/defguard-ui/components/svg/IconX';
1514
import { useToaster } from '../../../../../../../../shared/defguard-ui/hooks/toasts/useToaster';
15+
import { errorDetail } from '../../../../../../../../shared/utils/errorDetail';
1616
import { clientApi } from '../../../../../../clientAPI/clientApi';
1717
import { type CommonWireguardFields, LocationMfaType } from '../../../../../../types';
1818
import { useMFAModal } from '../../modals/MFAModal/useMFAModal';
@@ -66,8 +66,10 @@ export const LocationCardConnectButton = ({ location }: Props) => {
6666
message: String(e),
6767
}),
6868
);
69-
error(`Error handling interface: ${e}`);
70-
console.error(e);
69+
const detail = errorDetail(e);
70+
error(
71+
`Error handling interface for location ${location?.id} (${location?.active ? 'disconnect' : 'connect'}): ${detail}`,
72+
);
7173
}
7274
};
7375

src/pages/client/pages/ClientInstancePage/components/LocationsList/components/LocationCardRoute/LocationCardRoute.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useMemo } from 'react';
55
import { useI18nContext } from '../../../../../../../../i18n/i18n-react';
66
import { Toggle } from '../../../../../../../../shared/defguard-ui/components/Layout/Toggle/Toggle';
77
import type { ToggleOption } from '../../../../../../../../shared/defguard-ui/components/Layout/Toggle/types';
8+
import { errorDetail } from '../../../../../../../../shared/utils/errorDetail';
89
import { clientApi } from '../../../../../../clientAPI/clientApi';
910
import {
1011
ClientConnectionType,
@@ -30,8 +31,10 @@ export const LocationCardRoute = ({ location, selectedDefguardInstance }: Props)
3031
});
3132
}
3233
} catch (e) {
33-
error(`Error handling routing: ${e}`);
34-
console.error(e);
34+
const detail = errorDetail(e);
35+
error(
36+
`Failed to update routing for location ${location?.id} (type: ${location?.connection_type}, routeAllTraffic: ${value}): ${detail}`,
37+
);
3538
}
3639
};
3740

0 commit comments

Comments
 (0)