public PagedResult <LogMessage> 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 PagedResult <LogMessage>(totalRecords, pageNumber, pageSize)
                {
                    Items = logMessages
                });
            }


            Func <LogEvent, bool> filter;

            // 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(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 (FilterLanguage.TryCreateFilter(filterExpression, out var eval, out _))
                {
                    filter = evt => true.Equals(eval(evt));
                }
        public ExpressionFilter(string filterExpression)
        {
            Func <LogEvent, bool> filter;

            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(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 (FilterLanguage.TryCreateFilter(filterExpression, out var eval, out _))
                {
                    filter = evt => true.Equals(eval(evt));
                }