Summary
Setting LISTENARR_LOG_LEVEL=Trace does not increase log verbosity. It silently drops to Information, so it produces less detail than a valid level while looking like it took effect. "Turn on trace logging" is usually the first thing a maintainer asks a bug reporter to do, which is what makes the silent part costly.
Where it comes from
ConfigureSerilog in listenarr.api/Startup/ListenarrBuilderFactory.cs:158-176 parses both the env var and the config value with Enum.TryParse<LogEventLevel>:
var logLevelEnv = Environment.GetEnvironmentVariable("LISTENARR_LOG_LEVEL"); // line 161
...
if (!string.IsNullOrWhiteSpace(logLevelEnv) && Enum.TryParse<LogEventLevel>(logLevelEnv, ignoreCase: true, out var parsedFromEnv)) // line 165
minimumLevel = parsedFromEnv;
else if (...config...) // line 169
minimumLevel = parsedFromConfig;
else
minimumLevel = LogEventLevel.Information; // line 175
Serilog's LogEventLevel has no Trace member. Its levels are Verbose, Debug, Information, Warning, Error, Fatal. So Trace fails Enum.TryParse, the env branch is skipped, and (absent a valid config value) execution falls through to minimumLevel = LogEventLevel.Information. Nothing is logged to say the requested level was not understood. (Read: ListenarrBuilderFactory.cs:158-176.)
The trap is that Trace reads like a legitimate, more-verbose-than-Debug level to anyone coming from .NET's Microsoft.Extensions.Logging, where Trace is exactly that. Serilog just spells the equivalent Verbose.
Effect
Measured while working the #890 case on stock ghcr.io/listenarrs/listenarr:canary at a630572: a synthetic import run logged 124 lines with LISTENARR_LOG_LEVEL=Trace versus 205 lines at a valid Serilog level. The lines lost in the Trace run included the ones naming the cause of the import failure, so the setting most likely to be requested during triage actively removed the detail being asked for.
Suggested fix
Small and self-contained:
- Map
Trace to Verbose before/inside the parse, since Verbose is what a user typing Trace intends.
- When a level string is non-empty but unrecognized, log a warning naming the value and the levels that are accepted, rather than falling silently to
Information. That way the next person who mistypes a level finds out immediately.
This file is not touched by #993, so the change does not collide with that work.
I am happy to open a PR for this if useful.
Environment
Reproduced on stock ghcr.io/listenarrs/listenarr:canary at commit a630572.
Disclosure: drafted with Claude Code at my direction; I read the cited code at the stated commit and reviewed this before posting.
Summary
Setting
LISTENARR_LOG_LEVEL=Tracedoes not increase log verbosity. It silently drops toInformation, so it produces less detail than a valid level while looking like it took effect. "Turn on trace logging" is usually the first thing a maintainer asks a bug reporter to do, which is what makes the silent part costly.Where it comes from
ConfigureSeriloginlistenarr.api/Startup/ListenarrBuilderFactory.cs:158-176parses both the env var and the config value withEnum.TryParse<LogEventLevel>:Serilog's
LogEventLevelhas noTracemember. Its levels areVerbose,Debug,Information,Warning,Error,Fatal. SoTracefailsEnum.TryParse, the env branch is skipped, and (absent a valid config value) execution falls through tominimumLevel = LogEventLevel.Information. Nothing is logged to say the requested level was not understood. (Read: ListenarrBuilderFactory.cs:158-176.)The trap is that
Tracereads like a legitimate, more-verbose-than-Debug level to anyone coming from .NET'sMicrosoft.Extensions.Logging, whereTraceis exactly that. Serilog just spells the equivalentVerbose.Effect
Measured while working the #890 case on stock
ghcr.io/listenarrs/listenarr:canaryat a630572: a synthetic import run logged 124 lines withLISTENARR_LOG_LEVEL=Traceversus 205 lines at a valid Serilog level. The lines lost in theTracerun included the ones naming the cause of the import failure, so the setting most likely to be requested during triage actively removed the detail being asked for.Suggested fix
Small and self-contained:
TracetoVerbosebefore/inside the parse, sinceVerboseis what a user typingTraceintends.Information. That way the next person who mistypes a level finds out immediately.This file is not touched by #993, so the change does not collide with that work.
I am happy to open a PR for this if useful.
Environment
Reproduced on stock
ghcr.io/listenarrs/listenarr:canaryat commit a630572.Disclosure: drafted with Claude Code at my direction; I read the cited code at the stated commit and reviewed this before posting.