public ExpressionFilter(string filterExpression) { Func <LogEvent, bool> filter; // Our custom Serilog Functions to extend Serilog.Expressions // In this case we are plugging the gap for the missing Has() // function from porting away from Serilog.Filters.Expressions to Serilog.Expressions // Along with patching support for the more verbose built in property names var customSerilogFunctions = new SerilogLegacyNameResolver(typeof(SerilogExpressionsFunctions)); if (string.IsNullOrEmpty(filterExpression)) { return; } // If the expression is one word and doesn't contain a serilog operator then we can perform a like search if (!filterExpression.Contains(" ") && !filterExpression.ContainsAny(s_expressionOperators.Select(c => c))) { filter = PerformMessageLikeFilter(filterExpression); } else // check if it's a valid expression { // If the expression evaluates then make it into a filter if (SerilogExpression.TryCompile(filterExpression, null, customSerilogFunctions, out CompiledExpression compiled, out var error)) { filter = evt => { LogEventPropertyValue result = compiled(evt); return(ExpressionResult.IsTrue(result)); }; }
private Func <LogEvent, bool>?PerformMessageLikeFilter(string filterExpression) { var filterSearch = $"@Message like '%{SerilogExpression.EscapeLikeExpressionContent(filterExpression)}%'"; if (SerilogExpression.TryCompile(filterSearch, out CompiledExpression? compiled, out var error)) { // `compiled` is a function that can be executed against `LogEvent`s: return(evt => { LogEventPropertyValue?result = compiled(evt); return ExpressionResult.IsTrue(result); }); } return(null); }
public LogResults Search(int pageNumber = 1, int pageSize = 100, string?filterExpression = null, SortOrder sort = SortOrder.Descending) { //If filter null - return a simple page of results if (filterExpression == null) { var totalRecords = _logItems.Count; var logMessages = _logItems .OrderBy(x => x.Timestamp, sort) .Skip(pageSize * (pageNumber - 1)) .Take(pageSize) .Select(x => new LogMessage { Timestamp = x.Timestamp, Level = x.Level, MessageTemplateText = x.MessageTemplate.Text, Exception = x.Exception?.ToString(), Properties = x.Properties, RenderedMessage = x.RenderMessage() }); return(new LogResults() { Logs = new PagedResult <LogMessage>(totalRecords, pageNumber, pageSize) { Items = logMessages }, MessageTemplates = GetMessageTemplates(_logItems) }); } Func <LogEvent, bool>?filter; // Our custom Serilog Functions in this case plugging the gap for missing Has() function var customSerilogFunctions = new LegacyNameResolver(typeof(SerilogExtensions)); // With an empty expression - ensure all logs are sent back if (filterExpression == string.Empty) { filter = evt => { // Return true/matches return(true); }; } // If the expression is one word and doesn't contain a serilog operator then we can perform a like search else if (!filterExpression.Contains(" ") && !filterExpression.ContainsAny(ExpressionOperators)) { filter = PerformMessageLikeFilter(filterExpression); } else { // Check if it's a valid expression // If the expression evaluates then make it into a filter if (SerilogExpression.TryCompile(filterExpression, null, customSerilogFunctions, out var compiled, out var error)) { // `compiled` is a function that can be executed against `LogEvent`s: filter = evt => { var result = compiled(evt); return(ExpressionResult.IsTrue(result)); }; }