From d3446f3092e2b637d40d35d802edcedbe95b3208 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Thu, 23 Jan 2025 08:31:30 -0500 Subject: [PATCH] refactor: logging repository (#15540) --- server/src/app.module.ts | 4 ++-- server/src/bin/sync-sql.ts | 4 ++-- .../src/controllers/asset-media.controller.ts | 5 ++--- server/src/controllers/person.controller.ts | 6 +++--- server/src/controllers/user.controller.ts | 5 ++--- server/src/cores/storage.core.ts | 7 +++---- server/src/interfaces/logger.interface.ts | 17 ----------------- server/src/middleware/auth.guard.ts | 5 ++--- server/src/middleware/error.interceptor.ts | 5 ++--- .../src/middleware/file-upload.interceptor.ts | 6 +++--- .../src/middleware/global-exception.filter.ts | 6 +++--- server/src/middleware/logging.interceptor.ts | 6 +++--- server/src/repositories/cron.repository.ts | 6 +++--- server/src/repositories/database.repository.ts | 6 +++--- server/src/repositories/event.repository.ts | 6 +++--- server/src/repositories/index.ts | 6 ++---- server/src/repositories/job.repository.ts | 4 ++-- ...itory.spec.ts => logging.repository.spec.ts} | 10 +++++----- ...gger.repository.ts => logging.repository.ts} | 13 ++++++------- .../repositories/machine-learning.repository.ts | 6 +++--- server/src/repositories/map.repository.ts | 4 ++-- server/src/repositories/media.repository.ts | 6 +++--- server/src/repositories/metadata.repository.ts | 6 +++--- .../notification.repository.spec.ts | 13 ++++++------- .../src/repositories/notification.repository.ts | 6 +++--- server/src/repositories/oauth.repository.ts | 6 +++--- server/src/repositories/process.repository.ts | 6 +++--- server/src/repositories/search.repository.ts | 6 +++--- .../src/repositories/server-info.repository.ts | 6 +++--- .../src/repositories/storage.repository.spec.ts | 11 ++++++----- server/src/repositories/storage.repository.ts | 6 +++--- server/src/repositories/tag.repository.ts | 9 ++++----- server/src/repositories/telemetry.repository.ts | 6 +++--- server/src/services/api.service.ts | 6 +++--- server/src/services/base.service.ts | 4 ++-- server/src/services/database.service.spec.ts | 5 ++--- server/src/services/download.service.spec.ts | 4 ++-- server/src/services/duplicate.service.spec.ts | 4 ++-- server/src/services/job.service.spec.ts | 5 ++--- server/src/services/media.service.spec.ts | 5 ++--- server/src/services/storage.service.spec.ts | 5 ++--- .../src/services/system-config.service.spec.ts | 5 ++--- server/src/services/version.service.spec.ts | 5 ++--- server/src/types.ts | 14 ++++++++++++++ server/src/utils/config.ts | 5 ++--- server/src/utils/file.ts | 4 ++-- server/src/utils/logger.ts | 4 ++-- server/src/utils/misc.ts | 4 ++-- server/src/workers/api.ts | 4 ++-- server/src/workers/microservices.ts | 4 ++-- server/test/medium/metadata.service.spec.ts | 8 ++++++-- .../test/repositories/logger.repository.mock.ts | 4 ++-- server/test/utils.ts | 8 +++++--- 53 files changed, 159 insertions(+), 172 deletions(-) delete mode 100644 server/src/interfaces/logger.interface.ts rename server/src/repositories/{logger.repository.spec.ts => logging.repository.spec.ts} (80%) rename server/src/repositories/{logger.repository.ts => logging.repository.ts} (81%) diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 5e6432408f..d088af6188 100644 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -13,7 +13,6 @@ import { entities } from 'src/entities'; import { ImmichWorker } from 'src/enum'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ITelemetryRepository } from 'src/interfaces/telemetry.interface'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; @@ -22,6 +21,7 @@ import { GlobalExceptionFilter } from 'src/middleware/global-exception.filter'; import { LoggingInterceptor } from 'src/middleware/logging.interceptor'; import { providers, repositories } from 'src/repositories'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { teardownTelemetry } from 'src/repositories/telemetry.repository'; import { services } from 'src/services'; import { CliService } from 'src/services/cli.service'; @@ -64,7 +64,7 @@ const imports = [ class BaseModule implements OnModuleInit, OnModuleDestroy { constructor( @Inject(IWorker) private worker: ImmichWorker, - @Inject(ILoggerRepository) logger: ILoggerRepository, + logger: LoggingRepository, @Inject(IEventRepository) private eventRepository: IEventRepository, @Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(ITelemetryRepository) private telemetryRepository: ITelemetryRepository, diff --git a/server/src/bin/sync-sql.ts b/server/src/bin/sync-sql.ts index 21eff3b306..c25e1c8a90 100644 --- a/server/src/bin/sync-sql.ts +++ b/server/src/bin/sync-sql.ts @@ -11,10 +11,10 @@ import { join } from 'node:path'; import { format } from 'sql-formatter'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; import { entities } from 'src/entities'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { providers, repositories } from 'src/repositories'; import { AccessRepository } from 'src/repositories/access.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AuthService } from 'src/services/auth.service'; import { Logger } from 'typeorm'; @@ -62,7 +62,7 @@ class SqlGenerator { ...repositories.map((repository) => ({ provide: repository, useClass: repository as any })), ]; for (const repository of targets) { - if (repository.provide === ILoggerRepository) { + if (repository.provide === LoggingRepository) { continue; } await this.process(repository); diff --git a/server/src/controllers/asset-media.controller.ts b/server/src/controllers/asset-media.controller.ts index 56e793975a..553f1a261f 100644 --- a/server/src/controllers/asset-media.controller.ts +++ b/server/src/controllers/asset-media.controller.ts @@ -4,7 +4,6 @@ import { Get, HttpCode, HttpStatus, - Inject, Next, Param, ParseFilePipe, @@ -34,10 +33,10 @@ import { } from 'src/dtos/asset-media.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { ImmichHeader, RouteKey } from 'src/enum'; -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, UploadFiles, getFiles } from 'src/middleware/file-upload.interceptor'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AssetMediaService } from 'src/services/asset-media.service'; import { sendFile } from 'src/utils/file'; import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation'; @@ -46,7 +45,7 @@ import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation'; @Controller(RouteKey.ASSET) export class AssetMediaController { constructor( - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, private service: AssetMediaService, ) {} diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index c8faf87e62..e98dd6a002 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Inject, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; +import { Body, Controller, Get, 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,8 +15,8 @@ import { PersonUpdateDto, } from 'src/dtos/person.dto'; import { Permission } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { PersonService } from 'src/services/person.service'; import { sendFile } from 'src/utils/file'; import { UUIDParamDto } from 'src/validation'; @@ -26,7 +26,7 @@ import { UUIDParamDto } from 'src/validation'; export class PersonController { constructor( private service: PersonService, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) {} @Get() diff --git a/server/src/controllers/user.controller.ts b/server/src/controllers/user.controller.ts index 15bb1913db..9dbaa00d81 100644 --- a/server/src/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -5,7 +5,6 @@ import { Get, HttpCode, HttpStatus, - Inject, Next, Param, Post, @@ -22,9 +21,9 @@ import { UserPreferencesResponseDto, UserPreferencesUpdateDto } from 'src/dtos/u import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { UserAdminResponseDto, UserResponseDto, UserUpdateMeDto } from 'src/dtos/user.dto'; import { RouteKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { UserService } from 'src/services/user.service'; import { sendFile } from 'src/utils/file'; import { UUIDParamDto } from 'src/validation'; @@ -34,7 +33,7 @@ import { UUIDParamDto } from 'src/validation'; export class UserController { constructor( private service: UserService, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) {} @Get() diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 7285ff2163..50b07981a6 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -6,12 +6,11 @@ import { PersonEntity } from 'src/entities/person.entity'; import { AssetFileType, AssetPathType, ImageFormat, PathType, PersonPathType, StorageFolder } from 'src/enum'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { ICryptoRepository } from 'src/interfaces/crypto.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMoveRepository } from 'src/interfaces/move.interface'; import { IPersonRepository } from 'src/interfaces/person.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; -import { IConfigRepository } from 'src/types'; +import { IConfigRepository, ILoggingRepository } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { getConfig } from 'src/utils/config'; @@ -40,7 +39,7 @@ export class StorageCore { private personRepository: IPersonRepository, private storageRepository: IStorageRepository, private systemMetadataRepository: ISystemMetadataRepository, - private logger: ILoggerRepository, + private logger: ILoggingRepository, ) {} static create( @@ -51,7 +50,7 @@ export class StorageCore { personRepository: IPersonRepository, storageRepository: IStorageRepository, systemMetadataRepository: ISystemMetadataRepository, - logger: ILoggerRepository, + logger: ILoggingRepository, ) { if (!instance) { instance = new StorageCore( diff --git a/server/src/interfaces/logger.interface.ts b/server/src/interfaces/logger.interface.ts deleted file mode 100644 index 92984bf8e1..0000000000 --- a/server/src/interfaces/logger.interface.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ImmichWorker, LogLevel } from 'src/enum'; - -export const ILoggerRepository = 'ILoggerRepository'; - -export interface ILoggerRepository { - setAppName(name: ImmichWorker): void; - setContext(message: string): void; - setLogLevel(level: LogLevel | false): void; - isLevelEnabled(level: LogLevel): boolean; - - verbose(message: any, ...args: any): void; - debug(message: any, ...args: any): void; - log(message: any, ...args: any): void; - warn(message: any, ...args: any): void; - error(message: any, ...args: any): void; - fatal(message: any, ...args: any): void; -} diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index e05dba907b..438843436b 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -1,7 +1,6 @@ import { CanActivate, ExecutionContext, - Inject, Injectable, SetMetadata, applyDecorators, @@ -12,7 +11,7 @@ import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } fr import { Request } from 'express'; import { AuthDto } from 'src/dtos/auth.dto'; import { ImmichQuery, MetadataKey, Permission } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AuthService, LoginDetails } from 'src/services/auth.service'; import { UAParser } from 'ua-parser-js'; @@ -67,7 +66,7 @@ export interface AuthenticatedRequest extends Request { @Injectable() export class AuthGuard implements CanActivate { constructor( - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, private reflector: Reflector, private authService: AuthService, ) { diff --git a/server/src/middleware/error.interceptor.ts b/server/src/middleware/error.interceptor.ts index 5d93b40dc2..3c0c09aa54 100644 --- a/server/src/middleware/error.interceptor.ts +++ b/server/src/middleware/error.interceptor.ts @@ -2,19 +2,18 @@ import { CallHandler, ExecutionContext, HttpException, - Inject, Injectable, InternalServerErrorException, NestInterceptor, } from '@nestjs/common'; import { Observable, catchError, throwError } from 'rxjs'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { logGlobalError } from 'src/utils/logger'; import { routeToErrorMessage } from 'src/utils/misc'; @Injectable() export class ErrorInterceptor implements NestInterceptor { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(ErrorInterceptor.name); } diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index 108a187e67..743764ff75 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -1,4 +1,4 @@ -import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor } from '@nestjs/common'; +import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { PATH_METADATA } from '@nestjs/common/constants'; import { Reflector } from '@nestjs/core'; import { transformException } from '@nestjs/platform-express/multer/multer/multer.utils'; @@ -8,8 +8,8 @@ import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; import { UploadFieldName } from 'src/dtos/asset-media.dto'; import { RouteKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { AuthRequest } from 'src/middleware/auth.guard'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AssetMediaService, UploadFile } from 'src/services/asset-media.service'; import { asRequest, mapToUploadFile } from 'src/utils/asset.util'; @@ -64,7 +64,7 @@ export class FileUploadInterceptor implements NestInterceptor { constructor( private reflect: Reflector, private assetService: AssetMediaService, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(FileUploadInterceptor.name); diff --git a/server/src/middleware/global-exception.filter.ts b/server/src/middleware/global-exception.filter.ts index 6200363e86..7d7ade471e 100644 --- a/server/src/middleware/global-exception.filter.ts +++ b/server/src/middleware/global-exception.filter.ts @@ -1,13 +1,13 @@ -import { ArgumentsHost, Catch, ExceptionFilter, HttpException, Inject } from '@nestjs/common'; +import { ArgumentsHost, Catch, ExceptionFilter, HttpException } from '@nestjs/common'; import { Response } from 'express'; import { ClsService } from 'nestjs-cls'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { logGlobalError } from 'src/utils/logger'; @Catch() export class GlobalExceptionFilter implements ExceptionFilter { constructor( - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, private cls: ClsService, ) { this.logger.setContext(GlobalExceptionFilter.name); diff --git a/server/src/middleware/logging.interceptor.ts b/server/src/middleware/logging.interceptor.ts index 366ed06a5d..fe0daeed03 100644 --- a/server/src/middleware/logging.interceptor.ts +++ b/server/src/middleware/logging.interceptor.ts @@ -1,7 +1,7 @@ -import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor } from '@nestjs/common'; +import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { Request, Response } from 'express'; import { Observable, finalize } from 'rxjs'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; const maxArrayLength = 100; const replacer = (key: string, value: unknown) => { @@ -18,7 +18,7 @@ const replacer = (key: string, value: unknown) => { @Injectable() export class LoggingInterceptor implements NestInterceptor { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(LoggingInterceptor.name); } diff --git a/server/src/repositories/cron.repository.ts b/server/src/repositories/cron.repository.ts index fd7589a034..12533f67af 100644 --- a/server/src/repositories/cron.repository.ts +++ b/server/src/repositories/cron.repository.ts @@ -1,14 +1,14 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { SchedulerRegistry } from '@nestjs/schedule'; import { CronJob, CronTime } from 'cron'; import { CronCreate, CronUpdate, ICronRepository } from 'src/interfaces/cron.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; @Injectable() export class CronRepository implements ICronRepository { constructor( private schedulerRegistry: SchedulerRegistry, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(CronRepository.name); } diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index 336da8f303..f7d52efd7a 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { InjectDataSource } from '@nestjs/typeorm'; import AsyncLock from 'async-lock'; import { Kysely, sql } from 'kysely'; @@ -16,8 +16,8 @@ import { VectorIndex, VectorUpdateResult, } from 'src/interfaces/database.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { UPSERT_COLUMNS } from 'src/utils/database'; import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, EntityMetadata, QueryRunner } from 'typeorm'; @@ -30,7 +30,7 @@ export class DatabaseRepository implements IDatabaseRepository { constructor( @InjectKysely() private db: Kysely, @InjectDataSource() private dataSource: DataSource, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, configRepository: ConfigRepository, ) { this.vectorExtension = configRepository.getEnv().database.vectorExtension; diff --git a/server/src/repositories/event.repository.ts b/server/src/repositories/event.repository.ts index e1c31624d5..a443e0ed83 100644 --- a/server/src/repositories/event.repository.ts +++ b/server/src/repositories/event.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ModuleRef, Reflector } from '@nestjs/core'; import { OnGatewayConnection, @@ -22,8 +22,8 @@ import { serverEvents, ServerEvents, } from 'src/interfaces/event.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AuthService } from 'src/services/auth.service'; import { handlePromiseError } from 'src/utils/misc'; @@ -52,7 +52,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect constructor( private moduleRef: ModuleRef, private configRepository: ConfigRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(EventRepository.name); } diff --git a/server/src/repositories/index.ts b/server/src/repositories/index.ts index 197ab5f92d..7f4619d3de 100644 --- a/server/src/repositories/index.ts +++ b/server/src/repositories/index.ts @@ -7,7 +7,6 @@ import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; import { ILibraryRepository } from 'src/interfaces/library.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; import { IMapRepository } from 'src/interfaces/map.interface'; import { IMetadataRepository } from 'src/interfaces/metadata.interface'; @@ -43,7 +42,7 @@ import { DatabaseRepository } from 'src/repositories/database.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LibraryRepository } from 'src/repositories/library.repository'; -import { LoggerRepository } from 'src/repositories/logger.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; import { MapRepository } from 'src/repositories/map.repository'; import { MediaRepository } from 'src/repositories/media.repository'; @@ -70,12 +69,12 @@ import { VersionHistoryRepository } from 'src/repositories/version-history.repos import { ViewRepository } from 'src/repositories/view-repository'; export const repositories = [ - // AccessRepository, ActivityRepository, AuditRepository, ApiKeyRepository, ConfigRepository, + LoggingRepository, MediaRepository, MemoryRepository, ViewRepository, @@ -91,7 +90,6 @@ export const providers = [ { provide: IEventRepository, useClass: EventRepository }, { provide: IJobRepository, useClass: JobRepository }, { provide: ILibraryRepository, useClass: LibraryRepository }, - { provide: ILoggerRepository, useClass: LoggerRepository }, { provide: IMachineLearningRepository, useClass: MachineLearningRepository }, { provide: IMapRepository, useClass: MapRepository }, { provide: IMetadataRepository, useClass: MetadataRepository }, diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index e57b5ee964..9a5bf20df6 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -19,8 +19,8 @@ import { QueueName, QueueStatus, } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { getKeyByValue, getMethodNames, ImmichStartupError } from 'src/utils/misc'; type JobMapItem = { @@ -39,7 +39,7 @@ export class JobRepository implements IJobRepository { private moduleRef: ModuleRef, private configRepository: ConfigRepository, @Inject(IEventRepository) private eventRepository: IEventRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(JobRepository.name); } diff --git a/server/src/repositories/logger.repository.spec.ts b/server/src/repositories/logging.repository.spec.ts similarity index 80% rename from server/src/repositories/logger.repository.spec.ts rename to server/src/repositories/logging.repository.spec.ts index 7354035763..11fa19e48b 100644 --- a/server/src/repositories/logger.repository.spec.ts +++ b/server/src/repositories/logging.repository.spec.ts @@ -1,12 +1,12 @@ import { ClsService } from 'nestjs-cls'; import { ImmichWorker } from 'src/enum'; -import { LoggerRepository } from 'src/repositories/logger.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { IConfigRepository } from 'src/types'; import { mockEnvData, newConfigRepositoryMock } from 'test/repositories/config.repository.mock'; import { Mocked } from 'vitest'; -describe(LoggerRepository.name, () => { - let sut: LoggerRepository; +describe(LoggingRepository.name, () => { + let sut: LoggingRepository; let configMock: Mocked; let clsMock: Mocked; @@ -22,7 +22,7 @@ describe(LoggerRepository.name, () => { it('should use colors', () => { configMock.getEnv.mockReturnValue(mockEnvData({ noColor: false })); - sut = new LoggerRepository(clsMock, configMock); + sut = new LoggingRepository(clsMock, configMock); sut.setAppName(ImmichWorker.API); expect(sut['formatContext']('context')).toBe('\u001B[33m[Api:context]\u001B[39m '); @@ -31,7 +31,7 @@ describe(LoggerRepository.name, () => { it('should not use colors when noColor is true', () => { configMock.getEnv.mockReturnValue(mockEnvData({ noColor: true })); - sut = new LoggerRepository(clsMock, configMock); + sut = new LoggingRepository(clsMock, configMock); sut.setAppName(ImmichWorker.API); expect(sut['formatContext']('context')).toBe('[Api:context] '); diff --git a/server/src/repositories/logger.repository.ts b/server/src/repositories/logging.repository.ts similarity index 81% rename from server/src/repositories/logger.repository.ts rename to server/src/repositories/logging.repository.ts index c4f0f91e15..7ddae26a9d 100644 --- a/server/src/repositories/logger.repository.ts +++ b/server/src/repositories/logging.repository.ts @@ -3,7 +3,6 @@ import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-en import { ClsService } from 'nestjs-cls'; import { Telemetry } from 'src/decorators'; import { LogLevel } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; @@ -19,7 +18,7 @@ enum LogColor { @Injectable({ scope: Scope.TRANSIENT }) @Telemetry({ enabled: false }) -export class LoggerRepository extends ConsoleLogger implements ILoggerRepository { +export class LoggingRepository extends ConsoleLogger { private static logLevels: LogLevel[] = [LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; private noColor: boolean; @@ -27,7 +26,7 @@ export class LoggerRepository extends ConsoleLogger implements ILoggerRepository private cls: ClsService, configRepository: ConfigRepository, ) { - super(LoggerRepository.name); + super(LoggingRepository.name); const { noColor } = configRepository.getEnv(); this.noColor = noColor; @@ -36,19 +35,19 @@ export class LoggerRepository extends ConsoleLogger implements ILoggerRepository private static appName?: string = undefined; setAppName(name: string): void { - LoggerRepository.appName = name.charAt(0).toUpperCase() + name.slice(1); + LoggingRepository.appName = name.charAt(0).toUpperCase() + name.slice(1); } isLevelEnabled(level: LogLevel) { - return isLogLevelEnabled(level, LoggerRepository.logLevels); + return isLogLevelEnabled(level, LoggingRepository.logLevels); } setLogLevel(level: LogLevel | false): void { - LoggerRepository.logLevels = level ? LOG_LEVELS.slice(LOG_LEVELS.indexOf(level)) : []; + LoggingRepository.logLevels = level ? LOG_LEVELS.slice(LOG_LEVELS.indexOf(level)) : []; } protected formatContext(context: string): string { - let prefix = LoggerRepository.appName || ''; + let prefix = LoggingRepository.appName || ''; if (context) { prefix += (prefix ? ':' : '') + context; } diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index 56cdf30a1e..6266314bfd 100644 --- a/server/src/repositories/machine-learning.repository.ts +++ b/server/src/repositories/machine-learning.repository.ts @@ -1,7 +1,6 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; import { CLIPConfig } from 'src/dtos/model-config.dto'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ClipTextualResponse, ClipVisualResponse, @@ -13,10 +12,11 @@ import { ModelTask, ModelType, } from 'src/interfaces/machine-learning.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; @Injectable() export class MachineLearningRepository implements IMachineLearningRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(MachineLearningRepository.name); } diff --git a/server/src/repositories/map.repository.ts b/server/src/repositories/map.repository.ts index 4f6e78487d..3c5c3f5671 100644 --- a/server/src/repositories/map.repository.ts +++ b/server/src/repositories/map.repository.ts @@ -11,7 +11,6 @@ import { DB, GeodataPlaces, NaturalearthCountries } from 'src/db'; import { AssetEntity, withExif } from 'src/entities/asset.entity'; import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity'; import { LogLevel, SystemMetadataKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { GeoPoint, IMapRepository, @@ -21,6 +20,7 @@ import { } from 'src/interfaces/map.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; interface MapDB extends DB { geodata_places_tmp: GeodataPlaces; @@ -32,7 +32,7 @@ export class MapRepository implements IMapRepository { constructor( private configRepository: ConfigRepository, @Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, @InjectKysely() private db: Kysely, ) { this.logger.setContext(MapRepository.name); diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index 31f67c08bd..483bd3fd90 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { exiftool } from 'exiftool-vendored'; import ffmpeg, { FfprobeData } from 'fluent-ffmpeg'; import { Duration } from 'luxon'; @@ -7,7 +7,7 @@ import { Writable } from 'node:stream'; import sharp from 'sharp'; import { ORIENTATION_TO_SHARP_ROTATION } from 'src/constants'; import { Colorspace, LogLevel } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { DecodeToBufferOptions, GenerateThumbhashOptions, @@ -37,7 +37,7 @@ type ProgressEvent = { @Injectable() export class MediaRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(MediaRepository.name); } diff --git a/server/src/repositories/metadata.repository.ts b/server/src/repositories/metadata.repository.ts index 81c1b35e15..90a3a9e765 100644 --- a/server/src/repositories/metadata.repository.ts +++ b/server/src/repositories/metadata.repository.ts @@ -1,8 +1,8 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored'; import geotz from 'geo-tz'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; @Injectable() export class MetadataRepository implements IMetadataRepository { @@ -20,7 +20,7 @@ export class MetadataRepository implements IMetadataRepository { writeArgs: ['-api', 'largefilesupport=1', '-overwrite_original'], }); - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(MetadataRepository.name); } diff --git a/server/src/repositories/notification.repository.spec.ts b/server/src/repositories/notification.repository.spec.ts index 368ba3f0ce..f952e9ebed 100644 --- a/server/src/repositories/notification.repository.spec.ts +++ b/server/src/repositories/notification.repository.spec.ts @@ -1,19 +1,18 @@ -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { EmailRenderRequest, EmailTemplate } from 'src/interfaces/notification.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { NotificationRepository } from 'src/repositories/notification.repository'; +import { ILoggingRepository } from 'src/types'; +import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock'; import { Mocked } from 'vitest'; describe(NotificationRepository.name, () => { let sut: NotificationRepository; - let loggerMock: Mocked; + let loggerMock: Mocked; beforeEach(() => { - loggerMock = { - setContext: vitest.fn(), - debug: vitest.fn(), - } as unknown as Mocked; + loggerMock = newLoggingRepositoryMock(); - sut = new NotificationRepository(loggerMock); + sut = new NotificationRepository(loggerMock as ILoggingRepository as LoggingRepository); }); describe('renderEmail', () => { diff --git a/server/src/repositories/notification.repository.ts b/server/src/repositories/notification.repository.ts index 718f82bd75..ecdaed3866 100644 --- a/server/src/repositories/notification.repository.ts +++ b/server/src/repositories/notification.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { render } from '@react-email/render'; import { createTransport } from 'nodemailer'; import React from 'react'; @@ -6,7 +6,6 @@ import { AlbumInviteEmail } from 'src/emails/album-invite.email'; import { AlbumUpdateEmail } from 'src/emails/album-update.email'; import { TestEmail } from 'src/emails/test.email'; import { WelcomeEmail } from 'src/emails/welcome.email'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { EmailRenderRequest, EmailTemplate, @@ -15,10 +14,11 @@ import { SendEmailResponse, SmtpOptions, } from 'src/interfaces/notification.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; @Injectable() export class NotificationRepository implements INotificationRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(NotificationRepository.name); } diff --git a/server/src/repositories/oauth.repository.ts b/server/src/repositories/oauth.repository.ts index ed038f0137..dfd36edc2a 100644 --- a/server/src/repositories/oauth.repository.ts +++ b/server/src/repositories/oauth.repository.ts @@ -1,11 +1,11 @@ -import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common'; +import { Injectable, InternalServerErrorException } from '@nestjs/common'; import { custom, generators, Issuer } from 'openid-client'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IOAuthRepository, OAuthConfig, OAuthProfile } from 'src/interfaces/oauth.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; @Injectable() export class OAuthRepository implements IOAuthRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(OAuthRepository.name); } diff --git a/server/src/repositories/process.repository.ts b/server/src/repositories/process.repository.ts index 99ec51037c..bd533129f9 100644 --- a/server/src/repositories/process.repository.ts +++ b/server/src/repositories/process.repository.ts @@ -1,12 +1,12 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { ChildProcessWithoutNullStreams, spawn, SpawnOptionsWithoutStdio } from 'node:child_process'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IProcessRepository } from 'src/interfaces/process.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; @Injectable() export class ProcessRepository implements IProcessRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(StorageRepository.name); } diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index 0e43063e9a..9abee70de3 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Kysely, OrderByDirectionExpression, sql } from 'kysely'; import { InjectKysely } from 'nestjs-kysely'; import { randomUUID } from 'node:crypto'; @@ -7,7 +7,6 @@ import { DummyValue, GenerateSql } from 'src/decorators'; import { AssetEntity, searchAssetBuilder } from 'src/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { AssetType } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { AssetDuplicateSearch, AssetSearchOptions, @@ -20,6 +19,7 @@ import { SearchPaginationOptions, SmartSearchOptions, } from 'src/interfaces/search.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { anyUuid, asUuid } from 'src/utils/database'; import { Paginated } from 'src/utils/pagination'; import { isValidInteger } from 'src/validation'; @@ -27,7 +27,7 @@ import { isValidInteger } from 'src/validation'; @Injectable() export class SearchRepository implements ISearchRepository { constructor( - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, @InjectKysely() private db: Kysely, ) { this.logger.setContext(SearchRepository.name); diff --git a/server/src/repositories/server-info.repository.ts b/server/src/repositories/server-info.repository.ts index 13423d82b9..c0c0f88723 100644 --- a/server/src/repositories/server-info.repository.ts +++ b/server/src/repositories/server-info.repository.ts @@ -1,12 +1,12 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { exiftool } from 'exiftool-vendored'; import { exec as execCallback } from 'node:child_process'; import { readFile } from 'node:fs/promises'; import { promisify } from 'node:util'; import sharp from 'sharp'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { GitHubRelease, IServerInfoRepository, ServerBuildVersions } from 'src/interfaces/server-info.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; const exec = promisify(execCallback); const maybeFirstLine = async (command: string): Promise => { @@ -37,7 +37,7 @@ const getLockfileVersion = (name: string, lockfile?: BuildLockfile) => { export class ServerInfoRepository implements IServerInfoRepository { constructor( private configRepository: ConfigRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(ServerInfoRepository.name); } diff --git a/server/src/repositories/storage.repository.spec.ts b/server/src/repositories/storage.repository.spec.ts index 22a0ff8ddc..4c4a9d50b6 100644 --- a/server/src/repositories/storage.repository.spec.ts +++ b/server/src/repositories/storage.repository.spec.ts @@ -1,8 +1,9 @@ import mockfs from 'mock-fs'; import { CrawlOptionsDto } from 'src/dtos/library.dto'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; -import { newLoggerRepositoryMock } from 'test/repositories/logger.repository.mock'; +import { ILoggingRepository } from 'src/types'; +import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock'; interface Test { test: string; @@ -181,11 +182,11 @@ const tests: Test[] = [ describe(StorageRepository.name, () => { let sut: StorageRepository; - let logger: ILoggerRepository; + let logger: ILoggingRepository; beforeEach(() => { - logger = newLoggerRepositoryMock(); - sut = new StorageRepository(logger); + logger = newLoggingRepositoryMock(); + sut = new StorageRepository(logger as LoggingRepository); }); afterEach(() => { diff --git a/server/src/repositories/storage.repository.ts b/server/src/repositories/storage.repository.ts index a8d3db15d8..6766f442b8 100644 --- a/server/src/repositories/storage.repository.ts +++ b/server/src/repositories/storage.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import archiver from 'archiver'; import chokidar, { WatchOptions } from 'chokidar'; import { escapePath, glob, globStream } from 'fast-glob'; @@ -7,7 +7,6 @@ import fs from 'node:fs/promises'; import path from 'node:path'; import { Writable } from 'node:stream'; import { CrawlOptionsDto, WalkOptionsDto } from 'src/dtos/library.dto'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { DiskUsage, IStorageRepository, @@ -15,11 +14,12 @@ import { ImmichZipStream, WatchEvents, } from 'src/interfaces/storage.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { mimeTypes } from 'src/utils/mime-types'; @Injectable() export class StorageRepository implements IStorageRepository { - constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) { + constructor(private logger: LoggingRepository) { this.logger.setContext(StorageRepository.name); } diff --git a/server/src/repositories/tag.repository.ts b/server/src/repositories/tag.repository.ts index 994a49fc3d..3489f43640 100644 --- a/server/src/repositories/tag.repository.ts +++ b/server/src/repositories/tag.repository.ts @@ -1,18 +1,17 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; import { TagEntity } from 'src/entities/tag.entity'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { AssetTagItem, ITagRepository } from 'src/interfaces/tag.interface'; -import { DataSource, In, Repository, TreeRepository } from 'typeorm'; +import { LoggingRepository } from 'src/repositories/logging.repository'; +import { DataSource, In, Repository } from 'typeorm'; @Injectable() export class TagRepository implements ITagRepository { constructor( @InjectDataSource() private dataSource: DataSource, @InjectRepository(TagEntity) private repository: Repository, - @InjectRepository(TagEntity) private tree: TreeRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(TagRepository.name); } diff --git a/server/src/repositories/telemetry.repository.ts b/server/src/repositories/telemetry.repository.ts index c4401c9da3..7a82ba07e7 100644 --- a/server/src/repositories/telemetry.repository.ts +++ b/server/src/repositories/telemetry.repository.ts @@ -1,4 +1,4 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { MetricOptions } from '@opentelemetry/api'; import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks'; @@ -15,9 +15,9 @@ import { MetricService } from 'nestjs-otel'; import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils'; import { serverVersion } from 'src/constants'; import { ImmichTelemetry, MetadataKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMetricGroupRepository, ITelemetryRepository, MetricGroupOptions } from 'src/interfaces/telemetry.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; class MetricGroupRepository implements IMetricGroupRepository { private enabled = false; @@ -96,7 +96,7 @@ export class TelemetryRepository implements ITelemetryRepository { private metricService: MetricService, private reflect: Reflector, private configRepository: ConfigRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { const { telemetry } = this.configRepository.getEnv(); const { metrics } = telemetry; diff --git a/server/src/services/api.service.ts b/server/src/services/api.service.ts index 3fec0dbc0a..a18f863f99 100644 --- a/server/src/services/api.service.ts +++ b/server/src/services/api.service.ts @@ -1,10 +1,10 @@ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Cron, CronExpression, Interval } from '@nestjs/schedule'; import { NextFunction, Request, Response } from 'express'; import { readFileSync } from 'node:fs'; import { ONE_HOUR } from 'src/constants'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { AuthService } from 'src/services/auth.service'; import { JobService } from 'src/services/job.service'; import { SharedLinkService } from 'src/services/shared-link.service'; @@ -39,7 +39,7 @@ export class ApiService { private sharedLinkService: SharedLinkService, private versionService: VersionService, private configRepository: ConfigRepository, - @Inject(ILoggerRepository) private logger: ILoggerRepository, + private logger: LoggingRepository, ) { this.logger.setContext(ApiService.name); } diff --git a/server/src/services/base.service.ts b/server/src/services/base.service.ts index af46146e3e..398b1508f5 100644 --- a/server/src/services/base.service.ts +++ b/server/src/services/base.service.ts @@ -15,7 +15,6 @@ import { IDatabaseRepository } from 'src/interfaces/database.interface'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository } from 'src/interfaces/job.interface'; import { ILibraryRepository } from 'src/interfaces/library.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface'; import { IMapRepository } from 'src/interfaces/map.interface'; import { IMetadataRepository } from 'src/interfaces/metadata.interface'; @@ -42,6 +41,7 @@ import { ActivityRepository } from 'src/repositories/activity.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; import { ViewRepository } from 'src/repositories/view-repository'; @@ -52,7 +52,7 @@ export class BaseService { protected storageCore: StorageCore; constructor( - @Inject(ILoggerRepository) protected logger: ILoggerRepository, + protected logger: LoggingRepository, protected accessRepository: AccessRepository, protected activityRepository: ActivityRepository, protected auditRepository: AuditRepository, diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index 9458ba768b..477cb6931f 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -5,9 +5,8 @@ import { IDatabaseRepository, VectorExtension, } from 'src/interfaces/database.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { DatabaseService } from 'src/services/database.service'; -import { IConfigRepository } from 'src/types'; +import { IConfigRepository, ILoggingRepository } from 'src/types'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService } from 'test/utils'; import { Mocked } from 'vitest'; @@ -17,7 +16,7 @@ describe(DatabaseService.name, () => { let configMock: Mocked; let databaseMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let extensionRange: string; let versionBelowRange: string; let minVersionInRange: string; diff --git a/server/src/services/download.service.spec.ts b/server/src/services/download.service.spec.ts index 632d157384..12e3414ac3 100644 --- a/server/src/services/download.service.spec.ts +++ b/server/src/services/download.service.spec.ts @@ -2,9 +2,9 @@ import { BadRequestException } from '@nestjs/common'; import { DownloadResponseDto } from 'src/dtos/download.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { IAssetRepository } from 'src/interfaces/asset.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { DownloadService } from 'src/services/download.service'; +import { ILoggingRepository } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock } from 'test/repositories/access.repository.mock'; @@ -26,7 +26,7 @@ describe(DownloadService.name, () => { let sut: DownloadService; let accessMock: IAccessRepositoryMock; let assetMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let storageMock: Mocked; it('should work', () => { diff --git a/server/src/services/duplicate.service.spec.ts b/server/src/services/duplicate.service.spec.ts index c954d81a74..3c332edbe9 100644 --- a/server/src/services/duplicate.service.spec.ts +++ b/server/src/services/duplicate.service.spec.ts @@ -1,10 +1,10 @@ import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface'; import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ISearchRepository } from 'src/interfaces/search.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { DuplicateService } from 'src/services/duplicate.service'; import { SearchService } from 'src/services/search.service'; +import { ILoggingRepository } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { newTestService } from 'test/utils'; @@ -17,7 +17,7 @@ describe(SearchService.name, () => { let assetMock: Mocked; let jobMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let searchMock: Mocked; let systemMock: Mocked; diff --git a/server/src/services/job.service.spec.ts b/server/src/services/job.service.spec.ts index 5714f7fdd5..195ed10156 100644 --- a/server/src/services/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -3,10 +3,9 @@ import { defaults, SystemConfig } from 'src/config'; import { ImmichWorker } from 'src/enum'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IJobRepository, JobCommand, JobItem, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ITelemetryRepository } from 'src/interfaces/telemetry.interface'; import { JobService } from 'src/services/job.service'; -import { IConfigRepository } from 'src/types'; +import { IConfigRepository, ILoggingRepository } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { newTestService } from 'test/utils'; import { Mocked } from 'vitest'; @@ -16,7 +15,7 @@ describe(JobService.name, () => { let assetMock: Mocked; let configMock: Mocked; let jobMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let telemetryMock: Mocked; beforeEach(() => { diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index a0f296a27c..9ce6c8edb9 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -15,13 +15,12 @@ import { } from 'src/enum'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface'; import { IJobRepository, JobCounts, JobName, JobStatus } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IMoveRepository } from 'src/interfaces/move.interface'; import { IPersonRepository } from 'src/interfaces/person.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { MediaService } from 'src/services/media.service'; -import { IMediaRepository, RawImageInfo } from 'src/types'; +import { ILoggingRepository, IMediaRepository, RawImageInfo } from 'src/types'; import { assetStub } from 'test/fixtures/asset.stub'; import { faceStub } from 'test/fixtures/face.stub'; import { probeStub } from 'test/fixtures/media.stub'; @@ -34,7 +33,7 @@ describe(MediaService.name, () => { let assetMock: Mocked; let jobMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let mediaMock: Mocked; let moveMock: Mocked; let personMock: Mocked; diff --git a/server/src/services/storage.service.spec.ts b/server/src/services/storage.service.spec.ts index 7b5b2384e4..3a5bf3bad9 100644 --- a/server/src/services/storage.service.spec.ts +++ b/server/src/services/storage.service.spec.ts @@ -1,9 +1,8 @@ import { SystemMetadataKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { StorageService } from 'src/services/storage.service'; -import { IConfigRepository } from 'src/types'; +import { IConfigRepository, ILoggingRepository } from 'src/types'; import { ImmichStartupError } from 'src/utils/misc'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService } from 'test/utils'; @@ -13,7 +12,7 @@ describe(StorageService.name, () => { let sut: StorageService; let configMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let storageMock: Mocked; let systemMock: Mocked; diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index bba6201334..02166cdeb8 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -14,10 +14,9 @@ import { } from 'src/enum'; import { IEventRepository } from 'src/interfaces/event.interface'; import { QueueName } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { SystemConfigService } from 'src/services/system-config.service'; -import { DeepPartial, IConfigRepository } from 'src/types'; +import { DeepPartial, IConfigRepository, ILoggingRepository } from 'src/types'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService } from 'test/utils'; import { Mocked } from 'vitest'; @@ -203,7 +202,7 @@ describe(SystemConfigService.name, () => { let configMock: Mocked; let eventMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let systemMock: Mocked; beforeEach(() => { diff --git a/server/src/services/version.service.spec.ts b/server/src/services/version.service.spec.ts index a49f721355..022e1de613 100644 --- a/server/src/services/version.service.spec.ts +++ b/server/src/services/version.service.spec.ts @@ -4,12 +4,11 @@ import { serverVersion } from 'src/constants'; import { ImmichEnvironment, SystemMetadataKey } from 'src/enum'; import { IEventRepository } from 'src/interfaces/event.interface'; import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { IServerInfoRepository } from 'src/interfaces/server-info.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface'; import { VersionService } from 'src/services/version.service'; -import { IConfigRepository } from 'src/types'; +import { IConfigRepository, ILoggingRepository } from 'src/types'; import { mockEnvData } from 'test/repositories/config.repository.mock'; import { newTestService } from 'test/utils'; import { Mocked } from 'vitest'; @@ -30,7 +29,7 @@ describe(VersionService.name, () => { let configMock: Mocked; let eventMock: Mocked; let jobMock: Mocked; - let loggerMock: Mocked; + let loggerMock: Mocked; let serverInfoMock: Mocked; let systemMock: Mocked; let versionHistoryMock: Mocked; diff --git a/server/src/types.ts b/server/src/types.ts index 97f866e924..69d9d8e647 100644 --- a/server/src/types.ts +++ b/server/src/types.ts @@ -5,6 +5,7 @@ import { ActivityRepository } from 'src/repositories/activity.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; import { ViewRepository } from 'src/repositories/view-repository'; @@ -25,6 +26,19 @@ export type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInter export type IApiKeyRepository = RepositoryInterface; export type IAuditRepository = RepositoryInterface; export type IConfigRepository = RepositoryInterface; +export type ILoggingRepository = Pick< + LoggingRepository, + | 'verbose' + | 'log' + | 'debug' + | 'warn' + | 'error' + | 'fatal' + | 'isLevelEnabled' + | 'setLogLevel' + | 'setContext' + | 'setAppName' +>; export type IMediaRepository = RepositoryInterface; export type IMemoryRepository = RepositoryInterface; export type IViewRepository = RepositoryInterface; diff --git a/server/src/utils/config.ts b/server/src/utils/config.ts index 317f41d120..cd28c63618 100644 --- a/server/src/utils/config.ts +++ b/server/src/utils/config.ts @@ -7,9 +7,8 @@ import { SystemConfig, defaults } from 'src/config'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { SystemMetadataKey } from 'src/enum'; import { DatabaseLock } from 'src/interfaces/database.interface'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface'; -import { DeepPartial, IConfigRepository } from 'src/types'; +import { DeepPartial, IConfigRepository, ILoggingRepository } from 'src/types'; import { getKeysDeep, unsetDeep } from 'src/utils/misc'; export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise; @@ -17,7 +16,7 @@ export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConf type RepoDeps = { configRepo: IConfigRepository; metadataRepo: ISystemMetadataRepository; - logger: ILoggerRepository; + logger: ILoggingRepository; }; const asyncLock = new AsyncLock(); diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts index 869e4d7876..4f3009e39f 100644 --- a/server/src/utils/file.ts +++ b/server/src/utils/file.ts @@ -4,8 +4,8 @@ import { access, constants } from 'node:fs/promises'; import { basename, extname, isAbsolute } from 'node:path'; import { promisify } from 'node:util'; import { CacheControl } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ImmichReadStream } from 'src/interfaces/storage.interface'; +import { ILoggingRepository } from 'src/types'; import { isConnectionAborted } from 'src/utils/misc'; export function getFileNameWithoutExtension(path: string): string { @@ -37,7 +37,7 @@ export const sendFile = async ( res: Response, next: NextFunction, handler: () => Promise, - logger: ILoggerRepository, + logger: ILoggingRepository, ): 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 index cf66404d69..2fe2c618be 100644 --- a/server/src/utils/logger.ts +++ b/server/src/utils/logger.ts @@ -1,8 +1,8 @@ import { HttpException } from '@nestjs/common'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { ILoggingRepository } from 'src/types'; import { TypeORMError } from 'typeorm'; -export const logGlobalError = (logger: ILoggerRepository, error: Error) => { +export const logGlobalError = (logger: ILoggingRepository, error: Error) => { if (error instanceof HttpException) { const status = error.getStatus(); const response = error.getResponse(); diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts index fddaa1f061..d53f9ecf36 100644 --- a/server/src/utils/misc.ts +++ b/server/src/utils/misc.ts @@ -13,7 +13,7 @@ import path from 'node:path'; import { SystemConfig } from 'src/config'; import { CLIP_MODEL_INFO, serverVersion } from 'src/constants'; import { ImmichCookie, ImmichHeader, MetadataKey } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { ILoggingRepository } from 'src/types'; export class ImmichStartupError extends Error {} export const isStartUpError = (error: unknown): error is ImmichStartupError => error instanceof ImmichStartupError; @@ -96,7 +96,7 @@ export const isFaceImportEnabled = (metadata: SystemConfig['metadata']) => metad export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED'; -export const handlePromiseError = (promise: Promise, logger: ILoggerRepository): void => { +export const handlePromiseError = (promise: Promise, logger: ILoggingRepository): void => { promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack)); }; diff --git a/server/src/workers/api.ts b/server/src/workers/api.ts index 14786497c8..d6dc7233d1 100644 --- a/server/src/workers/api.ts +++ b/server/src/workers/api.ts @@ -7,9 +7,9 @@ import sirv from 'sirv'; import { ApiModule } from 'src/app.module'; import { excludePaths, serverVersion } from 'src/constants'; import { ImmichEnvironment } from 'src/enum'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { bootstrapTelemetry } from 'src/repositories/telemetry.repository'; import { ApiService } from 'src/services/api.service'; import { isStartUpError, useSwagger } from 'src/utils/misc'; @@ -23,7 +23,7 @@ async function bootstrap() { } const app = await NestFactory.create(ApiModule, { bufferLogs: true }); - const logger = await app.resolve(ILoggerRepository); + const logger = await app.resolve(LoggingRepository); const configRepository = app.get(ConfigRepository); const { environment, host, port, resourcePaths } = configRepository.getEnv(); diff --git a/server/src/workers/microservices.ts b/server/src/workers/microservices.ts index 34ad41ae26..d20064c436 100644 --- a/server/src/workers/microservices.ts +++ b/server/src/workers/microservices.ts @@ -2,9 +2,9 @@ import { NestFactory } from '@nestjs/core'; import { isMainThread } from 'node:worker_threads'; import { MicroservicesModule } from 'src/app.module'; import { serverVersion } from 'src/constants'; -import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; import { ConfigRepository } from 'src/repositories/config.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { bootstrapTelemetry } from 'src/repositories/telemetry.repository'; import { isStartUpError } from 'src/utils/misc'; @@ -15,7 +15,7 @@ export async function bootstrap() { } const app = await NestFactory.create(MicroservicesModule, { bufferLogs: true }); - const logger = await app.resolve(ILoggerRepository); + const logger = await app.resolve(LoggingRepository); logger.setContext('Bootstrap'); app.useLogger(logger); app.useWebSocketAdapter(new WebSocketAdapter(app)); diff --git a/server/test/medium/metadata.service.spec.ts b/server/test/medium/metadata.service.spec.ts index 3ccce0f16e..1750584018 100644 --- a/server/test/medium/metadata.service.spec.ts +++ b/server/test/medium/metadata.service.spec.ts @@ -5,13 +5,17 @@ import { join } from 'node:path'; import { AssetEntity } from 'src/entities/asset.entity'; import { IAssetRepository } from 'src/interfaces/asset.interface'; import { IStorageRepository } from 'src/interfaces/storage.interface'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { MetadataRepository } from 'src/repositories/metadata.repository'; import { MetadataService } from 'src/services/metadata.service'; -import { newLoggerRepositoryMock } from 'test/repositories/logger.repository.mock'; +import { ILoggingRepository } from 'src/types'; +import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock'; import { newRandomImage, newTestService } from 'test/utils'; import { Mocked } from 'vitest'; -const metadataRepository = new MetadataRepository(newLoggerRepositoryMock()); +const metadataRepository = new MetadataRepository( + newLoggingRepositoryMock() as ILoggingRepository as LoggingRepository, +); const createTestFile = async (exifData: Record) => { const data = newRandomImage(); diff --git a/server/test/repositories/logger.repository.mock.ts b/server/test/repositories/logger.repository.mock.ts index 6342e9e73c..0336a66090 100644 --- a/server/test/repositories/logger.repository.mock.ts +++ b/server/test/repositories/logger.repository.mock.ts @@ -1,7 +1,7 @@ -import { ILoggerRepository } from 'src/interfaces/logger.interface'; +import { ILoggingRepository } from 'src/types'; import { Mocked, vitest } from 'vitest'; -export const newLoggerRepositoryMock = (): Mocked => { +export const newLoggingRepositoryMock = (): Mocked => { return { setLogLevel: vitest.fn(), setContext: vitest.fn(), diff --git a/server/test/utils.ts b/server/test/utils.ts index 2ad14d5ee9..0ab1739e14 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -7,6 +7,7 @@ import { AccessRepository } from 'src/repositories/access.repository'; import { ActivityRepository } from 'src/repositories/activity.repository'; import { ApiKeyRepository } from 'src/repositories/api-key.repository'; import { AuditRepository } from 'src/repositories/audit.repository'; +import { LoggingRepository } from 'src/repositories/logging.repository'; import { MediaRepository } from 'src/repositories/media.repository'; import { MemoryRepository } from 'src/repositories/memory.repository'; import { ViewRepository } from 'src/repositories/view-repository'; @@ -16,6 +17,7 @@ import { IActivityRepository, IApiKeyRepository, IAuditRepository, + ILoggingRepository, IMediaRepository, IMemoryRepository, IViewRepository, @@ -34,7 +36,7 @@ import { newDatabaseRepositoryMock } from 'test/repositories/database.repository import { newEventRepositoryMock } from 'test/repositories/event.repository.mock'; import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock'; -import { newLoggerRepositoryMock } from 'test/repositories/logger.repository.mock'; +import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock'; import { newMachineLearningRepositoryMock } from 'test/repositories/machine-learning.repository.mock'; import { newMapRepositoryMock } from 'test/repositories/map.repository.mock'; import { newMediaRepositoryMock } from 'test/repositories/media.repository.mock'; @@ -78,7 +80,7 @@ export const newTestService = ( const { metadataRepository } = overrides || {}; const accessMock = newAccessRepositoryMock(); - const loggerMock = newLoggerRepositoryMock(); + const loggerMock = newLoggingRepositoryMock(); const cronMock = newCronRepositoryMock(); const cryptoMock = newCryptoRepositoryMock(); const activityMock = newActivityRepositoryMock(); @@ -118,7 +120,7 @@ export const newTestService = ( const viewMock = newViewRepositoryMock(); const sut = new Service( - loggerMock, + loggerMock as ILoggingRepository as LoggingRepository, accessMock as IAccessRepository as AccessRepository, activityMock as IActivityRepository as ActivityRepository, auditMock as IAuditRepository as AuditRepository,