mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 00:03:33 +10:00
feat: add more api logs (#1870)
Adds more detailed API logging using Pino
This commit is contained in:
@ -4,7 +4,9 @@ import type { AnyZodObject } from 'zod';
|
||||
|
||||
import { AppError, genericErrorCodeToTrpcErrorCodeMap } from '@documenso/lib/errors/app-error';
|
||||
import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token';
|
||||
import type { TrpcApiLog } from '@documenso/lib/types/api-logs';
|
||||
import type { ApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
|
||||
import { alphaid } from '@documenso/lib/universal/id';
|
||||
import { isAdmin } from '@documenso/lib/utils/is-admin';
|
||||
|
||||
import type { TrpcContext } from './context';
|
||||
@ -66,11 +68,13 @@ const t = initTRPC
|
||||
* Middlewares
|
||||
*/
|
||||
export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path }) => {
|
||||
const logger = ctx.logger.child({
|
||||
const infoToLog: TrpcApiLog = {
|
||||
path,
|
||||
auth: ctx.metadata.auth,
|
||||
source: ctx.metadata.source,
|
||||
});
|
||||
trpcMiddleware: 'authenticated',
|
||||
unverifiedTeamId: ctx.teamId,
|
||||
};
|
||||
|
||||
const authorizationHeader = ctx.req.headers.get('authorization');
|
||||
|
||||
@ -85,10 +89,11 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path })
|
||||
|
||||
const apiToken = await getApiTokenByToken({ token });
|
||||
|
||||
logger.info({
|
||||
ctx.logger.info({
|
||||
...infoToLog,
|
||||
userId: apiToken.user.id,
|
||||
apiTokenId: apiToken.id,
|
||||
});
|
||||
} satisfies TrpcApiLog);
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
@ -122,14 +127,21 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path })
|
||||
});
|
||||
}
|
||||
|
||||
logger.info({
|
||||
// Recreate the logger with a sub request ID to differentiate between batched requests.
|
||||
const trpcSessionLogger = ctx.logger.child({
|
||||
nonBatchedRequestId: alphaid(),
|
||||
});
|
||||
|
||||
trpcSessionLogger.info({
|
||||
...infoToLog,
|
||||
userId: ctx.user.id,
|
||||
apiTokenId: null,
|
||||
});
|
||||
} satisfies TrpcApiLog);
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
logger: trpcSessionLogger,
|
||||
user: ctx.user,
|
||||
session: ctx.session,
|
||||
metadata: {
|
||||
@ -145,10 +157,26 @@ export const authenticatedMiddleware = t.middleware(async ({ ctx, next, path })
|
||||
});
|
||||
});
|
||||
|
||||
export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next, path }) => {
|
||||
// Recreate the logger with a sub request ID to differentiate between batched requests.
|
||||
const trpcSessionLogger = ctx.logger.child({
|
||||
nonBatchedRequestId: alphaid(),
|
||||
});
|
||||
|
||||
ctx.logger.info({
|
||||
path,
|
||||
auth: ctx.metadata.auth,
|
||||
source: ctx.metadata.source,
|
||||
userId: ctx.user?.id,
|
||||
apiTokenId: null,
|
||||
trpcMiddleware: 'maybeAuthenticated',
|
||||
unverifiedTeamId: ctx.teamId,
|
||||
} satisfies TrpcApiLog);
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
logger: trpcSessionLogger,
|
||||
user: ctx.user,
|
||||
session: ctx.session,
|
||||
metadata: {
|
||||
@ -166,7 +194,7 @@ export const maybeAuthenticatedMiddleware = t.middleware(async ({ ctx, next }) =
|
||||
});
|
||||
});
|
||||
|
||||
export const adminMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
export const adminMiddleware = t.middleware(async ({ ctx, next, path }) => {
|
||||
if (!ctx.session || !ctx.user) {
|
||||
throw new TRPCError({
|
||||
code: 'UNAUTHORIZED',
|
||||
@ -183,9 +211,24 @@ export const adminMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Recreate the logger with a sub request ID to differentiate between batched requests.
|
||||
const trpcSessionLogger = ctx.logger.child({
|
||||
nonBatchedRequestId: alphaid(),
|
||||
});
|
||||
|
||||
trpcSessionLogger.info({
|
||||
path,
|
||||
auth: ctx.metadata.auth,
|
||||
source: ctx.metadata.source,
|
||||
userId: ctx.user.id,
|
||||
apiTokenId: null,
|
||||
trpcMiddleware: 'admin',
|
||||
} satisfies TrpcApiLog);
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
logger: trpcSessionLogger,
|
||||
user: ctx.user,
|
||||
session: ctx.session,
|
||||
metadata: {
|
||||
@ -201,11 +244,34 @@ export const adminMiddleware = t.middleware(async ({ ctx, next }) => {
|
||||
});
|
||||
});
|
||||
|
||||
export const procedureMiddleware = t.middleware(async ({ ctx, next, path }) => {
|
||||
// Recreate the logger with a sub request ID to differentiate between batched requests.
|
||||
const trpcSessionLogger = ctx.logger.child({
|
||||
nonBatchedRequestId: alphaid(),
|
||||
});
|
||||
|
||||
trpcSessionLogger.info({
|
||||
path,
|
||||
auth: ctx.metadata.auth,
|
||||
source: ctx.metadata.source,
|
||||
userId: ctx.user?.id,
|
||||
apiTokenId: null,
|
||||
trpcMiddleware: 'procedure',
|
||||
} satisfies TrpcApiLog);
|
||||
|
||||
return await next({
|
||||
ctx: {
|
||||
...ctx,
|
||||
logger: trpcSessionLogger,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Routers and Procedures
|
||||
*/
|
||||
export const router = t.router;
|
||||
export const procedure = t.procedure;
|
||||
export const procedure = t.procedure.use(procedureMiddleware);
|
||||
export const authenticatedProcedure = t.procedure.use(authenticatedMiddleware);
|
||||
// While this is functionally the same as `procedure`, it's useful for indicating purpose
|
||||
export const maybeAuthenticatedProcedure = t.procedure.use(maybeAuthenticatedMiddleware);
|
||||
|
||||
Reference in New Issue
Block a user