mirror of
https://github.com/chrisbenincasa/tunarr.git
synced 2026-04-18 09:03:35 -04:00
fix: properly set child log levels on level change from UI
This commit is contained in:
@@ -6,7 +6,8 @@ import { SavePlexProgramExternalIdsTask } from '@/tasks/plex/SavePlexProgramExte
|
||||
import { DateTimeRange } from '@/types/DateTimeRange.js';
|
||||
import { OpenDateTimeRange } from '@/types/OpenDateTimeRange.js';
|
||||
import type { RouterPluginAsyncCallback } from '@/types/serverType.js';
|
||||
import { tag } from '@tunarr/types';
|
||||
import { LoggerFactory } from '@/util/logging/LoggerFactory.js';
|
||||
import { LogLevels, tag } from '@tunarr/types';
|
||||
import { ChannelLineupQuery } from '@tunarr/types/api';
|
||||
import { ChannelLineupSchema } from '@tunarr/types/schemas';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -44,6 +45,23 @@ export const debugApi: RouterPluginAsyncCallback = async (fastify) => {
|
||||
return res.send(getHeapStatistics());
|
||||
});
|
||||
|
||||
fastify.get(
|
||||
'/debug/log',
|
||||
{
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
level: z.enum(LogLevels).default('debug'),
|
||||
log: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (req, res) => {
|
||||
const logger = LoggerFactory.root;
|
||||
logger[req.query.level](req.query.log ?? 'Test log');
|
||||
return res.send('ok');
|
||||
},
|
||||
);
|
||||
|
||||
fastify.get(
|
||||
'/debug/helpers/playing_at',
|
||||
{
|
||||
|
||||
@@ -31,11 +31,6 @@ import type { SerializedLogger } from './LoggerWrapper.ts';
|
||||
import { RootLoggerWrapper } from './LoggerWrapper.ts';
|
||||
import { RollingLogDestination } from './RollingDestination.ts';
|
||||
|
||||
export const LogConfigEnvVars = {
|
||||
level: 'LOG_LEVEL',
|
||||
directory: 'LOG_DIRECTORY',
|
||||
} as const;
|
||||
|
||||
export function getEnvironmentLogLevel(envVar?: string): Maybe<LogLevels> {
|
||||
const envLevel = trim(
|
||||
toLower(process.env[envVar ?? TUNARR_ENV_VARS.LOG_LEVEL_ENV_VAR]),
|
||||
@@ -108,12 +103,12 @@ export const LogCategories = ['streaming', 'scheduling'] as const;
|
||||
export type LogCategory = TupleToUnion<typeof LogCategories>;
|
||||
|
||||
class LoggerFactoryImpl {
|
||||
private settingsDB: SettingsDB;
|
||||
private settingsDB?: SettingsDB;
|
||||
// private rootLogger: PinoLogger<ExtraLogLevels>;
|
||||
private rootLogger!: RootLoggerWrapper;
|
||||
private initialized = false;
|
||||
private children: Record<string, WeakRef<Logger>> = {};
|
||||
private currentStreams: MultiStreamRes<LogLevels>;
|
||||
private currentStreams?: MultiStreamRes<LogLevels>;
|
||||
private roller?: RollingLogDestination;
|
||||
|
||||
constructor() {
|
||||
@@ -136,7 +131,7 @@ class LoggerFactoryImpl {
|
||||
}
|
||||
|
||||
const currentSettings =
|
||||
this.settingsDB.systemSettings().logging.logRollConfig;
|
||||
this.settingsDB?.systemSettings().logging.logRollConfig;
|
||||
|
||||
const { level: newLevel } = this.logLevel;
|
||||
const perCategoryLogLevel = this.perCategoryLogLevel;
|
||||
@@ -272,12 +267,11 @@ class LoggerFactoryImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the level of the root logger and all children
|
||||
// We do this by setting the level on the instance directly
|
||||
// but then for multistream to work, we have to manually reset the streams
|
||||
// by cloning them with new levels.
|
||||
this.rootLogger.level = newLevel;
|
||||
this.rootLogger.updateStreams(this.createLogStreams(newLevel));
|
||||
// Reset the level of the root logger and all children.
|
||||
// We set the level on every logger instance directly because pino children
|
||||
// snapshot the parent's level at creation time and don't follow changes.
|
||||
// For multistream to work, we also have to manually reset the streams.
|
||||
this.rootLogger.updateLevel(newLevel, this.createLogStreams(newLevel));
|
||||
}
|
||||
|
||||
private createStreams(logLevel: LogLevels): StreamEntry<LogLevels>[] {
|
||||
|
||||
@@ -25,6 +25,7 @@ interface ILoggerWrapper {
|
||||
args: GetChildLoggerArgs,
|
||||
opts?: ChildLoggerOptions<LogLevels>,
|
||||
): ILoggerWrapper;
|
||||
updateLevel(level: LogLevels, streams: MultiStreamRes<LogLevels>): void;
|
||||
updateStreams(streams: MultiStreamRes<LogLevels>): void;
|
||||
logger: Logger;
|
||||
traverseHierarchy(): Generator<readonly [string, SerializedLogger]>;
|
||||
@@ -32,7 +33,7 @@ interface ILoggerWrapper {
|
||||
}
|
||||
|
||||
abstract class BaseLoggerWrapper implements ILoggerWrapper {
|
||||
protected children: Record<string, WeakRef<ILoggerWrapper>> = {};
|
||||
protected children: Record<string, ILoggerWrapper> = {};
|
||||
|
||||
constructor(protected wrappedLogger: Logger) {}
|
||||
|
||||
@@ -41,14 +42,20 @@ abstract class BaseLoggerWrapper implements ILoggerWrapper {
|
||||
opts?: ChildLoggerOptions<LogLevels>,
|
||||
): ILoggerWrapper;
|
||||
|
||||
updateLevel(level: LogLevels, streams: MultiStreamRes<LogLevels>) {
|
||||
this.wrappedLogger.level = level;
|
||||
Object.assign(this.wrappedLogger[symbols.streamSym], streams);
|
||||
|
||||
for (const child of Object.values(this.children)) {
|
||||
child.updateLevel(level, streams);
|
||||
}
|
||||
}
|
||||
|
||||
updateStreams(streams: MultiStreamRes<LogLevels>) {
|
||||
Object.assign(this.wrappedLogger[symbols.streamSym], streams);
|
||||
|
||||
for (const childRef of Object.values(this.children)) {
|
||||
const child = childRef.deref();
|
||||
if (child) {
|
||||
child.updateStreams(streams);
|
||||
}
|
||||
for (const child of Object.values(this.children)) {
|
||||
child.updateStreams(streams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +74,8 @@ abstract class BaseLoggerWrapper implements ILoggerWrapper {
|
||||
}
|
||||
|
||||
*traverseHierarchy() {
|
||||
for (const [loggerName, ref] of Object.entries(this.children)) {
|
||||
const child = ref.deref();
|
||||
for (const [loggerName, child] of Object.entries(this.children)) {
|
||||
// const child = ref.deref();
|
||||
if (!child) {
|
||||
continue;
|
||||
}
|
||||
@@ -110,7 +117,7 @@ export class RootLoggerWrapper extends BaseLoggerWrapper {
|
||||
{ level: initialLogSettings?.categoryLogLevel?.[category] },
|
||||
);
|
||||
const wrapped = new LoggerWrapper(categoryLogger);
|
||||
this.children[`category:${category}`] = new WeakRef(wrapped);
|
||||
this.children[`category:${category}`] = wrapped;
|
||||
this.loggerByCategory.set(category, wrapped);
|
||||
}
|
||||
}
|
||||
@@ -121,7 +128,7 @@ export class RootLoggerWrapper extends BaseLoggerWrapper {
|
||||
): ILoggerWrapper {
|
||||
const { caller, className, category, ...rest } = args;
|
||||
|
||||
const ref = this.children[className]?.deref();
|
||||
const ref = this.children[className]; //?.deref();
|
||||
if (ref) {
|
||||
return ref;
|
||||
}
|
||||
@@ -145,15 +152,11 @@ export class RootLoggerWrapper extends BaseLoggerWrapper {
|
||||
} else {
|
||||
const newLogger = this.wrappedLogger.child(childOpts, opts);
|
||||
const wrapped = new LoggerWrapper(newLogger);
|
||||
this.children[className] = new WeakRef(wrapped);
|
||||
this.children[className] = wrapped;
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
|
||||
set level(newLevel: LogLevels) {
|
||||
this.wrappedLogger.level = newLevel;
|
||||
}
|
||||
|
||||
updateCategoryLevel(
|
||||
newLevel: LogLevels,
|
||||
category: LogCategory,
|
||||
@@ -164,8 +167,7 @@ export class RootLoggerWrapper extends BaseLoggerWrapper {
|
||||
return;
|
||||
}
|
||||
|
||||
rootCategoryLogger.logger.level = newLevel;
|
||||
rootCategoryLogger.updateStreams(newStreamFn());
|
||||
rootCategoryLogger.updateLevel(newLevel, newStreamFn());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@ export class LoggerWrapper extends BaseLoggerWrapper {
|
||||
): ILoggerWrapper {
|
||||
const { caller, className, ...rest } = args;
|
||||
|
||||
const ref = this.children[className]?.deref();
|
||||
const ref = this.children[className]; //?.deref();
|
||||
if (ref) {
|
||||
return ref;
|
||||
}
|
||||
@@ -208,7 +210,7 @@ export class LoggerWrapper extends BaseLoggerWrapper {
|
||||
const newChild = new LoggerWrapper(
|
||||
this.wrappedLogger.child(childOpts, opts),
|
||||
);
|
||||
this.children[className] = new WeakRef(newChild);
|
||||
this.children[className] = newChild;
|
||||
return newChild;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user