diff --git a/server/src/controllers/asset-v1.controller.ts b/server/src/controllers/asset-v1.controller.ts index 2f093e1d1f..37a94f24a1 100644 --- a/server/src/controllers/asset-v1.controller.ts +++ b/server/src/controllers/asset-v1.controller.ts @@ -4,6 +4,7 @@ import { Get, HttpCode, HttpStatus, + Inject, Next, Param, ParseFilePipe, @@ -30,6 +31,7 @@ import { ServeFileDto, } from 'src/dtos/asset-v1.dto'; import { AuthDto, ImmichHeader } from 'src/dtos/auth.dto'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { AssetUploadInterceptor } from 'src/middleware/asset-upload.interceptor'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from 'src/middleware/file-upload.interceptor'; @@ -46,7 +48,10 @@ interface UploadFiles { @ApiTags('Asset') @Controller(Route.ASSET) export class AssetControllerV1 { - constructor(private service: AssetServiceV1) {} + constructor( + private service: AssetServiceV1, + @Inject(ILoggerRepository) private logger: ILoggerRepository, + ) {} @Post('upload') @UseInterceptors(AssetUploadInterceptor, FileUploadInterceptor) @@ -95,7 +100,7 @@ export class AssetControllerV1 { @Param() { id }: UUIDParamDto, @Query() dto: ServeFileDto, ) { - await sendFile(res, next, () => this.service.serveFile(auth, id, dto)); + await sendFile(res, next, () => this.service.serveFile(auth, id, dto), this.logger); } @Get('/thumbnail/:id') @@ -108,7 +113,7 @@ export class AssetControllerV1 { @Param() { id }: UUIDParamDto, @Query() dto: GetAssetThumbnailDto, ) { - await sendFile(res, next, () => this.service.serveThumbnail(auth, id, dto)); + await sendFile(res, next, () => this.service.serveThumbnail(auth, id, dto), this.logger); } /** diff --git a/server/src/controllers/download.controller.ts b/server/src/controllers/download.controller.ts index c9f26864af..bc1d01c4be 100644 --- a/server/src/controllers/download.controller.ts +++ b/server/src/controllers/download.controller.ts @@ -1,9 +1,10 @@ -import { Body, Controller, HttpCode, HttpStatus, Next, Param, Post, Res, StreamableFile } from '@nestjs/common'; +import { Body, Controller, HttpCode, HttpStatus, Inject, Next, Param, Post, Res, StreamableFile } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { DownloadService } from 'src/services/download.service'; import { asStreamableFile, sendFile } from 'src/utils/file'; @@ -12,7 +13,10 @@ import { UUIDParamDto } from 'src/validation'; @ApiTags('Download') @Controller('download') export class DownloadController { - constructor(private service: DownloadService) {} + constructor( + private service: DownloadService, + @Inject(ILoggerRepository) private logger: ILoggerRepository, + ) {} @Post('info') @Authenticated({ sharedLink: true }) @@ -38,6 +42,6 @@ export class DownloadController { @Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, ) { - await sendFile(res, next, () => this.service.downloadFile(auth, id)); + await sendFile(res, next, () => this.service.downloadFile(auth, id), this.logger); } } diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index dc87825927..1d3371f82a 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; +import { Body, Controller, Get, Inject, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; @@ -15,6 +15,7 @@ import { PersonStatisticsResponseDto, PersonUpdateDto, } from 'src/dtos/person.dto'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { PersonService } from 'src/services/person.service'; import { sendFile } from 'src/utils/file'; @@ -23,7 +24,10 @@ import { UUIDParamDto } from 'src/validation'; @ApiTags('Person') @Controller('person') export class PersonController { - constructor(private service: PersonService) {} + constructor( + private service: PersonService, + @Inject(ILoggerRepository) private logger: ILoggerRepository, + ) {} @Get() @Authenticated() @@ -74,7 +78,7 @@ export class PersonController { @Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, ) { - await sendFile(res, next, () => this.service.getThumbnail(auth, id)); + await sendFile(res, next, () => this.service.getThumbnail(auth, id), this.logger); } @Get(':id/assets') diff --git a/server/src/controllers/user.controller.ts b/server/src/controllers/user.controller.ts index 8b1abbb26d..a1720dd404 100644 --- a/server/src/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -5,6 +5,7 @@ import { Get, HttpCode, HttpStatus, + Inject, Next, Param, Post, @@ -19,6 +20,7 @@ import { NextFunction, Response } from 'express'; import { AuthDto } from 'src/dtos/auth.dto'; import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto } from 'src/dtos/user.dto'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor'; import { UserService } from 'src/services/user.service'; @@ -28,7 +30,10 @@ import { UUIDParamDto } from 'src/validation'; @ApiTags('User') @Controller(Route.USER) export class UserController { - constructor(private service: UserService) {} + constructor( + private service: UserService, + @Inject(ILoggerRepository) private logger: ILoggerRepository, + ) {} @Get() @Authenticated() @@ -100,6 +105,6 @@ export class UserController { @FileResponse() @Authenticated() async getProfileImage(@Res() res: Response, @Next() next: NextFunction, @Param() { id }: UUIDParamDto) { - await sendFile(res, next, () => this.service.getProfileImage(id)); + await sendFile(res, next, () => this.service.getProfileImage(id), this.logger); } } diff --git a/server/src/repositories/logger.repository.ts b/server/src/repositories/logger.repository.ts index 65ccd8ea47..16cdea5603 100644 --- a/server/src/repositories/logger.repository.ts +++ b/server/src/repositories/logger.repository.ts @@ -1,15 +1,27 @@ -import { Injectable, Scope } from '@nestjs/common'; +import { ConsoleLogger, Injectable, Scope } from '@nestjs/common'; +import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-enabled.util'; import { ClsService } from 'nestjs-cls'; import { LogLevel } from 'src/entities/system-config.entity'; import { ILoggerRepository } from 'src/interfaces/logger.interface'; -import { ImmichLogger } from 'src/utils/logger'; + +const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; @Injectable({ scope: Scope.TRANSIENT }) -export class LoggerRepository extends ImmichLogger implements ILoggerRepository { +export class LoggerRepository extends ConsoleLogger implements ILoggerRepository { + private static logLevels: LogLevel[] = [LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; + constructor(private cls: ClsService) { super(LoggerRepository.name); } + isLevelEnabled(level: LogLevel) { + return isLogLevelEnabled(level, LoggerRepository.logLevels); + } + + setLogLevel(level: LogLevel): void { + LoggerRepository.logLevels = LOG_LEVELS.slice(LOG_LEVELS.indexOf(level)); + } + protected formatContext(context: string): string { let formattedContext = super.formatContext(context); @@ -20,8 +32,4 @@ export class LoggerRepository extends ImmichLogger implements ILoggerRepository return formattedContext; } - - setLogLevel(level: LogLevel): void { - ImmichLogger.setLogLevel(level); - } } diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index a80f17beae..8170fba4e9 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -3,8 +3,8 @@ import { NextFunction, Response } from 'express'; import { access, constants } from 'node:fs/promises'; import { basename, extname, isAbsolute } from 'node:path'; import { promisify } from 'node:util'; +import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ImmichReadStream } from 'src/interfaces/storage.interface'; -import { ImmichLogger } from 'src/utils/logger'; import { isConnectionAborted } from 'src/utils/misc'; export function getFileNameWithoutExtension(path: string): string { @@ -33,12 +33,11 @@ export class ImmichFileResponse { type SendFile = Parameters; type SendFileOptions = SendFile[1]; -const logger = new ImmichLogger('SendFile'); - export const sendFile = async ( res: Response, next: NextFunction, handler: () => Promise, + logger: ILoggerRepository, ): Promise => { const _sendFile = (path: string, options: SendFileOptions) => promisify(res.sendFile).bind(res)(path, options); diff --git a/server/src/utils/logger.ts b/server/src/utils/logger.ts deleted file mode 100644 index 05e8feb498..0000000000 --- a/server/src/utils/logger.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ConsoleLogger } from '@nestjs/common'; -import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-enabled.util'; -import { LogLevel } from 'src/entities/system-config.entity'; - -const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; - -// TODO move implementation to logger.repository.ts -export class ImmichLogger extends ConsoleLogger { - private static logLevels: LogLevel[] = [LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; - - constructor(context: string) { - super(context); - } - - isLevelEnabled(level: LogLevel) { - return isLogLevelEnabled(level, ImmichLogger.logLevels); - } - - static setLogLevel(level: LogLevel | false): void { - ImmichLogger.logLevels = level === false ? [] : LOG_LEVELS.slice(LOG_LEVELS.indexOf(level)); - } -}