From d6282221db467c53b6bf955edc3a7b1ba3eeb39c Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Wed, 13 Nov 2024 09:24:53 -0500 Subject: [PATCH] feat: customize log levels and downgrade common errors to info (#9156) ### What? Allows configuration of the log level based on the error being thrown and also downgrades common errors to be info instead of error by default. ### Why? Currently all errors result in logger.error being called which can polute the logs with junk that is normal and doesn't need attention. ### How? Adds a config property called `loggingLevels` that is used to override the default log levels based on the name of the error being thrown. Sanitize config will provide the defaulted 'info' level errors which can be overriden in the config. Before ![Screenshot 2024-11-12 144459](https://github.com/user-attachments/assets/47318329-23b7-4627-afc4-a0bcf4dc3d58) After ![image](https://github.com/user-attachments/assets/85b06be4-0ab8-4ca2-b237-d6a4d54add3a) --- docs/configuration/overview.mdx | 1 + packages/next/src/routes/rest/routeError.ts | 5 ++++- packages/payload/src/config/sanitize.ts | 10 +++++++++ packages/payload/src/config/types.ts | 25 ++++++++++++++++++++- packages/payload/src/errors/types.ts | 17 ++++++++++++++ 5 files changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx index a5194d88b..c3d0bafd0 100644 --- a/docs/configuration/overview.mdx +++ b/docs/configuration/overview.mdx @@ -76,6 +76,7 @@ The following options are available: | **`cors`** | Cross-origin resource sharing (CORS) is a mechanism that accept incoming requests from given domains. You can also customize the `Access-Control-Allow-Headers` header. [More details](#cors). | | **`localization`** | Opt-in to translate your content into multiple locales. [More details](./localization). | | **`logger`** | Logger options, logger options with a destination stream, or an instantiated logger instance. [More details](https://getpino.io/#/docs/api?id=options). | +| **`loggingLevels`** | An object to override the level to use in the logger for Payload's errors. | | **`graphQL`** | Manage GraphQL-specific functionality, including custom queries and mutations, query complexity limits, etc. [More details](../graphql/overview#graphql-options). | | **`cookiePrefix`** | A string that will be prefixed to all cookies that Payload sets. | | **`csrf`** | A whitelist array of URLs to allow Payload to accept cookies from. [More details](../authentication/overview#csrf-protection). | diff --git a/packages/next/src/routes/rest/routeError.ts b/packages/next/src/routes/rest/routeError.ts index ac5a5ad9b..1542eb996 100644 --- a/packages/next/src/routes/rest/routeError.ts +++ b/packages/next/src/routes/rest/routeError.ts @@ -47,7 +47,10 @@ export const routeError = async ({ let status = err.status || httpStatus.INTERNAL_SERVER_ERROR - logger.error(err.stack) + const level = payload.config.loggingLevels[err.name] ?? 'error' + if (level) { + logger[level](level === 'info' ? { msg: err.message } : { err }) + } // Internal server errors can contain anything, including potentially sensitive data. // Therefore, error details will be hidden from the response unless `config.debug` is `true` diff --git a/packages/payload/src/config/sanitize.ts b/packages/payload/src/config/sanitize.ts index a16544f0d..73e9387b9 100644 --- a/packages/payload/src/config/sanitize.ts +++ b/packages/payload/src/config/sanitize.ts @@ -24,6 +24,16 @@ import { defaults } from './defaults.js' const sanitizeAdminConfig = (configToSanitize: Config): Partial => { const sanitizedConfig = { ...configToSanitize } + // default logging level will be 'error' if not provided + sanitizedConfig.loggingLevels = { + Forbidden: 'info', + Locked: 'info', + MissingFile: 'info', + NotFound: 'info', + ValidationError: 'info', + ...(sanitizedConfig.loggingLevels || {}), + } + // add default user collection if none provided if (!sanitizedConfig?.admin?.user) { const firstCollectionWithAuth = sanitizedConfig.collections.find(({ auth }) => Boolean(auth)) diff --git a/packages/payload/src/config/types.ts b/packages/payload/src/config/types.ts index da28572fd..b10133690 100644 --- a/packages/payload/src/config/types.ts +++ b/packages/payload/src/config/types.ts @@ -8,7 +8,7 @@ import type { BusboyConfig } from 'busboy' import type GraphQL from 'graphql' import type { GraphQLFormattedError } from 'graphql' import type { JSONSchema4 } from 'json-schema' -import type { DestinationStream, pino } from 'pino' +import type { DestinationStream, Level, pino } from 'pino' import type React from 'react' import type { default as sharp } from 'sharp' import type { DeepRequired } from 'ts-essentials' @@ -34,6 +34,7 @@ import type { } from '../collections/config/types.js' import type { DatabaseAdapterResult } from '../database/types.js' import type { EmailAdapter, SendEmailOptions } from '../email/types.js' +import type { ErrorName } from '../errors/types.js' import type { GlobalConfig, Globals, SanitizedGlobalConfig } from '../globals/config/types.js' import type { JobsConfig, Payload, RequestContext, TypedUser } from '../index.js' import type { PayloadRequest, Where } from '../types/index.js' @@ -980,6 +981,28 @@ export type Config = { */ logger?: 'sync' | { destination?: DestinationStream; options: pino.LoggerOptions } | PayloadLogger + /** + * Override the log level of errors for Payload's error handler or disable logging with `false`. + * Levels can be any of the following: 'trace', 'debug', 'info', 'warn', 'error', 'fatal' or false. + * + * Default levels: + * { + `* APIError: 'error', + `* AuthenticationError: 'error', + `* ErrorDeletingFile: 'error', + `* FileRetrievalError: 'error', + `* FileUploadError: 'error', + `* Forbidden: 'info', + `* Locked: 'info', + `* LockedAuth: 'error', + `* MissingFile: 'info', + `* NotFound: 'info', + `* QueryError: 'error', + `* ValidationError: 'info', + * } + */ + loggingLevels?: Partial> + /** * The maximum allowed depth to be permitted application-wide. This setting helps prevent against malicious queries. * diff --git a/packages/payload/src/errors/types.ts b/packages/payload/src/errors/types.ts index fcb9204cb..2fdd0ce02 100644 --- a/packages/payload/src/errors/types.ts +++ b/packages/payload/src/errors/types.ts @@ -1 +1,18 @@ export * from './index.js' + +/** + * Error names that can be thrown by Payload during runtime + */ +export type ErrorName = + | 'APIError' + | 'AuthenticationError' + | 'ErrorDeletingFile' + | 'FileRetrievalError' + | 'FileUploadError' + | 'Forbidden' + | 'Locked' + | 'LockedAuth' + | 'MissingFile' + | 'NotFound' + | 'QueryError' + | 'ValidationError'