Skip to content

Commit

Permalink
fix: ensure loggingLevels is respected (#10308)
Browse files Browse the repository at this point in the history
Issue #10272

Adds `logError` utility that can be used across the codebase for logging
errors
  • Loading branch information
r1tsuu authored Jan 2, 2025
1 parent d9e0cd3 commit 2e58a4a
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 35 deletions.
3 changes: 2 additions & 1 deletion packages/next/src/routes/graphql/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { APIError, Payload, PayloadRequest, SanitizedConfig } from 'payload
import { configToSchema } from '@payloadcms/graphql'
import { createHandler } from 'graphql-http/lib/use/fetch'
import httpStatus from 'http-status'
import { logError } from 'payload'

import { addDataAndFileToRequest } from '../../utilities/addDataAndFileToRequest.js'
import { addLocalesToRequestFromData } from '../../utilities/addLocalesToRequest.js'
Expand All @@ -22,7 +23,7 @@ const handleError = async ({
}): Promise<GraphQLFormattedError> => {
const status = (err.originalError as APIError).status || httpStatus.INTERNAL_SERVER_ERROR
let errorMessage = err.message
payload.logger.error(err.stack)
logError({ err, payload })

// Internal server errors can contain anything, including potentially sensitive data.
// Therefore, error details will be hidden from the response unless `config.debug` is `true`
Expand Down
9 changes: 3 additions & 6 deletions packages/next/src/routes/rest/routeError.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Collection, ErrorResult, PayloadRequest, SanitizedConfig } from 'payload'

import httpStatus from 'http-status'
import { APIError, formatErrors, getPayload } from 'payload'
import { APIError, formatErrors, getPayload, logError } from 'payload'

import { headersWithCors } from '../../utilities/headersWithCors.js'
import { mergeHeaders } from '../../utilities/mergeHeaders.js'
Expand Down Expand Up @@ -40,16 +40,13 @@ export const routeError = async ({
req,
})

const { config, logger } = payload
const { config } = payload

let response = formatErrors(err)

let status = err.status || httpStatus.INTERNAL_SERVER_ERROR

const level = payload.config.loggingLevels[err.name] ?? 'error'
if (level) {
logger[level](level === 'info' ? { msg: err.message } : { err })
}
logError({ err, payload })

// Internal server errors can contain anything, including potentially sensitive data.
// Therefore, error details will be hidden from the response unless `config.debug` is `true`
Expand Down
7 changes: 3 additions & 4 deletions packages/next/src/views/Document/getDocumentData.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Locale, Payload, TypedUser, TypeWithID } from 'payload'

import { sanitizeID } from '@payloadcms/ui/shared'
import { type Locale, logError, type Payload, type TypedUser, type TypeWithID } from 'payload'

type Args = {
collectionSlug?: string
Expand Down Expand Up @@ -47,8 +46,8 @@ export const getDocumentData = async ({
user,
})
}
} catch (_err) {
payload.logger.error(_err)
} catch (err) {
logError({ err, payload })
}

return resolvedData
Expand Down
10 changes: 5 additions & 5 deletions packages/next/src/views/Document/getDocumentPermissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
hasSavePermission as getHasSavePermission,
isEditing as getIsEditing,
} from '@payloadcms/ui/shared'
import { docAccessOperation, docAccessOperationGlobal } from 'payload'
import { docAccessOperation, docAccessOperationGlobal, logError } from 'payload'

export const getDocumentPermissions = async (args: {
collectionConfig?: SanitizedCollectionConfig
Expand Down Expand Up @@ -59,8 +59,8 @@ export const getDocumentPermissions = async (args: {
},
}).then((permissions) => permissions.update)
}
} catch (error) {
req.payload.logger.error(error)
} catch (err) {
logError({ err, payload: req.payload })
}
}

Expand All @@ -86,8 +86,8 @@ export const getDocumentPermissions = async (args: {
},
}).then((permissions) => permissions.update)
}
} catch (error) {
req.payload.logger.error(error)
} catch (err) {
logError({ err, payload: req.payload })
}
}

Expand Down
4 changes: 3 additions & 1 deletion packages/next/src/views/Document/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerCompo
import { formatAdminURL, isEditing as getIsEditing } from '@payloadcms/ui/shared'
import { buildFormState } from '@payloadcms/ui/utilities/buildFormState'
import { notFound, redirect } from 'next/navigation.js'
import { logError } from 'payload'
import React from 'react'

import type { GenerateEditViewMetadata } from './getMetaBySegment.js'
Expand Down Expand Up @@ -384,7 +385,8 @@ export const Document: React.FC<AdminViewProps> = async (args) => {
if (error?.message === 'NEXT_REDIRECT') {
throw error
}
args.initPageResult.req.payload.logger.error(error)

logError({ err: error, payload: args.initPageResult.req.payload })

if (error.message === 'not-found') {
notFound()
Expand Down
7 changes: 5 additions & 2 deletions packages/next/src/views/Versions/getLatestVersion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Payload, Where } from 'payload'

import { logError } from 'payload'

type ReturnType = {
id: string
updatedAt: string
Expand Down Expand Up @@ -60,8 +62,9 @@ export async function getLatestVersion(args: Args): Promise<ReturnType> {
id: response.docs[0].id,
updatedAt: response.docs[0].updatedAt,
}
} catch (e) {
payload.logger.error(e)
} catch (err) {
logError({ err, payload })

return null
}
}
16 changes: 10 additions & 6 deletions packages/next/src/views/Versions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { EditViewComponent, PaginatedDocs, PayloadServerReactComponent } from 'payload'

import { Gutter, ListQueryProvider, SetDocumentStepNav } from '@payloadcms/ui'
import { notFound } from 'next/navigation.js'
import {
type EditViewComponent,
logError,
type PaginatedDocs,
type PayloadServerReactComponent,
} from 'payload'
import { isNumber } from 'payload/shared'
import React from 'react'

Expand Down Expand Up @@ -94,8 +98,8 @@ export const VersionsView: PayloadServerReactComponent<EditViewComponent> = asyn
status: 'published',
})
}
} catch (error) {
payload.logger.error(error)
} catch (err) {
logError({ err, payload })
}
}

Expand Down Expand Up @@ -137,8 +141,8 @@ export const VersionsView: PayloadServerReactComponent<EditViewComponent> = asyn
status: 'published',
})
}
} catch (error) {
payload.logger.error(error)
} catch (err) {
logError({ err, payload })
}

if (!versionsData) {
Expand Down
19 changes: 10 additions & 9 deletions packages/payload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import type {
TransformGlobalWithSelect,
} from './types/index.js'
import type { TraverseFieldsCallback } from './utilities/traverseFields.js'
export type { FieldState } from './admin/forms/Form.js'
import type { TypeWithVersion } from './versions/types.js'

import { decrypt, encrypt } from './auth/crypto.js'
Expand All @@ -78,8 +79,8 @@ import { getLogger } from './utilities/logger.js'
import { serverInit as serverInitTelemetry } from './utilities/telemetry/events/serverInit.js'
import { traverseFields } from './utilities/traverseFields.js'

export type { FieldState } from './admin/forms/Form.js'
export type * from './admin/types.js'
export { default as executeAccess } from './auth/executeAccess.js'

export interface GeneratedTypes {
authUntyped: {
Expand Down Expand Up @@ -881,7 +882,6 @@ interface RequestContext {
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface DatabaseAdapter extends BaseDatabaseAdapter {}
export type { Payload, RequestContext }
export { default as executeAccess } from './auth/executeAccess.js'
export { executeAuthStrategies } from './auth/executeAuthStrategies.js'
export { getAccessResults } from './auth/getAccessResults.js'
export { getFieldsToSign } from './auth/getFieldsToSign.js'
Expand All @@ -898,7 +898,6 @@ export { registerFirstUserOperation } from './auth/operations/registerFirstUser.
export { resetPasswordOperation } from './auth/operations/resetPassword.js'
export { unlockOperation } from './auth/operations/unlock.js'
export { verifyEmailOperation } from './auth/operations/verifyEmail.js'

export type {
AuthStrategyFunction,
AuthStrategyFunctionArgs,
Expand All @@ -919,8 +918,8 @@ export type {
} from './auth/types.js'

export { generateImportMap } from './bin/generateImportMap/index.js'
export type { ImportMap } from './bin/generateImportMap/index.js'

export type { ImportMap } from './bin/generateImportMap/index.js'
export { genImportMapIterateFields } from './bin/generateImportMap/iterateFields.js'

export {
Expand Down Expand Up @@ -967,6 +966,7 @@ export type {
TypeWithID,
TypeWithTimestamps,
} from './collections/config/types.js'

export { createDataloaderCacheKey, getDataLoader } from './collections/dataloader.js'
export { countOperation } from './collections/operations/count.js'
export { createOperation } from './collections/operations/create.js'
Expand All @@ -988,8 +988,8 @@ export {
serverOnlyAdminConfigProperties,
serverOnlyConfigProperties,
} from './config/client.js'

export { defaults } from './config/defaults.js'

export { sanitizeConfig } from './config/sanitize.js'
export type * from './config/types.js'
export { combineQueries } from './database/combineQueries.js'
Expand Down Expand Up @@ -1098,8 +1098,8 @@ export {
ValidationErrorName,
} from './errors/index.js'
export type { ValidationFieldError } from './errors/index.js'

export { baseBlockFields } from './fields/baseFields/baseBlockFields.js'

export { baseIDField } from './fields/baseFields/baseIDField.js'
export {
createClientField,
Expand Down Expand Up @@ -1209,16 +1209,16 @@ export type {
ValidateOptions,
ValueWithRelation,
} from './fields/config/types.js'

export { getDefaultValue } from './fields/getDefaultValue.js'

export { traverseFields as afterChangeTraverseFields } from './fields/hooks/afterChange/traverseFields.js'
export { promise as afterReadPromise } from './fields/hooks/afterRead/promise.js'
export { traverseFields as afterReadTraverseFields } from './fields/hooks/afterRead/traverseFields.js'
export { traverseFields as beforeChangeTraverseFields } from './fields/hooks/beforeChange/traverseFields.js'
export { traverseFields as beforeValidateTraverseFields } from './fields/hooks/beforeValidate/traverseFields.js'
export { default as sortableFieldTypes } from './fields/sortableFieldTypes.js'

export { validations } from './fields/validations.js'

export type {
ArrayFieldValidation,
BlocksFieldValidation,
Expand Down Expand Up @@ -1250,7 +1250,6 @@ export type {
UploadFieldValidation,
UsernameFieldValidation,
} from './fields/validations.js'

export {
type ClientGlobalConfig,
createClientGlobalConfig,
Expand All @@ -1272,6 +1271,7 @@ export type {
} from './globals/config/types.js'

export { docAccessOperation as docAccessOperationGlobal } from './globals/operations/docAccess.js'

export { findOneOperation } from './globals/operations/findOne.js'
export { findVersionByIDOperation as findVersionByIDOperationGlobal } from './globals/operations/findVersionByID.js'
export { findVersionsOperation as findVersionsOperationGlobal } from './globals/operations/findVersions.js'
Expand Down Expand Up @@ -1357,6 +1357,7 @@ export { default as isolateObjectProperty } from './utilities/isolateObjectPrope
export { isPlainObject } from './utilities/isPlainObject.js'
export { isValidID } from './utilities/isValidID.js'
export { killTransaction } from './utilities/killTransaction.js'
export { logError } from './utilities/logError.js'
export { defaultLoggerOptions } from './utilities/logger.js'
export { mapAsync } from './utilities/mapAsync.js'
export { sanitizeFallbackLocale } from './utilities/sanitizeFallbackLocale.js'
Expand Down
29 changes: 29 additions & 0 deletions packages/payload/src/utilities/logError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type pino from 'pino'

import type { Payload } from '../types/index.js'

export const logError = ({ err, payload }: { err: unknown; payload: Payload }): void => {
let level: false | pino.Level = 'error'

if (
err &&
typeof err === 'object' &&
'name' in err &&
typeof err.name === 'string' &&
typeof payload.config.loggingLevels[err.name] !== 'undefined'
) {
level = payload.config.loggingLevels[err.name]
}

if (level) {
const logObject: { err?: unknown; msg?: unknown } = {}

if (level === 'info') {
logObject.msg = typeof err === 'object' && 'message' in err ? err.message : 'Error'
} else {
logObject.err = err
}

payload.logger[level](logObject)
}
}
3 changes: 2 additions & 1 deletion packages/payload/src/versions/deleteCollectionVersions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Payload } from '../index.js'
import type { PayloadRequest } from '../types/index.js'

import { type Payload } from '../index.js'

type Args = {
id?: number | string
payload: Payload
Expand Down

0 comments on commit 2e58a4a

Please sign in to comment.