mirror of
https://github.com/logto-io/logto.git
synced 2025-01-06 20:40:08 -05:00
refactor: report all errors and user id (#3580)
to ApplicationInsights for better error analyzing.
This commit is contained in:
parent
c8fdaa0441
commit
29be040668
6 changed files with 53 additions and 17 deletions
|
@ -1,7 +1,6 @@
|
|||
import { appInsights } from '@logto/shared/app-insights';
|
||||
import { tryThat } from '@silverhand/essentials';
|
||||
import type { BaseContext, NextFunction } from '@withtyped/server';
|
||||
import { RequestError } from '@withtyped/server';
|
||||
|
||||
/**
|
||||
* Build a middleware function that reports error to Azure Application Insights.
|
||||
|
@ -9,9 +8,7 @@ import { RequestError } from '@withtyped/server';
|
|||
export default function withErrorReport<InputContext extends BaseContext>() {
|
||||
return async (context: InputContext, next: NextFunction<InputContext>) => {
|
||||
await tryThat(next(context), (error) => {
|
||||
if (!(error instanceof RequestError && error.status < 500)) {
|
||||
appInsights.trackException(error);
|
||||
}
|
||||
appInsights.trackException(error);
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useContext } from 'react';
|
|||
import AppLoading from '@/components/AppLoading';
|
||||
import { isCloud } from '@/consts/cloud';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import useTrackUserId from '@/hooks/use-track-user-id';
|
||||
import OnboardingApp from '@/onboarding/App';
|
||||
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
|
||||
import ConsoleApp from '@/pages/Main';
|
||||
|
@ -11,6 +12,8 @@ function TenantAppContainer() {
|
|||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { isOnboarding, isLoaded } = useUserOnboardingData();
|
||||
|
||||
useTrackUserId();
|
||||
|
||||
if (!userEndpoint || (isCloud && !isLoaded)) {
|
||||
return <AppLoading />;
|
||||
}
|
||||
|
|
42
packages/console/src/hooks/use-track-user-id.ts
Normal file
42
packages/console/src/hooks/use-track-user-id.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { useLogto } from '@logto/react';
|
||||
import { trySafe } from '@silverhand/essentials';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { getAppInsights } from '@/utils/app-insights';
|
||||
|
||||
class NoIdTokenClaimsError extends Error {
|
||||
name = 'NoIdTokenClaimsError';
|
||||
message = 'Cloud not fetch ID Token claims where user is authenticated.';
|
||||
}
|
||||
|
||||
const useTrackUserId = () => {
|
||||
const { isAuthenticated, getIdTokenClaims } = useLogto();
|
||||
|
||||
useEffect(() => {
|
||||
const setUserId = async () => {
|
||||
const appInsights = getAppInsights();
|
||||
|
||||
if (!appInsights) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAuthenticated) {
|
||||
appInsights.clearAuthenticatedUserContext();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const claims = await trySafe(getIdTokenClaims());
|
||||
|
||||
if (claims) {
|
||||
appInsights.setAuthenticatedUserContext(claims.sub, claims.sub, true);
|
||||
} else {
|
||||
appInsights.trackException({ exception: new NoIdTokenClaimsError() });
|
||||
}
|
||||
};
|
||||
|
||||
void setUserId();
|
||||
}, [getIdTokenClaims, isAuthenticated]);
|
||||
};
|
||||
|
||||
export default useTrackUserId;
|
|
@ -9,6 +9,8 @@ import { isCloud } from '@/consts/cloud';
|
|||
let reactPlugin: Optional<ReactPlugin>;
|
||||
let appInsights: Optional<ApplicationInsights>;
|
||||
|
||||
export const getAppInsights = () => appInsights;
|
||||
|
||||
const initAppInsights = () => {
|
||||
// The string needs to be normalized since it may contain '"'
|
||||
const connectionString = process.env.APPLICATIONINSIGHTS_CONNECTION_STRING?.replace(
|
||||
|
|
|
@ -37,12 +37,8 @@ export default async function initApp(app: Koa): Promise<void> {
|
|||
}
|
||||
|
||||
const tenant = await trySafe(tenantPool.get(tenantId), (error) => {
|
||||
if (error instanceof TenantNotFoundError) {
|
||||
ctx.status = 404;
|
||||
} else {
|
||||
ctx.status = 500;
|
||||
appInsights.trackException(error);
|
||||
}
|
||||
ctx.status = error instanceof TenantNotFoundError ? 404 : 500;
|
||||
appInsights.trackException(error);
|
||||
});
|
||||
|
||||
if (!tenant) {
|
||||
|
|
|
@ -19,20 +19,16 @@ export default function koaErrorHandler<StateT, ContextT, BodyT>(): Middleware<
|
|||
console.error(error);
|
||||
}
|
||||
|
||||
// Report all exceptions to ApplicationInsights
|
||||
appInsights.trackException(error);
|
||||
|
||||
if (error instanceof RequestError) {
|
||||
ctx.status = error.status;
|
||||
ctx.body = error.body;
|
||||
|
||||
if (error.status >= 500) {
|
||||
appInsights.trackException(error);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Report unhandled exceptions
|
||||
appInsights.trackException(error);
|
||||
|
||||
// Koa will handle `HttpError` with a built-in manner.
|
||||
if (error instanceof HttpError) {
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue