Example #1
0
        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));
                    };
                }
        public void UserDefinedFunctionsAreCallableInExpressions()
        {
            var expr = SerilogExpression.Compile(
                "magic(10) + 3 = 55",
                new StaticMemberNameResolver(typeof(NameResolverTests)));

            Assert.True(Coerce.IsTrue(expr(Some.InformationEvent())));
        }
Example #3
0
        public override string ToString()
        {
            if (_requiresEscape)
            {
                return($"@Properties['{SerilogExpression.EscapeStringContent(PropertyName)}']");
            }

            return((IsBuiltIn ? "@" : "") + PropertyName);
        }
Example #4
0
        public override string ToString()
        {
            if (SerilogExpression.IsValidIdentifier(MemberName))
            {
                return(Receiver + "." + MemberName);
            }

            return($"{Receiver}['{SerilogExpression.EscapeStringContent(MemberName)}']");
        }
        /// <summary>
        /// Exclude log events that match the provided expression.
        /// </summary>
        /// <param name="loggerFilterConfiguration">Filter configuration.</param>
        /// <param name="expression">The expression to apply.</param>
        /// <returns>The underlying <see cref="LoggerConfiguration"/>.</returns>
        public static LoggerConfiguration ByExcluding(this LoggerFilterConfiguration loggerFilterConfiguration, string expression)
        {
            if (loggerFilterConfiguration == null)
            {
                throw new ArgumentNullException(nameof(loggerFilterConfiguration));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var compiled = SerilogExpression.Compile(expression);

            return(loggerFilterConfiguration.ByExcluding(e => Coerce.IsTrue(compiled(e))));
        }
Example #6
0
    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);
    }
Example #7
0
        /// <summary>
        /// Enrich events with a property <paramref name="propertyName"/> computed by evaluating
        /// <paramref name="expression"/> in the context of the event.
        /// </summary>
        /// <param name="loggerEnrichmentConfiguration">Enrichment configuration.</param>
        /// <param name="propertyName">The name of the property to attach; if the property already
        /// exists, and <paramref name="expression"/> evaluates to a defined value, it will be overwritten.</param>
        /// <param name="expression">An expression to evaluate in the context of each event. If the result of
        /// evaluating the expression is defined, it will be attached to the event as <paramref name="propertyName"/>.</param>
        /// <returns>The underlying <see cref="LoggerConfiguration"/>.</returns>
        public static LoggerConfiguration WithComputed(
            this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration,
            string propertyName,
            string expression)
        {
            if (propertyName == null)
            {
                throw new ArgumentNullException(nameof(propertyName));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            var compiled = SerilogExpression.Compile(expression);

            return(loggerEnrichmentConfiguration.With(new ComputedPropertyEnricher(propertyName, compiled)));
        }
Example #8
0
        /// <summary>
        /// Write to a sink only when <paramref name="expression" /> evaluates to <c>true</c>.
        /// </summary>
        /// <param name="loggerSinkConfiguration">Sink configuration.</param>
        /// <param name="expression">An expression that evaluates to <c>true</c> when the
        /// supplied <see cref="T:Serilog.Events.LogEvent" />
        /// should be written to the configured sink.</param>
        /// <param name="configureSink">An action that configures the wrapped sink.</param>
        /// <returns>Configuration object allowing method chaining.</returns>
        /// <returns>The underlying <see cref="LoggerConfiguration"/>.</returns>
        public static LoggerConfiguration Conditional(
            this LoggerSinkConfiguration loggerSinkConfiguration,
            string expression,
            Action <LoggerSinkConfiguration> configureSink)
        {
            if (loggerSinkConfiguration == null)
            {
                throw new ArgumentNullException(nameof(loggerSinkConfiguration));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            if (configureSink == null)
            {
                throw new ArgumentNullException(nameof(configureSink));
            }

            var compiled = SerilogExpression.Compile(expression);

            return(loggerSinkConfiguration.Conditional(e => Coerce.IsTrue(compiled(e)), configureSink));
        }
Example #9
0
        /// <summary>
        /// Write to a sink only when <paramref name="expression" /> evaluates to <c>true</c>.
        /// </summary>
        /// <param name="loggerEnrichmentConfiguration">Enrichment configuration.</param>
        /// <param name="expression">An expression that evaluates to <c>true</c> when the supplied
        /// <see cref="T:Serilog.Events.LogEvent" /> should be enriched.</param>
        /// <param name="configureEnricher">An action that configures the wrapped enricher.</param>
        /// <returns>The underlying <see cref="LoggerConfiguration"/>.</returns>
        public static LoggerConfiguration When(
            this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration,
            string expression,
            Action <LoggerEnrichmentConfiguration> configureEnricher)
        {
            if (loggerEnrichmentConfiguration == null)
            {
                throw new ArgumentNullException(nameof(loggerEnrichmentConfiguration));
            }
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            if (configureEnricher == null)
            {
                throw new ArgumentNullException(nameof(configureEnricher));
            }

            var compiled = SerilogExpression.Compile(expression);

            return(loggerEnrichmentConfiguration.When(e => Coerce.IsTrue(compiled(e)), configureEnricher));
        }
        public ComparisonBenchmark()
        {
            // Just the delegate invocation overhead
            _trivialFilter = evt => true;

            // `A == 3`, the old way
            _handwrittenFilter = evt =>
            {
                if (evt.Properties.TryGetValue("A", out var a) && (a as ScalarValue)?.Value is int)
                {
                    return((int)((ScalarValue)a).Value == 3);
                }

                return(false);
            };

            // The code we're interested in; the `true.Equals()` overhead is normally added when
            // this is used with Serilog
            var compiled = SerilogExpression.Compile("A = 3");

            _expressionFilter = evt => ExpressionResult.IsTrue(compiled(evt));

            Assert.True(_trivialFilter(_event) && _handwrittenFilter(_event) && _expressionFilter(_event));
        }
Example #11
0
        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));
                    };
                }
Example #12
0
 public AmbientPropertyExpression(string propertyName, bool isBuiltIn)
 {
     PropertyName    = propertyName ?? throw new ArgumentNullException(nameof(propertyName));
     IsBuiltIn       = isBuiltIn;
     _requiresEscape = !SerilogExpression.IsValidIdentifier(propertyName);
 }