add searching log category (#2251)
This commit is contained in:
@@ -59,6 +59,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
### Changed
|
### Changed
|
||||||
- Always tell ffmpeg to stop encoding with a specific duration
|
- Always tell ffmpeg to stop encoding with a specific duration
|
||||||
- This was removed to try to improve transitions with ffmpeg 7.x, but has been causing issues with other content
|
- This was removed to try to improve transitions with ffmpeg 7.x, but has been causing issues with other content
|
||||||
|
- Move search debug logging to its own log category; add `Searching Minimum Log Level` to `Settings` > `Logging`
|
||||||
|
|
||||||
## [25.3.1] - 2025-07-24
|
## [25.3.1] - 2025-07-24
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ public class UpdateLoggingSettingsHandler : IRequestHandler<UpdateLoggingSetting
|
|||||||
loggingSettings.SchedulingMinimumLogLevel);
|
loggingSettings.SchedulingMinimumLogLevel);
|
||||||
_loggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = loggingSettings.SchedulingMinimumLogLevel;
|
_loggingLevelSwitches.SchedulingLevelSwitch.MinimumLevel = loggingSettings.SchedulingMinimumLogLevel;
|
||||||
|
|
||||||
|
await _configElementRepository.Upsert(
|
||||||
|
ConfigElementKey.MinimumLogLevelSearching,
|
||||||
|
loggingSettings.SearchingMinimumLogLevel);
|
||||||
|
_loggingLevelSwitches.SearchingLevelSwitch.MinimumLevel = loggingSettings.SearchingMinimumLogLevel;
|
||||||
|
|
||||||
await _configElementRepository.Upsert(
|
await _configElementRepository.Upsert(
|
||||||
ConfigElementKey.MinimumLogLevelStreaming,
|
ConfigElementKey.MinimumLogLevelStreaming,
|
||||||
loggingSettings.StreamingMinimumLogLevel);
|
loggingSettings.StreamingMinimumLogLevel);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ public class LoggingSettingsViewModel
|
|||||||
public LogEventLevel DefaultMinimumLogLevel { get; set; }
|
public LogEventLevel DefaultMinimumLogLevel { get; set; }
|
||||||
public LogEventLevel ScanningMinimumLogLevel { get; set; }
|
public LogEventLevel ScanningMinimumLogLevel { get; set; }
|
||||||
public LogEventLevel SchedulingMinimumLogLevel { get; set; }
|
public LogEventLevel SchedulingMinimumLogLevel { get; set; }
|
||||||
|
public LogEventLevel SearchingMinimumLogLevel { get; set; }
|
||||||
public LogEventLevel StreamingMinimumLogLevel { get; set; }
|
public LogEventLevel StreamingMinimumLogLevel { get; set; }
|
||||||
public LogEventLevel HttpMinimumLogLevel { get; set; }
|
public LogEventLevel HttpMinimumLogLevel { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ public class GetLoggingSettingsHandler : IRequestHandler<GetLoggingSettings, Log
|
|||||||
Option<LogEventLevel> maybeSchedulingLevel =
|
Option<LogEventLevel> maybeSchedulingLevel =
|
||||||
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScheduling);
|
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelScheduling);
|
||||||
|
|
||||||
|
Option<LogEventLevel> maybeSearchingLevel =
|
||||||
|
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelSearching);
|
||||||
|
|
||||||
Option<LogEventLevel> maybeStreamingLevel =
|
Option<LogEventLevel> maybeStreamingLevel =
|
||||||
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelStreaming);
|
await _configElementRepository.GetValue<LogEventLevel>(ConfigElementKey.MinimumLogLevelStreaming);
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ public class GetLoggingSettingsHandler : IRequestHandler<GetLoggingSettings, Log
|
|||||||
DefaultMinimumLogLevel = await maybeDefaultLevel.IfNoneAsync(LogEventLevel.Information),
|
DefaultMinimumLogLevel = await maybeDefaultLevel.IfNoneAsync(LogEventLevel.Information),
|
||||||
ScanningMinimumLogLevel = await maybeScanningLevel.IfNoneAsync(LogEventLevel.Information),
|
ScanningMinimumLogLevel = await maybeScanningLevel.IfNoneAsync(LogEventLevel.Information),
|
||||||
SchedulingMinimumLogLevel = await maybeSchedulingLevel.IfNoneAsync(LogEventLevel.Information),
|
SchedulingMinimumLogLevel = await maybeSchedulingLevel.IfNoneAsync(LogEventLevel.Information),
|
||||||
|
SearchingMinimumLogLevel = await maybeSearchingLevel.IfNoneAsync(LogEventLevel.Information),
|
||||||
StreamingMinimumLogLevel = await maybeStreamingLevel.IfNoneAsync(LogEventLevel.Information),
|
StreamingMinimumLogLevel = await maybeStreamingLevel.IfNoneAsync(LogEventLevel.Information),
|
||||||
HttpMinimumLogLevel = await maybeHttpLevel.IfNoneAsync(LogEventLevel.Information)
|
HttpMinimumLogLevel = await maybeHttpLevel.IfNoneAsync(LogEventLevel.Information)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public class ConfigElementKey
|
|||||||
public static ConfigElementKey MinimumLogLevel => new("log.minimum_level");
|
public static ConfigElementKey MinimumLogLevel => new("log.minimum_level");
|
||||||
public static ConfigElementKey MinimumLogLevelScanning => new("log.minimum_level.scanning");
|
public static ConfigElementKey MinimumLogLevelScanning => new("log.minimum_level.scanning");
|
||||||
public static ConfigElementKey MinimumLogLevelScheduling => new("log.minimum_level.scheduling");
|
public static ConfigElementKey MinimumLogLevelScheduling => new("log.minimum_level.scheduling");
|
||||||
|
public static ConfigElementKey MinimumLogLevelSearching => new("log.minimum_level.searching");
|
||||||
public static ConfigElementKey MinimumLogLevelStreaming => new("log.minimum_level.streaming");
|
public static ConfigElementKey MinimumLogLevelStreaming => new("log.minimum_level.streaming");
|
||||||
public static ConfigElementKey MinimumLogLevelHttp => new("log.minimum_level.http");
|
public static ConfigElementKey MinimumLogLevelHttp => new("log.minimum_level.http");
|
||||||
public static ConfigElementKey FFmpegPath => new("ffmpeg.ffmpeg_path");
|
public static ConfigElementKey FFmpegPath => new("ffmpeg.ffmpeg_path");
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ public class LoggingLevelSwitches
|
|||||||
|
|
||||||
public LoggingLevelSwitch SchedulingLevelSwitch { get; } = new();
|
public LoggingLevelSwitch SchedulingLevelSwitch { get; } = new();
|
||||||
|
|
||||||
|
public LoggingLevelSwitch SearchingLevelSwitch { get; } = new();
|
||||||
|
|
||||||
public LoggingLevelSwitch StreamingLevelSwitch { get; } = new();
|
public LoggingLevelSwitch StreamingLevelSwitch { get; } = new();
|
||||||
|
|
||||||
public LoggingLevelSwitch HttpLevelSwitch { get; } = new();
|
public LoggingLevelSwitch HttpLevelSwitch { get; } = new();
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ using Lucene.Net.Analysis.Miscellaneous;
|
|||||||
using Lucene.Net.Analysis.Standard;
|
using Lucene.Net.Analysis.Standard;
|
||||||
using Lucene.Net.QueryParsers.Classic;
|
using Lucene.Net.QueryParsers.Classic;
|
||||||
using Lucene.Net.Search;
|
using Lucene.Net.Search;
|
||||||
using Serilog;
|
using Microsoft.Extensions.Logging;
|
||||||
using Query = Lucene.Net.Search.Query;
|
using Query = Lucene.Net.Search.Query;
|
||||||
|
|
||||||
namespace ErsatzTV.Infrastructure.Search;
|
namespace ErsatzTV.Infrastructure.Search;
|
||||||
|
|
||||||
public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCache)
|
public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCache, ILogger<SearchQueryParser> logger)
|
||||||
{
|
{
|
||||||
static SearchQueryParser() => BooleanQuery.MaxClauseCount = 1024 * 4;
|
static SearchQueryParser() => BooleanQuery.MaxClauseCount = 1024 * 4;
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(smartCollectionName) && await smartCollectionCache.HasCycle(smartCollectionName))
|
if (!string.IsNullOrWhiteSpace(smartCollectionName) && await smartCollectionCache.HasCycle(smartCollectionName))
|
||||||
{
|
{
|
||||||
Log.Logger.Error("Smart collection {Name} contains a cycle; will not evaluate", smartCollectionName);
|
logger.LogError("Smart collection {Name} contains a cycle; will not evaluate", smartCollectionName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
{
|
{
|
||||||
if (replaceCount > 100)
|
if (replaceCount > 100)
|
||||||
{
|
{
|
||||||
Log.Logger.Warning("smart_collection query is nested too deep; giving up");
|
logger.LogWarning("smart_collection query is nested too deep; giving up");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
|
|
||||||
if (parsedQuery == replaceResult.Query)
|
if (parsedQuery == replaceResult.Query)
|
||||||
{
|
{
|
||||||
Log.Logger.Warning(
|
logger.LogWarning(
|
||||||
"Failed to replace smart_collection in query; is the syntax correct? Quotes are required. Giving up...");
|
"Failed to replace smart_collection in query; is the syntax correct? Quotes are required. Giving up...");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
};
|
};
|
||||||
Query result = ParseQuery(parsedQuery, parser);
|
Query result = ParseQuery(parsedQuery, parser);
|
||||||
|
|
||||||
Log.Logger.Debug("Search query parsed from [{Query}] to [{ParsedQuery}]", query, result.ToString());
|
logger.LogDebug("Search query parsed from [{Query}] to [{ParsedQuery}]", query, result.ToString());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
string smartCollectionName = match.Groups[1].Value;
|
string smartCollectionName = match.Groups[1].Value;
|
||||||
if (await smartCollectionCache.HasCycle(smartCollectionName))
|
if (await smartCollectionCache.HasCycle(smartCollectionName))
|
||||||
{
|
{
|
||||||
Log.Logger.Error(
|
logger.LogError(
|
||||||
"Smart collection {Name} contains a cycle; will not evaluate",
|
"Smart collection {Name} contains a cycle; will not evaluate",
|
||||||
smartCollectionName);
|
smartCollectionName);
|
||||||
return new ReplaceResult(query, true);
|
return new ReplaceResult(query, true);
|
||||||
@@ -130,7 +130,7 @@ public partial class SearchQueryParser(ISmartCollectionCache smartCollectionCach
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log.Logger.Warning(ex, "Unexpected exception replacing smart collections in search query");
|
logger.LogWarning(ex, "Unexpected exception replacing smart collections in search query");
|
||||||
return new ReplaceResult(query, true);
|
return new ReplaceResult(query, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,17 @@
|
|||||||
<MudSelectItem Value="@LogEventLevel.Error">Error</MudSelectItem>
|
<MudSelectItem Value="@LogEventLevel.Error">Error</MudSelectItem>
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||||
|
<div class="d-flex">
|
||||||
|
<MudText>Searching Minimum Log Level</MudText>
|
||||||
|
</div>
|
||||||
|
<MudSelect @bind-Value="_loggingSettings.SearchingMinimumLogLevel">
|
||||||
|
<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>
|
||||||
|
</MudStack>
|
||||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<MudText>Streaming Minimum Log Level</MudText>
|
<MudText>Streaming Minimum Log Level</MudText>
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ public class Program
|
|||||||
"ErsatzTV.Application.Subtitles.ExtractEmbeddedSubtitlesHandler",
|
"ErsatzTV.Application.Subtitles.ExtractEmbeddedSubtitlesHandler",
|
||||||
LoggingLevelSwitches.SchedulingLevelSwitch)
|
LoggingLevelSwitches.SchedulingLevelSwitch)
|
||||||
|
|
||||||
|
// searching
|
||||||
|
.MinimumLevel.Override("ErsatzTV.Infrastructure.Search.SearchQueryParser", LoggingLevelSwitches.SearchingLevelSwitch)
|
||||||
|
|
||||||
// streaming
|
// streaming
|
||||||
.MinimumLevel.Override("ErsatzTV.Application.Streaming", LoggingLevelSwitches.StreamingLevelSwitch)
|
.MinimumLevel.Override("ErsatzTV.Application.Streaming", LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
.MinimumLevel.Override("ErsatzTV.FFmpeg", LoggingLevelSwitches.StreamingLevelSwitch)
|
.MinimumLevel.Override("ErsatzTV.FFmpeg", LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
@@ -85,6 +88,7 @@ public class Program
|
|||||||
LoggingLevelSwitches.StreamingLevelSwitch)
|
LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
.MinimumLevel.Override("ErsatzTV.Controllers.IptvController", LoggingLevelSwitches.StreamingLevelSwitch)
|
.MinimumLevel.Override("ErsatzTV.Controllers.IptvController", LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
.MinimumLevel.Override("ErsatzTV.Controllers.InternalController", LoggingLevelSwitches.StreamingLevelSwitch)
|
.MinimumLevel.Override("ErsatzTV.Controllers.InternalController", LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
|
.MinimumLevel.Override("ErsatzTV.Controllers.TroubleshootController", LoggingLevelSwitches.StreamingLevelSwitch)
|
||||||
|
|
||||||
// http
|
// http
|
||||||
.MinimumLevel.Override("Serilog.AspNetCore.RequestLoggingMiddleware", LoggingLevelSwitches.HttpLevelSwitch)
|
.MinimumLevel.Override("Serilog.AspNetCore.RequestLoggingMiddleware", LoggingLevelSwitches.HttpLevelSwitch)
|
||||||
|
|||||||
Reference in New Issue
Block a user