From 3cd0d3022969b2c92a82533ba7b5caa62b858e51 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Mon, 25 Aug 2025 10:21:08 -0400 Subject: [PATCH 1/8] fix: support `--log-level` --- api/src/unraid-api/cli/restart.command.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index c3668f44ff..629908950f 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -1,9 +1,15 @@ -import { Command, CommandRunner } from 'nest-commander'; +import { Command, CommandRunner, Option } from 'nest-commander'; +import type { LogLevel } from '@app/core/log.js'; +import { levels } from '@app/core/log.js'; import { ECOSYSTEM_PATH } from '@app/environment.js'; import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; +interface RestartCommandOptions { + 'log-level'?: string; +} + @Command({ name: 'restart', description: 'Restart the Unraid API' }) export class RestartCommand extends CommandRunner { constructor( @@ -13,11 +19,11 @@ export class RestartCommand extends CommandRunner { super(); } - async run(): Promise { + async run(_: string[], options: RestartCommandOptions): Promise { try { this.logger.info('Restarting the Unraid API...'); const { stderr, stdout } = await this.pm2.run( - { tag: 'PM2 Restart', raw: true }, + { tag: 'PM2 Restart', raw: true, env: { LOG_LEVEL: options['log-level'] } }, 'restart', ECOSYSTEM_PATH, '--update-env' @@ -40,4 +46,13 @@ export class RestartCommand extends CommandRunner { process.exit(1); } } + + @Option({ + flags: `--log-level <${levels.join('|')}>`, + description: 'log level to use', + defaultValue: 'info', + }) + parseLogLevel(val: string): LogLevel { + return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info'; + } } From ad20aefb49bde9dcd0fb8ced4e2f89e4c951ad3f Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Mon, 25 Aug 2025 10:55:53 -0400 Subject: [PATCH 2/8] fix type check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit js abuse 🥲 --- api/src/unraid-api/cli/restart.command.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index 629908950f..f832ceb8f9 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -19,7 +19,7 @@ export class RestartCommand extends CommandRunner { super(); } - async run(_: string[], options: RestartCommandOptions): Promise { + async run(_?: string[], options: RestartCommandOptions = {}): Promise { try { this.logger.info('Restarting the Unraid API...'); const { stderr, stdout } = await this.pm2.run( From 393d82623d7ca471e5193b708a08b5e35c1b332d Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 13:17:40 -0400 Subject: [PATCH 3/8] add temporary logging to restart command --- api/src/unraid-api/cli/restart.command.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index f832ceb8f9..1c89d0a386 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -2,12 +2,12 @@ import { Command, CommandRunner, Option } from 'nest-commander'; import type { LogLevel } from '@app/core/log.js'; import { levels } from '@app/core/log.js'; -import { ECOSYSTEM_PATH } from '@app/environment.js'; +import { ECOSYSTEM_PATH, LOG_LEVEL } from '@app/environment.js'; import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; interface RestartCommandOptions { - 'log-level'?: string; + logLevel?: string; } @Command({ name: 'restart', description: 'Restart the Unraid API' }) @@ -21,9 +21,16 @@ export class RestartCommand extends CommandRunner { async run(_?: string[], options: RestartCommandOptions = {}): Promise { try { + this.logger.info( + JSON.stringify( + { options, env: LOG_LEVEL, target: options.logLevel ?? LOG_LEVEL }, + null, + 2 + ) + ); this.logger.info('Restarting the Unraid API...'); const { stderr, stdout } = await this.pm2.run( - { tag: 'PM2 Restart', raw: true, env: { LOG_LEVEL: options['log-level'] } }, + { tag: 'PM2 Restart', raw: true, env: { LOG_LEVEL: options.logLevel ?? LOG_LEVEL } }, 'restart', ECOSYSTEM_PATH, '--update-env' From 082bb581f61c39c780fe5b931cd94e05c7e5f27f Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 13:43:13 -0400 Subject: [PATCH 4/8] fix: incorrect reference to parsed log level option --- api/src/unraid-api/cli/restart.command.ts | 14 ++++---------- api/src/unraid-api/cli/start.command.ts | 18 +++++------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index 1c89d0a386..f628fe8a4f 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -6,7 +6,7 @@ import { ECOSYSTEM_PATH, LOG_LEVEL } from '@app/environment.js'; import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; -interface RestartCommandOptions { +export interface LogLevelOptions { logLevel?: string; } @@ -19,18 +19,12 @@ export class RestartCommand extends CommandRunner { super(); } - async run(_?: string[], options: RestartCommandOptions = {}): Promise { + async run(_?: string[], options: LogLevelOptions = {}): Promise { try { - this.logger.info( - JSON.stringify( - { options, env: LOG_LEVEL, target: options.logLevel ?? LOG_LEVEL }, - null, - 2 - ) - ); this.logger.info('Restarting the Unraid API...'); + const env = { LOG_LEVEL: options.logLevel ?? LOG_LEVEL }; const { stderr, stdout } = await this.pm2.run( - { tag: 'PM2 Restart', raw: true, env: { LOG_LEVEL: options.logLevel ?? LOG_LEVEL } }, + { tag: 'PM2 Restart', raw: true, extendEnv: true, env }, 'restart', ECOSYSTEM_PATH, '--update-env' diff --git a/api/src/unraid-api/cli/start.command.ts b/api/src/unraid-api/cli/start.command.ts index 33e2c4845d..591e55e949 100644 --- a/api/src/unraid-api/cli/start.command.ts +++ b/api/src/unraid-api/cli/start.command.ts @@ -1,15 +1,12 @@ import { Command, CommandRunner, Option } from 'nest-commander'; import type { LogLevel } from '@app/core/log.js'; +import type { LogLevelOptions } from '@app/unraid-api/cli/restart.command.js'; import { levels } from '@app/core/log.js'; -import { ECOSYSTEM_PATH } from '@app/environment.js'; +import { ECOSYSTEM_PATH, LOG_LEVEL } from '@app/environment.js'; import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; -interface StartCommandOptions { - 'log-level'?: string; -} - @Command({ name: 'start', description: 'Start the Unraid API' }) export class StartCommand extends CommandRunner { constructor( @@ -27,17 +24,12 @@ export class StartCommand extends CommandRunner { await this.pm2.run({ tag: 'PM2 Delete' }, 'delete', ECOSYSTEM_PATH); } - async run(_: string[], options: StartCommandOptions): Promise { + async run(_: string[], options: LogLevelOptions): Promise { this.logger.info('Starting the Unraid API'); await this.cleanupPM2State(); - - const env: Record = {}; - if (options['log-level']) { - env.LOG_LEVEL = options['log-level']; - } - + const env = { LOG_LEVEL: options.logLevel ?? LOG_LEVEL }; const { stderr, stdout } = await this.pm2.run( - { tag: 'PM2 Start', env, raw: true }, + { tag: 'PM2 Start', raw: true, extendEnv: true, env }, 'start', ECOSYSTEM_PATH, '--update-env' From eba353487fe3a34823fa8930857380abbec1f02b Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 13:44:23 -0400 Subject: [PATCH 5/8] doc: usage of LOG_LEVEL env var --- api/docs/public/cli.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/api/docs/public/cli.md b/api/docs/public/cli.md index 4bfa26e879..8f2ffa057d 100644 --- a/api/docs/public/cli.md +++ b/api/docs/public/cli.md @@ -21,8 +21,15 @@ unraid-api start [--log-level ] Starts the Unraid API service. Options: + - `--log-level`: Set logging level (trace|debug|info|warn|error) +Alternative: You can also set the log level using the `LOG_LEVEL` environment variable: + +```bash +LOG_LEVEL=trace unraid-api start +``` + ### Stop ```bash @@ -36,11 +43,21 @@ Stops the Unraid API service. ### Restart ```bash -unraid-api restart +unraid-api restart [--log-level ] ``` Restarts the Unraid API service. +Options: + +- `--log-level`: Set logging level (trace|debug|info|warn|error) + +Alternative: You can also set the log level using the `LOG_LEVEL` environment variable: + +```bash +LOG_LEVEL=trace unraid-api restart +``` + ### Logs ```bash From 3b011d9be44d6710dfb4a5a99fa6cb79a8df57aa Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 16:00:54 -0400 Subject: [PATCH 6/8] refactor: simplify default --log-level value --- api/src/unraid-api/cli/restart.command.ts | 6 +++--- api/src/unraid-api/cli/start.command.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index f628fe8a4f..924fb4c348 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -7,7 +7,7 @@ import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; export interface LogLevelOptions { - logLevel?: string; + logLevel?: LogLevel; } @Command({ name: 'restart', description: 'Restart the Unraid API' }) @@ -22,7 +22,7 @@ export class RestartCommand extends CommandRunner { async run(_?: string[], options: LogLevelOptions = {}): Promise { try { this.logger.info('Restarting the Unraid API...'); - const env = { LOG_LEVEL: options.logLevel ?? LOG_LEVEL }; + const env = { LOG_LEVEL: options.logLevel }; const { stderr, stdout } = await this.pm2.run( { tag: 'PM2 Restart', raw: true, extendEnv: true, env }, 'restart', @@ -51,7 +51,7 @@ export class RestartCommand extends CommandRunner { @Option({ flags: `--log-level <${levels.join('|')}>`, description: 'log level to use', - defaultValue: 'info', + defaultValue: LOG_LEVEL, }) parseLogLevel(val: string): LogLevel { return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info'; diff --git a/api/src/unraid-api/cli/start.command.ts b/api/src/unraid-api/cli/start.command.ts index 591e55e949..9234d3c739 100644 --- a/api/src/unraid-api/cli/start.command.ts +++ b/api/src/unraid-api/cli/start.command.ts @@ -27,7 +27,7 @@ export class StartCommand extends CommandRunner { async run(_: string[], options: LogLevelOptions): Promise { this.logger.info('Starting the Unraid API'); await this.cleanupPM2State(); - const env = { LOG_LEVEL: options.logLevel ?? LOG_LEVEL }; + const env = { LOG_LEVEL: options.logLevel }; const { stderr, stdout } = await this.pm2.run( { tag: 'PM2 Start', raw: true, extendEnv: true, env }, 'start', @@ -46,7 +46,7 @@ export class StartCommand extends CommandRunner { @Option({ flags: `--log-level <${levels.join('|')}>`, description: 'log level to use', - defaultValue: 'info', + defaultValue: LOG_LEVEL, }) parseLogLevel(val: string): LogLevel { return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info'; From 9aec6e7645886973812edc57f56c8a06aa461b15 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 16:02:02 -0400 Subject: [PATCH 7/8] add fatal log level option --- api/docs/public/cli.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/docs/public/cli.md b/api/docs/public/cli.md index 8f2ffa057d..27d33c4322 100644 --- a/api/docs/public/cli.md +++ b/api/docs/public/cli.md @@ -22,7 +22,7 @@ Starts the Unraid API service. Options: -- `--log-level`: Set logging level (trace|debug|info|warn|error) +- `--log-level`: Set logging level (trace|debug|info|warn|error|fatal) Alternative: You can also set the log level using the `LOG_LEVEL` environment variable: @@ -50,7 +50,7 @@ Restarts the Unraid API service. Options: -- `--log-level`: Set logging level (trace|debug|info|warn|error) +- `--log-level`: Set logging level (trace|debug|info|warn|error|fatal) Alternative: You can also set the log level using the `LOG_LEVEL` environment variable: From aad2b5bfaddbe833f208665ff41e7c138d0dce11 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Thu, 28 Aug 2025 16:29:08 -0400 Subject: [PATCH 8/8] make log level parsing stricter --- api/src/unraid-api/cli/restart.command.ts | 12 ++++++++++-- api/src/unraid-api/cli/start.command.ts | 5 +++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/api/src/unraid-api/cli/restart.command.ts b/api/src/unraid-api/cli/restart.command.ts index 924fb4c348..da6005a68c 100644 --- a/api/src/unraid-api/cli/restart.command.ts +++ b/api/src/unraid-api/cli/restart.command.ts @@ -10,6 +10,14 @@ export interface LogLevelOptions { logLevel?: LogLevel; } +export function parseLogLevelOption(val: string, allowedLevels: string[] = [...levels]): LogLevel { + const normalized = val.toLowerCase() as LogLevel; + if (allowedLevels.includes(normalized)) { + return normalized; + } + throw new Error(`Invalid --log-level "${val}". Allowed: ${allowedLevels.join(', ')}`); +} + @Command({ name: 'restart', description: 'Restart the Unraid API' }) export class RestartCommand extends CommandRunner { constructor( @@ -51,9 +59,9 @@ export class RestartCommand extends CommandRunner { @Option({ flags: `--log-level <${levels.join('|')}>`, description: 'log level to use', - defaultValue: LOG_LEVEL, + defaultValue: LOG_LEVEL.toLowerCase(), }) parseLogLevel(val: string): LogLevel { - return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info'; + return parseLogLevelOption(val); } } diff --git a/api/src/unraid-api/cli/start.command.ts b/api/src/unraid-api/cli/start.command.ts index 9234d3c739..74d512574b 100644 --- a/api/src/unraid-api/cli/start.command.ts +++ b/api/src/unraid-api/cli/start.command.ts @@ -6,6 +6,7 @@ import { levels } from '@app/core/log.js'; import { ECOSYSTEM_PATH, LOG_LEVEL } from '@app/environment.js'; import { LogService } from '@app/unraid-api/cli/log.service.js'; import { PM2Service } from '@app/unraid-api/cli/pm2.service.js'; +import { parseLogLevelOption } from '@app/unraid-api/cli/restart.command.js'; @Command({ name: 'start', description: 'Start the Unraid API' }) export class StartCommand extends CommandRunner { @@ -46,9 +47,9 @@ export class StartCommand extends CommandRunner { @Option({ flags: `--log-level <${levels.join('|')}>`, description: 'log level to use', - defaultValue: LOG_LEVEL, + defaultValue: LOG_LEVEL.toLowerCase(), }) parseLogLevel(val: string): LogLevel { - return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info'; + return parseLogLevelOption(val); } }