Added Log level to background service (#685)

This commit is contained in:
Alex 2022-09-13 12:09:57 -05:00 committed by GitHub
parent 858ad43d3b
commit e79e92c60f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 37 deletions

View file

@ -36,6 +36,11 @@ REDIS_HOSTNAME=immich_redis
UPLOAD_LOCATION=absolute_location_on_your_machine_where_you_want_to_store_the_backup UPLOAD_LOCATION=absolute_location_on_your_machine_where_you_want_to_store_the_backup
###################################################################################
# Log message level - [simple|verbose]
###################################################################################
LOG_LEVEL=simple
################################################################################### ###################################################################################

View file

@ -13,7 +13,7 @@ import {
} from '@app/job/constants/queue-name.constant'; } from '@app/job/constants/queue-name.constant';
import { BullModule } from '@nestjs/bull'; import { BullModule } from '@nestjs/bull';
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config'; import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm'; import { TypeOrmModule } from '@nestjs/typeorm';
import { CommunicationModule } from '../../immich/src/api-v1/communication/communication.module'; import { CommunicationModule } from '../../immich/src/api-v1/communication/communication.module';
import { MicroservicesService } from './microservices.service'; import { MicroservicesService } from './microservices.service';
@ -40,42 +40,48 @@ import { VideoTranscodeProcessor } from './processors/video-transcode.processor'
}, },
}), }),
}), }),
BullModule.registerQueue({ BullModule.registerQueue(
name: thumbnailGeneratorQueueName, {
defaultJobOptions: { name: thumbnailGeneratorQueueName,
attempts: 3, defaultJobOptions: {
removeOnComplete: true, attempts: 3,
removeOnFail: false, removeOnComplete: true,
removeOnFail: false,
},
}, },
}, { {
name: assetUploadedQueueName, name: assetUploadedQueueName,
defaultJobOptions: { defaultJobOptions: {
attempts: 3, attempts: 3,
removeOnComplete: true, removeOnComplete: true,
removeOnFail: false, removeOnFail: false,
},
}, },
}, { {
name: metadataExtractionQueueName, name: metadataExtractionQueueName,
defaultJobOptions: { defaultJobOptions: {
attempts: 3, attempts: 3,
removeOnComplete: true, removeOnComplete: true,
removeOnFail: false, removeOnFail: false,
},
}, },
}, { {
name: videoConversionQueueName, name: videoConversionQueueName,
defaultJobOptions: { defaultJobOptions: {
attempts: 3, attempts: 3,
removeOnComplete: true, removeOnComplete: true,
removeOnFail: false, removeOnFail: false,
},
}, },
}, { {
name: generateChecksumQueueName, name: generateChecksumQueueName,
defaultJobOptions: { defaultJobOptions: {
attempts: 3, attempts: 3,
removeOnComplete: true, removeOnComplete: true,
removeOnFail: false, removeOnFail: false,
},
}, },
}), ),
CommunicationModule, CommunicationModule,
], ],
controllers: [], controllers: [],
@ -86,6 +92,7 @@ import { VideoTranscodeProcessor } from './processors/video-transcode.processor'
MetadataExtractionProcessor, MetadataExtractionProcessor,
VideoTranscodeProcessor, VideoTranscodeProcessor,
GenerateChecksumProcessor, GenerateChecksumProcessor,
ConfigService,
], ],
exports: [], exports: [],
}) })

View file

@ -1,3 +1,4 @@
import { ImmichLogLevel } from '@app/common/constants/log-level.constant';
import { AssetEntity } from '@app/database/entities/asset.entity'; import { AssetEntity } from '@app/database/entities/asset.entity';
import { ExifEntity } from '@app/database/entities/exif.entity'; import { ExifEntity } from '@app/database/entities/exif.entity';
import { SmartInfoEntity } from '@app/database/entities/smart-info.entity'; import { SmartInfoEntity } from '@app/database/entities/smart-info.entity';
@ -16,6 +17,7 @@ import { MapiResponse } from '@mapbox/mapbox-sdk/lib/classes/mapi-response';
import mapboxGeocoding, { GeocodeService } from '@mapbox/mapbox-sdk/services/geocoding'; import mapboxGeocoding, { GeocodeService } from '@mapbox/mapbox-sdk/services/geocoding';
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import axios from 'axios'; import axios from 'axios';
import { Job } from 'bull'; import { Job } from 'bull';
@ -28,6 +30,7 @@ import { Repository } from 'typeorm/repository/Repository';
@Processor(metadataExtractionQueueName) @Processor(metadataExtractionQueueName)
export class MetadataExtractionProcessor { export class MetadataExtractionProcessor {
private geocodingClient?: GeocodeService; private geocodingClient?: GeocodeService;
private logLevel: ImmichLogLevel;
constructor( constructor(
@InjectRepository(AssetEntity) @InjectRepository(AssetEntity)
@ -38,12 +41,16 @@ export class MetadataExtractionProcessor {
@InjectRepository(SmartInfoEntity) @InjectRepository(SmartInfoEntity)
private smartInfoRepository: Repository<SmartInfoEntity>, private smartInfoRepository: Repository<SmartInfoEntity>,
private configService: ConfigService,
) { ) {
if (process.env.ENABLE_MAPBOX == 'true' && process.env.MAPBOX_KEY) { if (process.env.ENABLE_MAPBOX == 'true' && process.env.MAPBOX_KEY) {
this.geocodingClient = mapboxGeocoding({ this.geocodingClient = mapboxGeocoding({
accessToken: process.env.MAPBOX_KEY, accessToken: process.env.MAPBOX_KEY,
}); });
} }
this.logLevel = this.configService.get('LOG_LEVEL') || ImmichLogLevel.SIMPLE;
} }
@Process(exifExtractionProcessorName) @Process(exifExtractionProcessorName)
@ -139,6 +146,10 @@ export class MetadataExtractionProcessor {
await this.exifRepository.save(newExif); await this.exifRepository.save(newExif);
} catch (e) { } catch (e) {
Logger.error(`Error extracting EXIF ${String(e)}`, 'extractExif'); Logger.error(`Error extracting EXIF ${String(e)}`, 'extractExif');
if (this.logLevel === ImmichLogLevel.VERBOSE) {
console.trace('Error extracting EXIF', e);
}
} }
} }

View file

@ -1,3 +1,4 @@
import { ImmichLogLevel } from '@app/common/constants/log-level.constant';
import { AssetEntity, AssetType } from '@app/database/entities/asset.entity'; import { AssetEntity, AssetType } from '@app/database/entities/asset.entity';
import { import {
WebpGeneratorProcessor, WebpGeneratorProcessor,
@ -11,6 +12,7 @@ import {
} from '@app/job'; } from '@app/job';
import { InjectQueue, Process, Processor } from '@nestjs/bull'; import { InjectQueue, Process, Processor } from '@nestjs/bull';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { mapAsset } from 'apps/immich/src/api-v1/asset/response-dto/asset-response.dto'; import { mapAsset } from 'apps/immich/src/api-v1/asset/response-dto/asset-response.dto';
import { Job, Queue } from 'bull'; import { Job, Queue } from 'bull';
@ -23,6 +25,8 @@ import { CommunicationGateway } from '../../../immich/src/api-v1/communication/c
@Processor(thumbnailGeneratorQueueName) @Processor(thumbnailGeneratorQueueName)
export class ThumbnailGeneratorProcessor { export class ThumbnailGeneratorProcessor {
private logLevel: ImmichLogLevel;
constructor( constructor(
@InjectRepository(AssetEntity) @InjectRepository(AssetEntity)
private assetRepository: Repository<AssetEntity>, private assetRepository: Repository<AssetEntity>,
@ -34,7 +38,11 @@ export class ThumbnailGeneratorProcessor {
@InjectQueue(metadataExtractionQueueName) @InjectQueue(metadataExtractionQueueName)
private metadataExtractionQueue: Queue, private metadataExtractionQueue: Queue,
) {}
private configService: ConfigService,
) {
this.logLevel = this.configService.get('LOG_LEVEL') || ImmichLogLevel.SIMPLE;
}
@Process({ name: generateJPEGThumbnailProcessorName, concurrency: 3 }) @Process({ name: generateJPEGThumbnailProcessorName, concurrency: 3 })
async generateJPEGThumbnail(job: Job<JpegGeneratorProcessor>) { async generateJPEGThumbnail(job: Job<JpegGeneratorProcessor>) {
@ -51,8 +59,16 @@ export class ThumbnailGeneratorProcessor {
const jpegThumbnailPath = resizePath + originalFilename + '.jpeg'; const jpegThumbnailPath = resizePath + originalFilename + '.jpeg';
if (asset.type == AssetType.IMAGE) { if (asset.type == AssetType.IMAGE) {
await sharp(asset.originalPath).resize(1440, 2560, { fit: 'inside' }).jpeg().rotate().toFile(jpegThumbnailPath); try {
await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath }); await sharp(asset.originalPath).resize(1440, 2560, { fit: 'inside' }).jpeg().rotate().toFile(jpegThumbnailPath);
await this.assetRepository.update({ id: asset.id }, { resizePath: jpegThumbnailPath });
} catch (error) {
Logger.error('Failed to generate jpeg thumbnail for asset: ' + asset.id);
if (this.logLevel == ImmichLogLevel.VERBOSE) {
console.trace('Failed to generate jpeg thumbnail for asset', error);
}
}
// Update resize path to send to generate webp queue // Update resize path to send to generate webp queue
asset.resizePath = jpegThumbnailPath; asset.resizePath = jpegThumbnailPath;
@ -105,7 +121,15 @@ export class ThumbnailGeneratorProcessor {
const webpPath = asset.resizePath.replace('jpeg', 'webp'); const webpPath = asset.resizePath.replace('jpeg', 'webp');
await sharp(asset.resizePath).resize(250).webp().rotate().toFile(webpPath); try {
await this.assetRepository.update({ id: asset.id }, { webpPath: webpPath }); await sharp(asset.resizePath).resize(250).webp().rotate().toFile(webpPath);
await this.assetRepository.update({ id: asset.id }, { webpPath: webpPath });
} catch (error) {
Logger.error('Failed to generate webp thumbnail for asset: ' + asset.id);
if (this.logLevel == ImmichLogLevel.VERBOSE) {
console.trace('Failed to generate webp thumbnail for asset', error);
}
}
} }
} }

View file

@ -16,5 +16,6 @@ export const immichAppConfig: ConfigModuleOptions = {
then: Joi.string().optional().allow(null, ''), then: Joi.string().optional().allow(null, ''),
otherwise: Joi.string().required(), otherwise: Joi.string().required(),
}), }),
LOG_LEVEL: Joi.string().optional().valid('simple', 'verbose').default('simple'),
}), }),
}; };

View file

@ -0,0 +1,4 @@
export enum ImmichLogLevel {
SIMPLE = 'simple',
VERBOSE = 'verbose',
}