Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions api/docs/public/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ unraid-api start [--log-level <level>]
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:

```bash
LOG_LEVEL=trace unraid-api start
```

### Stop

Expand All @@ -36,11 +43,21 @@ Stops the Unraid API service.
### Restart

```bash
unraid-api restart
unraid-api restart [--log-level <level>]
```

Restarts the Unraid API service.

Options:

- `--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:

```bash
LOG_LEVEL=trace unraid-api restart
```

### Logs

```bash
Expand Down
32 changes: 28 additions & 4 deletions api/src/unraid-api/cli/restart.command.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { Command, CommandRunner } from 'nest-commander';
import { Command, CommandRunner, Option } from 'nest-commander';

import { ECOSYSTEM_PATH } from '@app/environment.js';
import type { LogLevel } from '@app/core/log.js';
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';

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(
Expand All @@ -13,11 +27,12 @@ export class RestartCommand extends CommandRunner {
super();
}

async run(): Promise<void> {
async run(_?: string[], options: LogLevelOptions = {}): Promise<void> {
try {
this.logger.info('Restarting the Unraid API...');
const env = { LOG_LEVEL: options.logLevel };
const { stderr, stdout } = await this.pm2.run(
{ tag: 'PM2 Restart', raw: true },
{ tag: 'PM2 Restart', raw: true, extendEnv: true, env },
'restart',
Comment on lines +30 to 36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Don’t clobber existing PM2 env when flag is omitted; only set LOG_LEVEL when present.

Currently we always pass LOG_LEVEL, which can override the process’s saved/env-configured level. Respect “fallback to existing LOG_LEVEL” by conditionally setting it.

   async run(_?: string[], options: LogLevelOptions = {}): Promise<void> {
     try {
       this.logger.info('Restarting the Unraid API...');
-      const env = { LOG_LEVEL: options.logLevel };
+      // Use explicit flag if provided; else use shell env if set; else don't override PM2 env.
+      const level =
+        options.logLevel ??
+        (process.env.LOG_LEVEL ? parseLogLevelOption(process.env.LOG_LEVEL) : undefined);
+      const env: NodeJS.ProcessEnv | undefined = level ? { LOG_LEVEL: level } : undefined;
       const { stderr, stdout } = await this.pm2.run(
-        { tag: 'PM2 Restart', raw: true, extendEnv: true, env },
+        { tag: 'PM2 Restart', raw: true, extendEnv: true, ...(env ? { env } : {}) },
         'restart',
         ECOSYSTEM_PATH,
         '--update-env'
       );

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In api/src/unraid-api/cli/restart.command.ts around lines 30 to 36, the code
always passes a LOG_LEVEL key to PM2 which can overwrite a saved/previous
LOG_LEVEL; change the env construction to add LOG_LEVEL only when
options.logLevel is non-null/undefined (e.g., conditionally set env.LOG_LEVEL or
build env via a spread when options.logLevel is present) and only include the
env parameter in the pm2.run call when that env object is non-empty so existing
PM2 process env values are preserved when the flag is omitted.

ECOSYSTEM_PATH,
'--update-env'
Expand All @@ -40,4 +55,13 @@ export class RestartCommand extends CommandRunner {
process.exit(1);
}
}

@Option({
flags: `--log-level <${levels.join('|')}>`,
description: 'log level to use',
defaultValue: LOG_LEVEL.toLowerCase(),
})
parseLogLevel(val: string): LogLevel {
return parseLogLevelOption(val);
}
}
23 changes: 8 additions & 15 deletions api/src/unraid-api/cli/start.command.ts
Original file line number Diff line number Diff line change
@@ -1,14 +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;
}
import { parseLogLevelOption } from '@app/unraid-api/cli/restart.command.js';

@Command({ name: 'start', description: 'Start the Unraid API' })
export class StartCommand extends CommandRunner {
Expand All @@ -27,17 +25,12 @@ export class StartCommand extends CommandRunner {
await this.pm2.run({ tag: 'PM2 Delete' }, 'delete', ECOSYSTEM_PATH);
}

async run(_: string[], options: StartCommandOptions): Promise<void> {
async run(_: string[], options: LogLevelOptions): Promise<void> {
this.logger.info('Starting the Unraid API');
await this.cleanupPM2State();

const env: Record<string, string> = {};
if (options['log-level']) {
env.LOG_LEVEL = options['log-level'];
}

const env = { LOG_LEVEL: options.logLevel };
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'
Expand All @@ -54,9 +47,9 @@ export class StartCommand extends CommandRunner {
@Option({
flags: `--log-level <${levels.join('|')}>`,
description: 'log level to use',
defaultValue: 'info',
defaultValue: LOG_LEVEL.toLowerCase(),
})
parseLogLevel(val: string): LogLevel {
return levels.includes(val as LogLevel) ? (val as LogLevel) : 'info';
return parseLogLevelOption(val);
}
}
Loading