示例#1
0
        protected bool ShouldApplySystemFilter(IExceptionlessSystemFilterQuery sf, string filter)
        {
            // Apply filter to non admin user.
            if (!Request.IsGlobalAdmin())
            {
                return(true);
            }

            // Apply filter as it's scoped via a controller action.
            if (!sf.IsUserOrganizationsFilter)
            {
                return(true);
            }

            // Empty user filter
            if (String.IsNullOrEmpty(filter))
            {
                return(true);
            }

            // Used for impersonating a user. Only skip the filter if it contains an org, project or stack.
            bool hasOrganizationOrProjectOrStackFilter = filter.Contains("organization:") || filter.Contains("project:") || filter.Contains("stack:");

            return(!hasOrganizationOrProjectOrStackFilter);
        }
示例#2
0
        public Task <FindResults <PersistentEvent> > GetByFilterAsync(IExceptionlessSystemFilterQuery systemFilter, string userFilter, string sort, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging)
        {
            var search = new ExceptionlessQuery()
                         .WithDateRange(utcStart, utcEnd, field ?? ElasticType.GetFieldName(e => e.Date))
                         .WithIndexes(utcStart, utcEnd)
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithPaging(paging);

            search = !String.IsNullOrEmpty(sort) ? search.WithSort(sort) : search.WithSortDescending((PersistentEvent e) => e.Date);
            return(FindAsync(search));
        }
        public Task <FindResults <Stack> > GetByFilterAsync(IExceptionlessSystemFilterQuery systemFilter, string userFilter, string sort, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging)
        {
            var search = new ExceptionlessQuery()
                         .WithDateRange(utcStart, utcEnd, field ?? ElasticType.GetFieldName(s => s.LastOccurrence))
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithPaging(paging)
                         .WithSort(sort);

            search = !String.IsNullOrEmpty(sort) ? search.WithSort(sort) : search.WithSortDescending((Stack s) => s.LastOccurrence);
            return(FindAsync(search));
        }
示例#4
0
        public Task <FindResults <Stack> > GetByFilterAsync(IExceptionlessSystemFilterQuery systemFilter, string userFilter, SortingOptions sorting, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging)
        {
            if (sorting.Fields.Count == 0)
            {
                sorting.Fields.Add(new FieldSort {
                    Field = StackIndexType.Fields.LastOccurrence, Order = SortOrder.Descending
                });
            }

            var search = new ExceptionlessQuery()
                         .WithDateRange(utcStart, utcEnd, field ?? StackIndexType.Fields.LastOccurrence)
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithPaging(paging)
                         .WithSort(sorting);

            return(FindAsync(search));
        }
        protected virtual async Task <IHttpActionResult> GetCountAsync(IExceptionlessSystemFilterQuery sf, TimeInfo ti, string filter = null, string aggregations = null)
        {
            var pr = await _validator.ValidateQueryAsync(filter);

            if (!pr.IsValid)
            {
                return(BadRequest(pr.Message));
            }

            var far = await _validator.ValidateAggregationsAsync(aggregations);

            if (!far.IsValid)
            {
                return(BadRequest(far.Message));
            }

            sf.UsesPremiumFeatures = pr.UsesPremiumFeatures || far.UsesPremiumFeatures;
            IRepositoryQuery query = new ExceptionlessQuery()
                                     .WithSystemFilter(ShouldApplySystemFilter(sf, filter) ? sf : null)
                                     .WithDateRange(ti.Range.UtcStart, ti.Range.UtcEnd, ti.Field)
                                     .WithIndexes(ti.Range.UtcStart, ti.Range.UtcEnd);

            CountResult result;

            try {
                result = await _repository.CountBySearchAsync(query, filter, aggregations);
            } catch (Exception ex) {
                _logger.Error().Exception(ex)
                .Message("An error has occurred. Please check your filter or aggregations.")
                .Property("Search Filter", new { SystemFilter = sf, UserFilter = filter, Time = ti, Aggregations = aggregations })
                .Tag("Search")
                .Identity(CurrentUser.EmailAddress)
                .Property("User", CurrentUser)
                .SetActionContext(ActionContext)
                .Write();

                return(BadRequest("An error has occurred. Please check your search filter."));
            }

            return(Ok(result));
        }
示例#6
0
        private async Task <string> GetNextEventIdAsync(PersistentEvent ev, IExceptionlessSystemFilterQuery systemFilter = null, string userFilter = null, DateTime?utcStart = null, DateTime?utcEnd = null)
        {
            if (ev == null)
            {
                return(null);
            }

            if (!utcStart.HasValue || utcStart.Value.IsBefore(ev.Date.UtcDateTime))
            {
                utcStart = ev.Date.UtcDateTime;
            }

            if (!utcEnd.HasValue || utcEnd.Value.IsAfter(SystemClock.UtcNow))
            {
                utcEnd = SystemClock.UtcNow;
            }

            var utcEventDate = ev.Date.UtcDateTime;

            // utcEnd is before the current event date.
            if (utcStart > utcEventDate || utcEnd < utcEventDate)
            {
                return(null);
            }

            if (String.IsNullOrEmpty(userFilter))
            {
                userFilter = String.Concat(EventIndexType.Alias.StackId, ":", ev.StackId);
            }

            var results = await FindAsync(new ExceptionlessQuery()
                                          .WithDateRange(utcEventDate, utcEnd, (PersistentEvent e) => e.Date)
                                          .WithIndexes(utcStart, utcEventDate)
                                          .WithSortAscending((PersistentEvent e) => e.Date)
                                          .WithLimit(10)
                                          .IncludeFields((PersistentEvent e) => e.Id, e => e.Date)
                                          .WithSystemFilter(systemFilter)
                                          .WithElasticFilter(!Query <PersistentEvent> .Ids(ids => ids.Values(ev.Id)))
                                          .WithFilter(userFilter)).AnyContext();

            if (results.Total == 0)
            {
                return(null);
            }

            // make sure we don't have records with the exact same occurrence date
            if (results.Documents.All(t => t.Date != ev.Date))
            {
                return(results.Documents.OrderBy(t => t.Date).ThenBy(t => t.Id).First().Id);
            }

            // we have records with the exact same occurrence date, we need to figure out the order of those
            // put our target error into the mix, sort it and return the result after the target
            var unionResults = results.Documents.Union(new[] { ev })
                               .OrderBy(t => t.Date.Ticks).ThenBy(t => t.Id)
                               .ToList();

            var index = unionResults.FindIndex(t => t.Id == ev.Id);

            return(index == unionResults.Count - 1 ? null : unionResults[index + 1].Id);
        }
示例#7
0
        public async Task <PreviousAndNextEventIdResult> GetPreviousAndNextEventIdsAsync(PersistentEvent ev, IExceptionlessSystemFilterQuery systemFilter, string userFilter, DateTime?utcStart, DateTime?utcEnd)
        {
            var previous = await GetPreviousEventIdAsync(ev, systemFilter, userFilter, utcStart, utcEnd).AnyContext();

            var next = await GetNextEventIdAsync(ev, systemFilter, userFilter, utcStart, utcEnd).AnyContext();

            return(new PreviousAndNextEventIdResult {
                Previous = previous,
                Next = next
            });
        }
示例#8
0
        public async Task <NumbersTermStatsResult> GetNumbersTermsStatsAsync(string term, IEnumerable <FieldAggregation> fields, DateTime utcStart, DateTime utcEnd, IExceptionlessSystemFilterQuery systemFilter, string userFilter = null, TimeSpan?displayTimeOffset = null, int max = 25)
        {
            var allowedTerms = new[] { "organization_id", "project_id", "stack_id", "tags", "version" };

            if (!allowedTerms.Contains(term))
            {
                throw new ArgumentException("Must be a valid term.", nameof(term));
            }

            if (!displayTimeOffset.HasValue)
            {
                displayTimeOffset = TimeSpan.Zero;
            }

            var filter = new ElasticQuery()
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithDateRange(utcStart, utcEnd, EventIndexType.Fields.Date)
                         .WithIndexes(utcStart, utcEnd);

            // if no start date then figure out first event date
            if (!filter.DateRanges.First().UseStartDate)
            {
                await UpdateFilterStartDateRangesAsync(filter, utcEnd).AnyContext();
            }

            utcStart = filter.DateRanges.First().GetStartDate();
            utcEnd   = filter.DateRanges.First().GetEndDate();

            var descriptor = new SearchDescriptor <PersistentEvent>()
                             .SearchType(SearchType.Count)
                             .IgnoreUnavailable()
                             .Indices(_configuration.Events.Event.GetIndexesByQuery(filter))
                             .Type(_configuration.Events.Event.Name)
                             .Aggregations(agg => BuildAggregations(agg
                                                                    .Terms("terms", t => BuildTermSort(t
                                                                                                       .Field(term)
                                                                                                       .Size(max)
                                                                                                       .Aggregations(agg2 => BuildAggregations(agg2
                                                                                                                                               .Min("first_occurrence", o => o.Field(ev => ev.Date))
                                                                                                                                               .Max("last_occurrence", o => o.Field(ev => ev.Date)), fields)
                                                                                                                     ), fields)
                                                                           ), fields)
                                           );

            _configuration.Events.Event.QueryBuilder.ConfigureSearch(filter, GetQueryOptions(), descriptor);
            var response = await _configuration.Client.SearchAsync <PersistentEvent>(descriptor).AnyContext();

            _logger.Trace(() => response.GetRequest());

            if (!response.IsValid)
            {
                string message = $"Retrieving stats failed: {response.GetErrorMessage()}";
                _logger.Error().Exception(response.ConnectionStatus.OriginalException).Message(message).Property("request", response.GetRequest()).Write();
                throw new ApplicationException(message, response.ConnectionStatus.OriginalException);
            }

            var stats = new NumbersTermStatsResult {
                Total   = response.Total,
                Start   = utcStart.SafeAdd(displayTimeOffset.Value),
                End     = utcEnd.SafeAdd(displayTimeOffset.Value),
                Numbers = GetNumbers(response.Aggs, fields)
            };

            var terms = response.Aggs.Terms("terms");

            if (terms != null)
            {
                stats.Terms.AddRange(terms.Items.Select(i => {
                    var item = new NumbersTermStatsItem {
                        Total   = i.DocCount,
                        Term    = i.Key,
                        Numbers = GetNumbers(i, fields)
                    };

                    var termFirstOccurrence = i.Min("first_occurrence");
                    if (termFirstOccurrence?.Value != null)
                    {
                        item.FirstOccurrence = termFirstOccurrence.Value.Value.ToDateTime().SafeAdd(displayTimeOffset.Value);
                    }

                    var termLastOccurrence = i.Max("last_occurrence");
                    if (termLastOccurrence?.Value != null)
                    {
                        item.LastOccurrence = termLastOccurrence.Value.Value.ToDateTime().SafeAdd(displayTimeOffset.Value);
                    }

                    return(item);
                }));
            }

            return(stats);
        }
示例#9
0
        public async Task <NumbersStatsResult> GetNumbersStatsAsync(IEnumerable <FieldAggregation> fields, DateTime utcStart, DateTime utcEnd, IExceptionlessSystemFilterQuery systemFilter, string userFilter = null, TimeSpan?displayTimeOffset = null)
        {
            if (!displayTimeOffset.HasValue)
            {
                displayTimeOffset = TimeSpan.Zero;
            }

            var filter = new ElasticQuery()
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithDateRange(utcStart, utcEnd, EventIndexType.Fields.Date)
                         .WithIndexes(utcStart, utcEnd);

            // if no start date then figure out first event date
            if (!filter.DateRanges.First().UseStartDate)
            {
                await UpdateFilterStartDateRangesAsync(filter, utcEnd).AnyContext();
            }

            utcStart = filter.DateRanges.First().GetStartDate();
            utcEnd   = filter.DateRanges.First().GetEndDate();

            var descriptor = new SearchDescriptor <PersistentEvent>()
                             .SearchType(SearchType.Count)
                             .IgnoreUnavailable()
                             .Indices(_configuration.Events.Event.GetIndexesByQuery(filter))
                             .Type(_configuration.Events.Event.Name)
                             .Aggregations(agg => BuildAggregations(agg, fields));

            _configuration.Events.Event.QueryBuilder.ConfigureSearch(filter, GetQueryOptions(), descriptor);
            var response = await _configuration.Client.SearchAsync <PersistentEvent>(descriptor).AnyContext();

            _logger.Trace(() => response.GetRequest());

            if (!response.IsValid)
            {
                string message = $"Retrieving stats failed: {response.GetErrorMessage()}";
                _logger.Error().Exception(response.ConnectionStatus.OriginalException).Message(message).Property("request", response.GetRequest()).Write();
                throw new ApplicationException(message, response.ConnectionStatus.OriginalException);
            }

            return(new NumbersStatsResult {
                Total = response.Total,
                Start = utcStart.SafeAdd(displayTimeOffset.Value),
                End = utcEnd.SafeAdd(displayTimeOffset.Value),
                Numbers = GetNumbers(response.Aggs, fields)
            });
        }
示例#10
0
        public async Task <NumbersTimelineStatsResult> GetNumbersTimelineStatsAsync(IEnumerable <FieldAggregation> fields, DateTime utcStart, DateTime utcEnd, IExceptionlessSystemFilterQuery systemFilter, string userFilter = null, TimeSpan?displayTimeOffset = null, int desiredDataPoints = 100)
        {
            if (!displayTimeOffset.HasValue)
            {
                displayTimeOffset = TimeSpan.Zero;
            }

            var filter = new ElasticQuery()
                         .WithSystemFilter(systemFilter)
                         .WithFilter(userFilter)
                         .WithDateRange(utcStart, utcEnd, EventIndexType.Fields.Date)
                         .WithIndexes(utcStart, utcEnd);

            // if no start date then figure out first event date
            if (!filter.DateRanges.First().UseStartDate)
            {
                await UpdateFilterStartDateRangesAsync(filter, utcEnd).AnyContext();
            }

            utcStart = filter.DateRanges.First().GetStartDate();
            utcEnd   = filter.DateRanges.First().GetEndDate();
            var interval = GetInterval(utcStart, utcEnd, desiredDataPoints);

            var descriptor = new SearchDescriptor <PersistentEvent>()
                             .SearchType(SearchType.Count)
                             .IgnoreUnavailable()
                             .Indices(_configuration.Events.Event.GetIndexesByQuery(filter))
                             .Type(_configuration.Events.Event.Name)
                             .Aggregations(agg => BuildAggregations(agg
                                                                    .DateHistogram("timelime", t => t
                                                                                   .Field(ev => ev.Date)
                                                                                   .MinimumDocumentCount(0)
                                                                                   .Interval(interval.Item1)
                                                                                   .TimeZone(HoursAndMinutes(displayTimeOffset.Value))
                                                                                   .Aggregations(agg2 => BuildAggregations(agg2, fields))
                                                                                   )
                                                                    .Min("first_occurrence", t => t.Field(ev => ev.Date))
                                                                    .Max("last_occurrence", t => t.Field(ev => ev.Date)), fields)
                                           );

            _configuration.Events.Event.QueryBuilder.ConfigureSearch(filter, GetQueryOptions(), descriptor);
            var response = await _configuration.Client.SearchAsync <PersistentEvent>(descriptor).AnyContext();

            _logger.Trace(() => response.GetRequest());

            if (!response.IsValid)
            {
                string message = $"Retrieving stats failed: {response.GetErrorMessage()}";
                _logger.Error().Exception(response.ConnectionStatus.OriginalException).Message(message).Property("request", response.GetRequest()).Write();
                throw new ApplicationException(message, response.ConnectionStatus.OriginalException);
            }

            var stats = new NumbersTimelineStatsResult {
                Total = response.Total, Numbers = GetNumbers(response.Aggs, fields)
            };
            var timeline = response.Aggs.DateHistogram("timelime");

            if (timeline != null)
            {
                stats.Timeline.AddRange(timeline.Items.Select(i => new NumbersTimelineItem {
                    Date    = i.Date,
                    Total   = i.DocCount,
                    Numbers = GetNumbers(i, fields)
                }));
            }

            stats.Start = stats.Timeline.Count > 0 ? stats.Timeline.Min(tl => tl.Date).SafeAdd(displayTimeOffset.Value) : utcStart.SafeAdd(displayTimeOffset.Value);
            stats.End   = utcEnd.SafeAdd(displayTimeOffset.Value);

            var totalHours = stats.End.Subtract(stats.Start).TotalHours;

            if (totalHours > 0.0)
            {
                stats.AvgPerHour = stats.Total / totalHours;
            }

            if (stats.Timeline.Count <= 0)
            {
                return(stats);
            }

            var firstOccurrence = response.Aggs.Min("first_occurrence");

            if (firstOccurrence?.Value != null)
            {
                stats.FirstOccurrence = firstOccurrence.Value.Value.ToDateTime().SafeAdd(displayTimeOffset.Value);
            }

            var lastOccurrence = response.Aggs.Max("last_occurrence");

            if (lastOccurrence?.Value != null)
            {
                stats.LastOccurrence = lastOccurrence.Value.Value.ToDateTime().SafeAdd(displayTimeOffset.Value);
            }

            return(stats);
        }
示例#11
0
        public static async Task <PreviousAndNextEventIdResult> GetPreviousAndNextEventIdsAsync(this IEventRepository repository, string id, IExceptionlessSystemFilterQuery systemFilter = null, string userFilter = null, DateTime?utcStart = null, DateTime?utcEnd = null)
        {
            var ev = await repository.GetByIdAsync(id, true).AnyContext();

            return(await repository.GetPreviousAndNextEventIdsAsync(ev, systemFilter, userFilter, utcStart, utcEnd).AnyContext());
        }
示例#12
0
        private async Task <string> GetNextEventIdAsync(PersistentEvent ev, IExceptionlessSystemFilterQuery systemFilter = null, string userFilter = null, DateTime?utcStart = null, DateTime?utcEnd = null)
        {
            if (ev == null)
            {
                return(null);
            }

            if (!utcStart.HasValue)
            {
                utcStart = DateTime.MinValue;
            }

            if (!utcEnd.HasValue)
            {
                utcEnd = DateTime.MaxValue;
            }

            var utcEventDate = ev.Date.ToUniversalTime().DateTime;

            // utcEnd is before the current event date.
            if (utcStart > utcEventDate || utcEnd < utcEventDate)
            {
                return(null);
            }

            if (String.IsNullOrEmpty(userFilter))
            {
                userFilter = "stack:" + ev.StackId;
            }

            var results = await FindAsync(new ExceptionlessQuery()
                                          .WithDateRange(utcEventDate, utcEnd, EventIndexType.Fields.Date)
                                          .WithIndexes(utcStart, utcEventDate)
                                          .WithSort(EventIndexType.Fields.Date, SortOrder.Ascending)
                                          .WithLimit(10)
                                          .WithSelectedFields("id", "date")
                                          .WithSystemFilter(systemFilter)
                                          .WithElasticFilter(!Filter <PersistentEvent> .Ids(new[] { ev.Id }))
                                          .WithFilter(userFilter)).AnyContext();

            if (results.Total == 0)
            {
                return(null);
            }

            // make sure we don't have records with the exact same occurrence date
            if (results.Documents.All(t => t.Date != ev.Date))
            {
                return(results.Documents.OrderBy(t => t.Date).ThenBy(t => t.Id).First().Id);
            }

            // we have records with the exact same occurrence date, we need to figure out the order of those
            // put our target error into the mix, sort it and return the result after the target
            var unionResults = results.Documents.Union(new[] { ev })
                               .OrderBy(t => t.Date.Ticks).ThenBy(t => t.Id)
                               .ToList();

            var index = unionResults.FindIndex(t => t.Id == ev.Id);

            return(index == unionResults.Count - 1 ? null : unionResults[index + 1].Id);
        }