feat(web,server)!: runtime log level (#5672)

* feat: change log level at runtime

* chore: open api

* chore: prefer env over runtime

* chore: remove default env value
This commit is contained in:
Jason Rasmussen 2023-12-14 11:55:40 -05:00 committed by GitHub
parent f2270ad757
commit 9768931275
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 771 additions and 117 deletions

View file

@ -2,6 +2,7 @@ import {
AudioCodec,
Colorspace,
CQMode,
LogLevel,
SystemConfig,
SystemConfigEntity,
SystemConfigKey,
@ -11,7 +12,8 @@ import {
TranscodePolicy,
VideoCodec,
} from '@app/infra/entities';
import { BadRequestException, ForbiddenException, Injectable, Logger } from '@nestjs/common';
import { ImmichLogger } from '@app/infra/logger';
import { BadRequestException, ForbiddenException, Injectable } from '@nestjs/common';
import { CronExpression } from '@nestjs/schedule';
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
@ -21,7 +23,7 @@ import { QueueName } from '../job/job.constants';
import { ISystemConfigRepository } from '../repositories';
import { SystemConfigDto } from './dto';
export type SystemConfigValidator = (config: SystemConfig) => void | Promise<void>;
export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise<void>;
export const defaults = Object.freeze<SystemConfig>({
ffmpeg: {
@ -57,6 +59,10 @@ export const defaults = Object.freeze<SystemConfig>({
[QueueName.THUMBNAIL_GENERATION]: { concurrency: 5 },
[QueueName.VIDEO_CONVERSION]: { concurrency: 1 },
},
logging: {
enabled: true,
level: LogLevel.LOG,
},
machineLearning: {
enabled: process.env.IMMICH_MACHINE_LEARNING_ENABLED !== 'false',
url: process.env.IMMICH_MACHINE_LEARNING_URL || 'http://immich-machine-learning:3003',
@ -149,7 +155,7 @@ let instance: SystemConfigCore | null;
@Injectable()
export class SystemConfigCore {
private logger = new Logger(SystemConfigCore.name);
private logger = new ImmichLogger(SystemConfigCore.name);
private validators: SystemConfigValidator[] = [];
private configCache: SystemConfigEntity<SystemConfigValue>[] | null = null;
@ -253,14 +259,16 @@ export class SystemConfigCore {
return config;
}
public async updateConfig(config: SystemConfig): Promise<SystemConfig> {
public async updateConfig(newConfig: SystemConfig): Promise<SystemConfig> {
if (await this.hasFeature(FeatureFlag.CONFIG_FILE)) {
throw new BadRequestException('Cannot update configuration while IMMICH_CONFIG_FILE is in use');
}
const oldConfig = await this.getConfig();
try {
for (const validator of this.validators) {
await validator(config);
await validator(newConfig, oldConfig);
}
} catch (e) {
this.logger.warn(`Unable to save system config due to a validation error: ${e}`);
@ -272,9 +280,9 @@ export class SystemConfigCore {
for (const key of Object.values(SystemConfigKey)) {
// get via dot notation
const item = { key, value: _.get(config, key) as SystemConfigValue };
const item = { key, value: _.get(newConfig, key) as SystemConfigValue };
const defaultValue = _.get(defaults, key);
const isMissing = !_.has(config, key);
const isMissing = !_.has(newConfig, key);
if (
isMissing ||
@ -298,11 +306,11 @@ export class SystemConfigCore {
await this.repository.deleteKeys(deletes.map((item) => item.key));
}
const newConfig = await this.getConfig();
const config = await this.getConfig();
this.config$.next(newConfig);
this.config$.next(config);
return newConfig;
return config;
}
public async refreshConfig() {