Browse Source

add more log level switches (#1582)

* label block and json playouts as experimental

* add more log level switches
pull/1583/head
Jason Dove 2 years ago committed by GitHub
parent
commit
6923b25177
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      CHANGELOG.md
  2. 20
      ErsatzTV.Application/Configuration/Commands/UpdateGeneralSettingsHandler.cs
  3. 5
      ErsatzTV.Application/Configuration/GeneralSettingsViewModel.cs
  4. 16
      ErsatzTV.Application/Configuration/Queries/GetGeneralSettingsHandler.cs
  5. 11
      ErsatzTV.Application/Libraries/Commands/CallLibraryScannerHandler.cs
  6. 18
      ErsatzTV.Application/Streaming/HlsSessionWorker.cs
  7. 3
      ErsatzTV.Core/Domain/ConfigElementKey.cs
  8. 14
      ErsatzTV.Core/LoggingLevelSwitches.cs
  9. 6
      ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs
  10. 4
      ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs
  11. 2
      ErsatzTV/Controllers/InternalController.cs
  12. 2
      ErsatzTV/Controllers/IptvController.cs
  13. 2
      ErsatzTV/Pages/Channels.razor
  14. 16
      ErsatzTV/Pages/Playouts.razor
  15. 37
      ErsatzTV/Pages/Settings.razor
  16. 31
      ErsatzTV/Program.cs
  17. 26
      ErsatzTV/Services/RunOnce/LoadLoggingLevelService.cs

5
CHANGELOG.md

@ -39,6 +39,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -39,6 +39,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Channels MUST use `MPEG-TS` or `HLS Segmenter` streaming modes
- Since `MPEG-TS` uses `HLS Segmenter` under the hood, the preview player will use `HLS Segmenter`, so it's not 100% equivalent, but it should be representative
- Add button to stop transcoding session for each channel that has an active session
- Add more log levels to `Settings` page, allowing more specific debug logging as needed
- Default Minimum Log Level (applies when no other categories/level overrides match)
- Scanning Minimum Log Level
- Scheduling Minimum Log Level
- Streaming Minimum Log Level
### Fixed
- Fix error loading path replacements when using MySql

20
ErsatzTV.Application/Configuration/Commands/UpdateGeneralSettingsHandler.cs

@ -1,20 +1,19 @@ @@ -1,20 +1,19 @@
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
using Serilog.Core;
namespace ErsatzTV.Application.Configuration;
public class UpdateGeneralSettingsHandler : IRequestHandler<UpdateGeneralSettings, Either<BaseError, Unit>>
{
private readonly IConfigElementRepository _configElementRepository;
private readonly LoggingLevelSwitch _loggingLevelSwitch;
private readonly LoggingLevelSwitches _loggingLevelSwitches;
public UpdateGeneralSettingsHandler(
LoggingLevelSwitch loggingLevelSwitch,
LoggingLevelSwitches loggingLevelSwitches,
IConfigElementRepository configElementRepository)
{
_loggingLevelSwitch = loggingLevelSwitch;
_loggingLevelSwitches = loggingLevelSwitches;
_configElementRepository = configElementRepository;
}
@ -24,8 +23,17 @@ public class UpdateGeneralSettingsHandler : IRequestHandler<UpdateGeneralSetting @@ -24,8 +23,17 @@ public class UpdateGeneralSettingsHandler : IRequestHandler<UpdateGeneralSetting
private async Task<Unit> ApplyUpdate(GeneralSettingsViewModel generalSettings)
{
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevel, generalSettings.MinimumLogLevel);
_loggingLevelSwitch.MinimumLevel = generalSettings.MinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevel, generalSettings.DefaultMinimumLogLevel);
_loggingLevelSwitches.DefaultLevelSwitch.MinimumLevel = generalSettings.DefaultMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelScanning, generalSettings.ScanningMinimumLogLevel);
_loggingLevelSwitches.ScanningLevelSwitch.MinimumLevel = generalSettings.ScanningMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelScheduling, generalSettings.SchedulingMinimumLogLevel);
_loggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = generalSettings.SchedulingMinimumLogLevel;
await _configElementRepository.Upsert(ConfigElementKey.MinimumLogLevelStreaming, generalSettings.StreamingMinimumLogLevel);
_loggingLevelSwitches.StreamingLevelSwitch.MinimumLevel = generalSettings.StreamingMinimumLogLevel;
return Unit.Default;
}

5
ErsatzTV.Application/Configuration/GeneralSettingsViewModel.cs

@ -4,5 +4,8 @@ namespace ErsatzTV.Application.Configuration; @@ -4,5 +4,8 @@ namespace ErsatzTV.Application.Configuration;
public class GeneralSettingsViewModel
{
public LogEventLevel MinimumLogLevel { get; set; }
public LogEventLevel DefaultMinimumLogLevel { get; set; }
public LogEventLevel ScanningMinimumLogLevel { get; set; }
public LogEventLevel SchedulingMinimumLogLevel { get; set; }
public LogEventLevel StreamingMinimumLogLevel { get; set; }
}

16
ErsatzTV.Application/Configuration/Queries/GetGeneralSettingsHandler.cs

@ -13,12 +13,24 @@ public class GetGeneralSettingsHandler : IRequestHandler<GetGeneralSettings, Gen @@ -13,12 +13,24 @@ public class GetGeneralSettingsHandler : IRequestHandler<GetGeneralSettings, Gen
public async Task<GeneralSettingsViewModel> Handle(GetGeneralSettings request, CancellationToken cancellationToken)
{
Option<LogEventLevel> maybeLogLevel =
Option<LogEventLevel> maybeDefaultLevel =
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevel);
Option<LogEventLevel> maybeScanningLevel =
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScanning);
Option<LogEventLevel> maybeSchedulingLevel =
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScheduling);
Option<LogEventLevel> maybeStreamingLevel =
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelStreaming);
return new GeneralSettingsViewModel
{
MinimumLogLevel = await maybeLogLevel.IfNoneAsync(LogEventLevel.Information)
DefaultMinimumLogLevel = await maybeDefaultLevel.IfNoneAsync(LogEventLevel.Information),
ScanningMinimumLogLevel = await maybeScanningLevel.IfNoneAsync(LogEventLevel.Information),
SchedulingMinimumLogLevel = await maybeSchedulingLevel.IfNoneAsync(LogEventLevel.Information),
StreamingMinimumLogLevel = await maybeStreamingLevel.IfNoneAsync(LogEventLevel.Information),
};
}
}

11
ErsatzTV.Application/Libraries/Commands/CallLibraryScannerHandler.cs

@ -84,7 +84,16 @@ public abstract class CallLibraryScannerHandler<TRequest> @@ -84,7 +84,16 @@ public abstract class CallLibraryScannerHandler<TRequest>
// because the compact json writer used by the scanner
// writes in UTC
LogEvent logEvent = LogEventReader.ReadFromString(s);
Log.Write(
ILogger log = Log.Logger;
if (logEvent.Properties.TryGetValue("SourceContext", out LogEventPropertyValue property))
{
log = log.ForContext(
Serilog.Core.Constants.SourceContextPropertyName,
property.ToString().Trim('"'));
}
log.Write(
new LogEvent(
logEvent.Timestamp.ToLocalTime(),
logEvent.Level,

18
ErsatzTV.Application/Streaming/HlsSessionWorker.cs

@ -125,7 +125,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -125,7 +125,7 @@ public class HlsSessionWorker : IHlsSessionWorker
catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{
// do nothing
_logger.LogInformation("HlsSessionWorker.TrimPlaylist was canceled");
_logger.LogDebug("HlsSessionWorker.TrimPlaylist was canceled");
}
catch (Exception ex)
{
@ -302,7 +302,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -302,7 +302,7 @@ public class HlsSessionWorker : IHlsSessionWorker
if (!realtime)
{
Interlocked.Increment(ref _workAheadCount);
_logger.LogInformation("HLS segmenter will work ahead for channel {Channel}", _channelNumber);
_logger.LogDebug("HLS segmenter will work ahead for channel {Channel}", _channelNumber);
HlsSessionState nextState = _state switch
{
@ -319,7 +319,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -319,7 +319,7 @@ public class HlsSessionWorker : IHlsSessionWorker
}
else
{
_logger.LogInformation(
_logger.LogDebug(
"HLS segmenter will NOT work ahead for channel {Channel}",
_channelNumber);
@ -341,7 +341,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -341,7 +341,7 @@ public class HlsSessionWorker : IHlsSessionWorker
long ptsOffset = await GetPtsOffset(_channelNumber, cancellationToken);
// _logger.LogInformation("PTS offset: {PtsOffset}", ptsOffset);
_logger.LogInformation("HLS session state: {State}", _state);
_logger.LogDebug("HLS session state: {State}", _state);
DateTimeOffset now = _state is HlsSessionState.SeekAndWorkAhead
? DateTimeOffset.Now
@ -379,7 +379,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -379,7 +379,7 @@ public class HlsSessionWorker : IHlsSessionWorker
Command process = processModel.Process;
_logger.LogInformation("ffmpeg hls arguments {FFmpegArguments}", process.Arguments);
_logger.LogDebug("ffmpeg hls arguments {FFmpegArguments}", process.Arguments);
try
{
@ -389,7 +389,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -389,7 +389,7 @@ public class HlsSessionWorker : IHlsSessionWorker
if (commandResult.ExitCode == 0)
{
_logger.LogInformation("HLS process has completed for channel {Channel}", _channelNumber);
_logger.LogDebug("HLS process has completed for channel {Channel}", _channelNumber);
_logger.LogDebug("Transcoded until: {Until}", processModel.Until);
_transcodedUntil = processModel.Until;
_state = NextState(_state, processModel);
@ -427,7 +427,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -427,7 +427,7 @@ public class HlsSessionWorker : IHlsSessionWorker
{
Command errorProcess = errorProcessModel.Process;
_logger.LogInformation(
_logger.LogDebug(
"ffmpeg hls error arguments {FFmpegArguments}",
errorProcess.Arguments);
@ -451,7 +451,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -451,7 +451,7 @@ public class HlsSessionWorker : IHlsSessionWorker
}
catch (Exception ex) when (ex is TaskCanceledException or OperationCanceledException)
{
_logger.LogInformation("Terminating HLS process for channel {Channel}", _channelNumber);
_logger.LogInformation("Terminating HLS session for channel {Channel}", _channelNumber);
return false;
}
}
@ -600,7 +600,7 @@ public class HlsSessionWorker : IHlsSessionWorker @@ -600,7 +600,7 @@ public class HlsSessionWorker : IHlsSessionWorker
return await File.ReadAllLinesAsync(fileName, cancellationToken);
}
_logger.LogInformation("Playlist does not exist at expected location {File}", fileName);
_logger.LogDebug("Playlist does not exist at expected location {File}", fileName);
return None;
}

3
ErsatzTV.Core/Domain/ConfigElementKey.cs

@ -7,6 +7,9 @@ public class ConfigElementKey @@ -7,6 +7,9 @@ public class ConfigElementKey
public string Key { get; }
public static ConfigElementKey MinimumLogLevel => new("log.minimum_level");
public static ConfigElementKey MinimumLogLevelScanning => new("log.minimum_level.scanning");
public static ConfigElementKey MinimumLogLevelScheduling => new("log.minimum_level.scheduling");
public static ConfigElementKey MinimumLogLevelStreaming => new("log.minimum_level.streaming");
public static ConfigElementKey FFmpegPath => new("ffmpeg.ffmpeg_path");
public static ConfigElementKey FFprobePath => new("ffmpeg.ffprobe_path");
public static ConfigElementKey FFmpegDefaultProfileId => new("ffmpeg.default_profile_id");

14
ErsatzTV.Core/LoggingLevelSwitches.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using Serilog.Core;
namespace ErsatzTV.Core;
public class LoggingLevelSwitches
{
public LoggingLevelSwitch DefaultLevelSwitch { get; } = new();
public LoggingLevelSwitch ScanningLevelSwitch { get; } = new();
public LoggingLevelSwitch SchedulingLevelSwitch { get; } = new();
public LoggingLevelSwitch StreamingLevelSwitch { get; } = new();
}

6
ErsatzTV.FFmpeg/Capabilities/HardwareCapabilitiesFactory.cs

@ -293,7 +293,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory @@ -293,7 +293,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
if (profileEntrypoints is not null && profileEntrypoints.Count != 0)
{
_logger.LogInformation(
_logger.LogDebug(
"Detected {Count} VAAPI profile entrypoints for using {Driver} {Device}",
profileEntrypoints.Count,
driver,
@ -359,7 +359,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory @@ -359,7 +359,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
if (profileEntrypoints is not null && profileEntrypoints.Count != 0)
{
_logger.LogInformation(
_logger.LogDebug(
"Detected {Count} VAAPI profile entrypoints for using QSV device {Device}",
profileEntrypoints.Count,
device);
@ -408,7 +408,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory @@ -408,7 +408,7 @@ public class HardwareCapabilitiesFactory : IHardwareCapabilitiesFactory
const string MODEL_PATTERN = @"(GTX\s+[0-9a-zA-Z]+[\sTtIi]+)";
Match modelMatch = Regex.Match(line, MODEL_PATTERN);
string model = modelMatch.Success ? modelMatch.Groups[1].Value.Trim() : "unknown";
_logger.LogInformation(
_logger.LogDebug(
"Detected NVIDIA GPU model {Model} architecture SM {Architecture}",
model,
architecture);

4
ErsatzTV.FFmpeg/Pipeline/PipelineBuilderBase.cs

@ -659,7 +659,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -659,7 +659,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
if (ffmpegState.DecoderHardwareAccelerationMode != HardwareAccelerationMode.None ||
ffmpegState.EncoderHardwareAccelerationMode != HardwareAccelerationMode.None)
{
_logger.LogInformation(
_logger.LogDebug(
"Forcing {Threads} ffmpeg thread when hardware acceleration is used",
1);
@ -667,7 +667,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder @@ -667,7 +667,7 @@ public abstract class PipelineBuilderBase : IPipelineBuilder
}
else if (ffmpegState.Start.Exists(s => s > TimeSpan.Zero) && desiredState.Realtime)
{
_logger.LogInformation(
_logger.LogDebug(
"Forcing {Threads} ffmpeg thread due to buggy combination of stream seek and realtime output",
1);

2
ErsatzTV/Controllers/InternalController.cs

@ -53,7 +53,7 @@ public class InternalController : ControllerBase @@ -53,7 +53,7 @@ public class InternalController : ControllerBase
{
Command command = processModel.Process;
_logger.LogInformation("ffmpeg arguments {FFmpegArguments}", command.Arguments);
_logger.LogDebug("ffmpeg arguments {FFmpegArguments}", command.Arguments);
var process = new FFmpegProcess
{
StartInfo = new ProcessStartInfo

2
ErsatzTV/Controllers/IptvController.cs

@ -111,7 +111,7 @@ public class IptvController : ControllerBase @@ -111,7 +111,7 @@ public class IptvController : ControllerBase
Command command = processModel.Process;
_logger.LogInformation("Starting ts stream for channel {ChannelNumber}", channelNumber);
_logger.LogInformation("ffmpeg arguments {FFmpegArguments}", command.Arguments);
_logger.LogDebug("ffmpeg arguments {FFmpegArguments}", command.Arguments);
var process = new FFmpegProcess
{
StartInfo = new ProcessStartInfo

2
ErsatzTV/Pages/Channels.razor

@ -183,8 +183,6 @@ @@ -183,8 +183,6 @@
string currentUri = NavigationManager.Uri;
string streamUri = currentUri.Replace("/channels", $"/iptv/channel/{channel.Number}.m3u8?mode=segmenter");
Serilog.Log.Logger.Information("Stream uri: {StreamUri}", streamUri);
var parameters = new DialogParameters { { "StreamUri", streamUri } };
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraLarge };
await Dialog.ShowAsync<ChannelPreviewDialog>("Channel Preview", parameters, options);

16
ErsatzTV/Pages/Playouts.razor

@ -14,12 +14,16 @@ @@ -14,12 +14,16 @@
<MudButton Variant="Variant.Filled" Color="Color.Primary" Link="playouts/add">
Add Playout
</MudButton>
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" Link="@($"playouts/add/{PlayoutKind.Block}")">
Add Block Playout
</MudButton>
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" Link="@($"playouts/add/{PlayoutKind.ExternalJson}")">
Add External Json Playout
</MudButton>
<MudTooltip Text="This feature is experimental">
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Link="@($"playouts/add/{PlayoutKind.Block}")">
Add Block Playout
</MudButton>
</MudTooltip>
<MudTooltip Text="This feature is experimental">
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Link="@($"playouts/add/{PlayoutKind.ExternalJson}")">
Add External Json Playout
</MudButton>
</MudTooltip>
</div>
<MudTable Hover="true"
Dense="true"

37
ErsatzTV/Pages/Settings.razor

@ -121,9 +121,36 @@ @@ -121,9 +121,36 @@
<MudCardContent>
<MudForm>
<MudSelect Class="mt-3"
Label="Minimum Log Level"
@bind-Value="_generalSettings.MinimumLogLevel"
For="@(() => _generalSettings.MinimumLogLevel)">
Label="Default Minimum Log Level"
@bind-Value="_generalSettings.DefaultMinimumLogLevel"
For="@(() => _generalSettings.DefaultMinimumLogLevel)">
<MudSelectItem Value="@LogEventLevel.Debug">Debug</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Information">Information</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Warning">Warning</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Error">Error</MudSelectItem>
</MudSelect>
<MudSelect Class="mt-3"
Label="Scanning Minimum Log Level"
@bind-Value="_generalSettings.ScanningMinimumLogLevel"
For="@(() => _generalSettings.ScanningMinimumLogLevel)">
<MudSelectItem Value="@LogEventLevel.Debug">Debug</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Information">Information</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Warning">Warning</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Error">Error</MudSelectItem>
</MudSelect>
<MudSelect Class="mt-3"
Label="Scheduling Minimum Log Level"
@bind-Value="_generalSettings.SchedulingMinimumLogLevel"
For="@(() => _generalSettings.SchedulingMinimumLogLevel)">
<MudSelectItem Value="@LogEventLevel.Debug">Debug</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Information">Information</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Warning">Warning</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Error">Error</MudSelectItem>
</MudSelect>
<MudSelect Class="mt-3"
Label="Streaming Minimum Log Level"
@bind-Value="_generalSettings.StreamingMinimumLogLevel"
For="@(() => _generalSettings.StreamingMinimumLogLevel)">
<MudSelectItem Value="@LogEventLevel.Debug">Debug</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Information">Information</MudSelectItem>
<MudSelectItem Value="@LogEventLevel.Warning">Warning</MudSelectItem>
@ -132,7 +159,9 @@ @@ -132,7 +159,9 @@
</MudForm>
</MudCardContent>
<MudCardActions>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveGeneralSettings())">Save Settings</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveGeneralSettings())" StartIcon="@Icons.Material.Filled.Save">
Save Settings
</MudButton>
</MudCardActions>
</MudCard>
<MudCard Class="mb-6" Style="width: 350px">

31
ErsatzTV/Program.cs

@ -35,12 +35,12 @@ public class Program @@ -35,12 +35,12 @@ public class Program
.AddEnvironmentVariables()
.Build();
LoggingLevelSwitch = new LoggingLevelSwitch();
LoggingLevelSwitches = new LoggingLevelSwitches();
}
private static IConfiguration Configuration { get; }
private static LoggingLevelSwitch LoggingLevelSwitch { get; }
private static LoggingLevelSwitches LoggingLevelSwitches { get; }
public static async Task<int> Main(string[] args)
{
@ -54,11 +54,29 @@ public class Program @@ -54,11 +54,29 @@ public class Program
return 1;
}
LoggingLevelSwitch.MinimumLevel = LogEventLevel.Information;
LoggingLevelSwitches.DefaultLevelSwitch.MinimumLevel = LogEventLevel.Information;
LoggingLevelSwitches.ScanningLevelSwitch.MinimumLevel = LogEventLevel.Information;
LoggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = LogEventLevel.Information;
LoggingLevelSwitches.StreamingLevelSwitch.MinimumLevel = LogEventLevel.Information;
LoggerConfiguration loggerConfiguration = new LoggerConfiguration()
.ReadFrom.Configuration(Configuration)
.MinimumLevel.ControlledBy(LoggingLevelSwitch)
.MinimumLevel.ControlledBy(LoggingLevelSwitches.DefaultLevelSwitch)
// scanning
.MinimumLevel.Override("ErsatzTV.Services.ScannerService", LoggingLevelSwitches.ScanningLevelSwitch)
.MinimumLevel.Override("ErsatzTV.Scanner", LoggingLevelSwitches.ScanningLevelSwitch)
// scheduling
.MinimumLevel.Override("ErsatzTV.Core.Scheduling", LoggingLevelSwitches.SchedulingLevelSwitch)
.MinimumLevel.Override("ErsatzTV.Application.Subtitles.ExtractEmbeddedSubtitlesHandler", LoggingLevelSwitches.SchedulingLevelSwitch)
// streaming
.MinimumLevel.Override("ErsatzTV.Application.Streaming", LoggingLevelSwitches.StreamingLevelSwitch)
.MinimumLevel.Override("ErsatzTV.FFmpeg", LoggingLevelSwitches.StreamingLevelSwitch)
.MinimumLevel.Override("ErsatzTV.Controllers.IptvController", LoggingLevelSwitches.StreamingLevelSwitch)
.Destructure.UsingAttributes()
.Enrich.FromLogContext()
.WriteTo.File(
@ -78,7 +96,8 @@ public class Program @@ -78,7 +96,8 @@ public class Program
{
loggerConfiguration = loggerConfiguration.WriteTo.Console(
theme: AnsiConsoleTheme.Code,
formatProvider: CultureInfo.InvariantCulture);
formatProvider: CultureInfo.InvariantCulture,
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <{SourceContext:l}> {NewLine}{Exception}");
// for troubleshooting log category
// outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} <{SourceContext:l}> {NewLine}{Exception}"
@ -104,7 +123,7 @@ public class Program @@ -104,7 +123,7 @@ public class Program
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services => services.AddSingleton(LoggingLevelSwitch))
.ConfigureServices(services => services.AddSingleton(LoggingLevelSwitches))
.ConfigureWebHostDefaults(
webBuilder => webBuilder.UseStartup<Startup>()
.UseConfiguration(Configuration)

26
ErsatzTV/Services/RunOnce/LoadLoggingLevelService.cs

@ -31,12 +31,28 @@ public class LoadLoggingLevelService : BackgroundService @@ -31,12 +31,28 @@ public class LoadLoggingLevelService : BackgroundService
IConfigElementRepository configElementRepository =
scope.ServiceProvider.GetRequiredService<IConfigElementRepository>();
Option<LogEventLevel> maybeLogLevel =
await configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevel);
foreach (LogEventLevel logLevel in maybeLogLevel)
foreach (LogEventLevel logLevel in await configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevel))
{
LoggingLevelSwitch loggingLevelSwitch = scope.ServiceProvider.GetRequiredService<LoggingLevelSwitch>();
loggingLevelSwitch.MinimumLevel = logLevel;
LoggingLevelSwitches loggingLevelSwitches = scope.ServiceProvider.GetRequiredService<LoggingLevelSwitches>();
loggingLevelSwitches.DefaultLevelSwitch.MinimumLevel = logLevel;
}
foreach (LogEventLevel logLevel in await configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScanning))
{
LoggingLevelSwitches loggingLevelSwitches = scope.ServiceProvider.GetRequiredService<LoggingLevelSwitches>();
loggingLevelSwitches.ScanningLevelSwitch.MinimumLevel = logLevel;
}
foreach (LogEventLevel logLevel in await configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScheduling))
{
LoggingLevelSwitches loggingLevelSwitches = scope.ServiceProvider.GetRequiredService<LoggingLevelSwitches>();
loggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = logLevel;
}
foreach (LogEventLevel logLevel in await configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelStreaming))
{
LoggingLevelSwitches loggingLevelSwitches = scope.ServiceProvider.GetRequiredService<LoggingLevelSwitches>();
loggingLevelSwitches.StreamingLevelSwitch.MinimumLevel = logLevel;
}
}
}

Loading…
Cancel
Save