diff --git a/packages/core/auth/src/base/auth.ts b/packages/core/auth/src/base/auth.ts index 0a7e250b965..e7de8829133 100644 --- a/packages/core/auth/src/base/auth.ts +++ b/packages/core/auth/src/base/auth.ts @@ -84,6 +84,7 @@ export class BaseAuth extends Auth { this.ctx.throw(401, { message: this.ctx.t('Unauthenticated. Please sign in to continue.', { ns: localeNamespace }), code: AuthErrorCode.EMPTY_TOKEN, + logLevel: 'trace', }); } diff --git a/packages/plugins/@nocobase/plugin-error-handler/src/server/__tests__/middleware.test.ts b/packages/plugins/@nocobase/plugin-error-handler/src/server/__tests__/middleware.test.ts index d30fb7498e2..b1a8b6119c0 100644 --- a/packages/plugins/@nocobase/plugin-error-handler/src/server/__tests__/middleware.test.ts +++ b/packages/plugins/@nocobase/plugin-error-handler/src/server/__tests__/middleware.test.ts @@ -9,7 +9,9 @@ import { Database } from '@nocobase/database'; import { MockServer, createMockServer } from '@nocobase/test'; +import { vi } from 'vitest'; import Plugin from '..'; +import { ErrorHandler } from '../error-handler'; describe('middleware', () => { let app: MockServer; @@ -70,4 +72,60 @@ describe('middleware', () => { errors: ['custom error'], }); }); + + it('should respect error log level', async () => { + const errorHandler = new ErrorHandler(); + const trace = vi.fn(); + const error = vi.fn(); + const err = Object.assign(new Error('Unauthenticated. Please sign in to continue.'), { + code: 'EMPTY_TOKEN', + logLevel: 'trace', + status: 401, + }); + const ctx = { log: { trace, error } }; + + await errorHandler.middleware()(ctx, async () => { + throw err; + }); + + expect(ctx).toMatchObject({ + status: 401, + body: { + errors: [ + { + code: 'EMPTY_TOKEN', + message: 'Unauthenticated. Please sign in to continue.', + }, + ], + }, + }); + expect(trace).toHaveBeenCalledWith(err.message, { + method: 'error-handler', + err: err.stack, + cause: err.cause, + }); + expect(error).not.toHaveBeenCalled(); + }); + + it('should keep errors without log level as error logs', async () => { + const errorHandler = new ErrorHandler(); + const trace = vi.fn(); + const error = vi.fn(); + const err = Object.assign(new Error('Your session has expired. Please sign in again.'), { + code: 'INVALID_TOKEN', + status: 401, + }); + const ctx = { log: { trace, error } }; + + await errorHandler.middleware()(ctx, async () => { + throw err; + }); + + expect(error).toHaveBeenCalledWith(err.message, { + method: 'error-handler', + err: err.stack, + cause: err.cause, + }); + expect(trace).not.toHaveBeenCalled(); + }); }); diff --git a/packages/plugins/@nocobase/plugin-error-handler/src/server/error-handler.ts b/packages/plugins/@nocobase/plugin-error-handler/src/server/error-handler.ts index 0cf3286bbf2..367371c25b0 100644 --- a/packages/plugins/@nocobase/plugin-error-handler/src/server/error-handler.ts +++ b/packages/plugins/@nocobase/plugin-error-handler/src/server/error-handler.ts @@ -55,14 +55,25 @@ export class ErrorHandler { try { await next(); } catch (err) { - ctx.log.error(err.message, { method: 'error-handler', err: err.stack, cause: err.cause }); - if (err.statusCode) { ctx.status = err.statusCode; } self.renderError(err, ctx); + + const logMethod = getLogMethod(err); + ctx.log[logMethod](err.message, { method: 'error-handler', err: err.stack, cause: err.cause }); } }; } } + +const logMethods = ['trace', 'debug', 'info', 'warn', 'error']; + +function getLogMethod(err) { + if (logMethods.includes(err?.logLevel)) { + return err.logLevel; + } + + return 'error'; +}