diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts index 2bf67207b9..7c788cc625 100644 --- a/packages/backend/src/boot/entry.ts +++ b/packages/backend/src/boot/entry.ts @@ -71,7 +71,7 @@ if (!envOption.quiet) { // Display detail of uncaught exception process.on('uncaughtException', err => { try { - logger.error('Uncaught exception', { error: err }); + logger.error(`Uncaught exception: ${err.message}`, { error: err }); } catch { } }); diff --git a/packages/backend/src/logger.ts b/packages/backend/src/logger.ts index 1d442cd65b..e3283b6866 100644 --- a/packages/backend/src/logger.ts +++ b/packages/backend/src/logger.ts @@ -4,6 +4,7 @@ */ import cluster from 'node:cluster'; +import util from 'node:util'; import chalk from 'chalk'; import { default as convertColor } from 'color-convert'; import { format as dateFormat } from 'date-fns'; @@ -11,6 +12,34 @@ import { bindThis } from '@/decorators.js'; import { envOption } from './env.js'; import type { KEYWORD } from 'color-convert/conversions.js'; +util.inspect.defaultOptions = envOption.logJson ? { + showHidden: false, + depth: null, + colors: false, + customInspect: true, + showProxy: false, + maxArrayLength: null, + maxStringLength: null, + breakLength: Infinity, + compact: true, + sorted: false, + getters: false, + numericSeparator: false, +} : { + showHidden: false, + depth: null, + colors: true, + customInspect: true, + showProxy: false, + maxArrayLength: null, + maxStringLength: null, + breakLength: Infinity, + compact: true, + sorted: false, + getters: false, + numericSeparator: false, +}; + type Context = { name: string; color?: KEYWORD; @@ -18,6 +47,13 @@ type Context = { type Level = 'error' | 'success' | 'warning' | 'debug' | 'info'; +function inspect(_: string, value: any): null | string | number | boolean { + if (value === null || value === undefined) return null; + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value; + if (value instanceof Date) return value.toISOString(); + return util.inspect(value); +} + // eslint-disable-next-line import/no-default-export export default class Logger { private context: Context; @@ -59,7 +95,7 @@ export default class Logger { important: important, context: [this.context].concat(subContexts).map(d => d.name).join('.'), cluster: cluster.isPrimary ? 'primary' : `worker-${cluster.worker!.id}`, - })); + }, inspect)); return; } @@ -86,7 +122,7 @@ export default class Logger { const args: unknown[] = [important ? chalk.bold(log) : log]; if (data != null) { - args.push(data); + args.push(JSON.stringify(data, inspect, 2)); } if (level === 'error' || level === 'warning') { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts index 91d9e4b6a4..2dfa95d303 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -77,8 +77,20 @@ export default class extends Endpoint { // eslint- // Create file driveFile = await this.driveService.uploadFromUrl({ url: emoji.originalUrl, user: null, force: true }); } catch (e) { - // TODO: need to return Drive Error - throw new ApiError(); + const err = e as Error; + throw new ApiError( + { + message: 'Failed to upload image from URL.', + code: 'FAILED_TO_UPLOAD_IMAGE_FROM_URL', + id: '5c77c4d7-0f68-48f9-8694-8453a2294840', + }, + { + e: { + message: err.message, + code: err.name, + } + } + ); } // Duplication Check diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 59eff00370..34fc637ab4 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -113,13 +113,26 @@ export default class extends Endpoint { // eslint- requestHeaders: instance.enableIpLogging ? headers : null, }); return await this.driveFileEntityService.pack(driveFile, me, { self: true }); - } catch (err) { - this.logger.error('Failed to create drive file', { error: err }); - if (err instanceof IdentifiableError) { - if (err.id === '282f77bf-5816-4f72-9264-aa14d8261a21') throw new ApiError(meta.errors.inappropriate); - if (err.id === 'c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6') throw new ApiError(meta.errors.noFreeSpace); + } catch (e) { + this.logger.error('Failed to create drive file', { error: e }); + if (e instanceof IdentifiableError) { + if (e.id === '282f77bf-5816-4f72-9264-aa14d8261a21') throw new ApiError(meta.errors.inappropriate); + if (e.id === 'c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6') throw new ApiError(meta.errors.noFreeSpace); } - throw new ApiError(); + const err = e as Error; + throw new ApiError( + { + message: 'Failed to create drive file.', + code: 'FAILED_TO_CREATE_DRIVE_FILE', + id: '6708863c-6791-4487-aa01-2d682c6e7db0', + }, + { + e: { + message: err.message, + code: err.name, + } + } + ); } finally { cleanup!(); }