public Task <FindResults <PersistentEvent> > GetMostRecentAsync(string projectId, DateTime utcStart, DateTime utcEnd, PagingOptions paging, bool includeHidden = false, bool includeFixed = false, bool includeNotFound = true) { var filter = new FilterContainer(); if (!includeHidden) { filter &= !Filter <PersistentEvent> .Term(e => e.IsHidden, true); } if (!includeFixed) { filter &= !Filter <PersistentEvent> .Term(e => e.IsFixed, true); } if (!includeNotFound) { filter &= !Filter <PersistentEvent> .Term(e => e.Type, "404"); } if (utcStart != DateTime.MinValue) { filter &= Filter <PersistentEvent> .Range(r => r.OnField(e => e.Date).GreaterOrEquals(utcStart)); } if (utcEnd != DateTime.MaxValue) { filter &= Filter <PersistentEvent> .Range(r => r.OnField(e => e.Date).LowerOrEquals(utcEnd)); } return(FindAsync(new ElasticSearchOptions <PersistentEvent>().WithProjectId(projectId).WithFilter(filter).WithIndices(utcStart, utcEnd).WithPaging(paging).WithSort(s => s.OnField(e => e.Date).Descending()))); }
public virtual ICollection <T> GetByOrganizationIds(ICollection <string> organizationIds, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (organizationIds == null || organizationIds.Count == 0) { return(new List <T>()); } string cacheKey = String.Concat("org:", String.Join("", organizationIds).GetHashCode().ToString()); return(Find(new ElasticSearchOptions <T>() .WithOrganizationIds(organizationIds) .WithPaging(paging) .WithCacheKey(useCache ? cacheKey : null) .WithExpiresIn(expiresIn))); }
public Task <FindResults <PersistentEvent> > GetByOrganizationIdsAsync(ICollection <string> organizationIds, string query = null, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (organizationIds == null || organizationIds.Count == 0) { return(Task.FromResult(new FindResults <PersistentEvent>())); } string cacheKey = String.Concat("org:", String.Join("", organizationIds).GetHashCode().ToString()); return(FindAsync(new ElasticSearchOptions <PersistentEvent>() .WithOrganizationIds(organizationIds) .WithQuery(query) .WithPaging(GetPagingWithSortingOptions(paging)) .WithCacheKey(useCache ? cacheKey : null) .WithExpiresIn(expiresIn))); }
private ElasticSearchPagingOptions <PersistentEvent> GetPagingWithSortingOptions(PagingOptions paging) { var pagingOptions = new ElasticSearchPagingOptions <PersistentEvent>(paging); pagingOptions.SortBy.Add(s => s.OnField(f => f.Date).Descending()); pagingOptions.SortBy.Add(s => s.OnField("_uid").Descending()); return(pagingOptions); }
public Task <FindResults <PersistentEvent> > GetByStackIdOccurrenceDateAsync(string stackId, DateTime utcStart, DateTime utcEnd, PagingOptions paging) { var filter = new FilterContainer(); if (utcStart != DateTime.MinValue) { filter &= Filter <PersistentEvent> .Range(r => r.OnField(e => e.Date).GreaterOrEquals(utcStart)); } if (utcEnd != DateTime.MaxValue) { filter &= Filter <PersistentEvent> .Range(r => r.OnField(e => e.Date).LowerOrEquals(utcEnd)); } return(FindAsync(new ElasticSearchOptions <PersistentEvent>().WithStackId(stackId).WithFilter(filter).WithIndices(utcStart, utcEnd).WithPaging(paging).WithSort(s => s.OnField(e => e.Date).Descending()))); }
public override Task <FindResults <PersistentEvent> > GetByOrganizationIdAsync(string organizationId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(GetByOrganizationIdsAsync(new[] { organizationId }, paging, useCache, expiresIn)); }
public override Task <FindResults <PersistentEvent> > GetByProjectIdAsync(string projectId, PagingOptions paging = null) { return(FindAsync(new ExceptionlessQuery() .WithProjectId(projectId) .WithPaging(paging) .WithSort(EventIndexType.Fields.Date, SortOrder.Descending) .WithSort("_uid", SortOrder.Descending))); }
public ICollection <Stack> GetNew(string projectId, DateTime utcStart, DateTime utcEnd, PagingOptions paging, string query) { var options = new ElasticSearchOptions <Stack>().WithProjectId(projectId).WithQuery(query).WithSort(s => s.OnField(e => e.FirstOccurrence).Descending()).WithPaging(paging); options.Filter = Filter <Stack> .Range(r => r.OnField(s => s.FirstOccurrence).GreaterOrEquals(utcStart)); options.Filter &= Filter <Stack> .Range(r => r.OnField(s => s.FirstOccurrence).LowerOrEquals(utcEnd)); return(Find(options)); }
// TODO: We need to index and search by the created time. public Task <FindResults <PersistentEvent> > GetOpenSessionsAsync(DateTime createdBeforeUtc, PagingOptions paging = null) { var filter = Filter <PersistentEvent> .Term(e => e.Type, Event.KnownTypes.Session) && Filter <PersistentEvent> .Missing(e => e.Idx[Event.KnownDataKeys.SessionEnd + "-d"]); if (createdBeforeUtc.Ticks > 0) { filter &= Filter <PersistentEvent> .Range(r => r.OnField(e => e.Date).LowerOrEquals(createdBeforeUtc)); } return(FindAsync(new ExceptionlessQuery() .WithElasticFilter(filter) .WithSort(EventIndexType.Fields.Date, SortOrder.Descending) .WithPaging(paging))); }
public override Task <FindResults <PersistentEvent> > GetByOrganizationIdAsync(string organizationId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (String.IsNullOrEmpty(organizationId)) { throw new ArgumentNullException(nameof(organizationId)); } return(FindAsync(new ExceptionlessQuery() .WithOrganizationId(organizationId) .WithPaging(paging) .WithSort(EventIndexType.Fields.Date, SortOrder.Descending) .WithSort("_uid", SortOrder.Descending) .WithExpiresIn(expiresIn))); }
public Task <FindResults <PersistentEvent> > 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 = EventIndexType.Fields.Date, Order = SortOrder.Descending }); } var search = new ExceptionlessQuery() .WithDateRange(utcStart, utcEnd, field ?? EventIndexType.Fields.Date) .WithIndexes(utcStart, utcEnd) .WithSystemFilter(systemFilter) .WithFilter(userFilter) .WithPaging(paging) .WithSort(sorting); return(FindAsync(search)); }
public virtual Task <FindResults <User> > GetByOrganizationIdsAsync(ICollection <string> organizationIds, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (organizationIds == null || organizationIds.Count == 0) { return(Task.FromResult(new FindResults <User> { Documents = new List <User>(), Total = 0 })); } string cacheKey = String.Concat("org:", String.Join("", organizationIds).GetHashCode().ToString()); var filter = Filter <User> .Term(u => u.OrganizationIds, organizationIds); return(FindAsync(new ElasticSearchOptions <User>() .WithFilter(filter) .WithPaging(paging) .WithCacheKey(useCache ? cacheKey : null) .WithExpiresIn(expiresIn))); }
public virtual Task <FindResults <User> > GetByOrganizationIdAsync(string organizationId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(GetByOrganizationIdsAsync(new[] { organizationId }, paging, useCache, expiresIn)); }
public ICollection <Organization> GetByCriteria(string criteria, PagingOptions paging, OrganizationSortBy sortBy, bool?paid = null, bool?suspended = null) { var options = new MultiOptions().WithPaging(paging); if (!String.IsNullOrWhiteSpace(criteria)) { options.Query = options.Query.And(Query.Matches(FieldNames.Name, new BsonRegularExpression(String.Format("/{0}/i", criteria)))); } if (paid.HasValue) { if (paid.Value) { options.Query = options.Query.And(Query.NE(FieldNames.PlanId, new BsonString(BillingManager.FreePlan.Id))); } else { options.Query = options.Query.And(Query.EQ(FieldNames.PlanId, new BsonString(BillingManager.FreePlan.Id))); } } if (suspended.HasValue) { if (suspended.Value) { options.Query = options.Query.And( Query.Or( Query.And( Query.NE(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Active)), Query.NE(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Trialing)), Query.NE(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Canceled)) ), Query.EQ(FieldNames.IsSuspended, new BsonBoolean(true)))); } else { options.Query = options.Query.And( Query.Or( Query.EQ(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Active)), Query.EQ(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Trialing)), Query.EQ(FieldNames.BillingStatus, new BsonInt32((int)BillingStatus.Canceled)) ), Query.EQ(FieldNames.IsSuspended, new BsonBoolean(false))); } } switch (sortBy) { case OrganizationSortBy.Newest: options.SortBy = SortBy.Descending(FieldNames.Id); break; case OrganizationSortBy.Subscribed: options.SortBy = SortBy.Descending(FieldNames.SubscribeDate); break; case OrganizationSortBy.MostActive: options.SortBy = SortBy.Descending(FieldNames.TotalEventCount); break; default: options.SortBy = SortBy.Ascending(FieldNames.Name); break; } return(Find <Organization>(options)); }
public Task <FindResults <Organization> > GetByCriteriaAsync(string criteria, PagingOptions paging, OrganizationSortBy sortBy, bool?paid = null, bool?suspended = null) { var filter = Filter <Organization> .MatchAll(); if (!String.IsNullOrWhiteSpace(criteria)) { filter &= Filter <Organization> .Term(o => o.Name, criteria); } if (paid.HasValue) { if (paid.Value) { filter &= !Filter <Organization> .Term(o => o.PlanId, BillingManager.FreePlan.Id); } else { filter &= Filter <Organization> .Term(o => o.PlanId, BillingManager.FreePlan.Id); } } if (suspended.HasValue) { if (suspended.Value) { filter &= Filter <Organization> .And(and => (( !Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Active) && !Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Trialing) && !Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Canceled) ) || Filter <Organization> .Term(o => o.IsSuspended, true))); } else { filter &= Filter <Organization> .And(and => (( Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Active) && Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Trialing) && Filter <Organization> .Term(o => o.BillingStatus, BillingStatus.Canceled) ) || Filter <Organization> .Term(o => o.IsSuspended, false))); } } var query = new ExceptionlessQuery().WithPaging(paging).WithElasticFilter(filter); switch (sortBy) { case OrganizationSortBy.Newest: query.WithSort(OrganizationIndex.Fields.Organization.Id, SortOrder.Descending); break; case OrganizationSortBy.Subscribed: query.WithSort(OrganizationIndex.Fields.Organization.SubscribeDate, SortOrder.Descending); break; // case OrganizationSortBy.MostActive: // query.WithSort(OrganizationIndex.Fields.Organization.TotalEventCount, SortOrder.Descending); // break; default: query.WithSort(OrganizationIndex.Fields.Organization.Name, SortOrder.Ascending); break; } return(FindAsync(query)); }
public ICollection <Stack> GetByFilter(string systemFilter, string userFilter, string sort, SortOrder sortOrder, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging) { if (String.IsNullOrEmpty(sort)) { sort = "last"; sortOrder = SortOrder.Descending; } var search = new ElasticSearchOptions <Stack>() .WithDateRange(utcStart, utcEnd, field ?? "last") .WithFilter(!String.IsNullOrEmpty(systemFilter) ? Filter <Stack> .Query(q => q.QueryString(qs => qs.DefaultOperator(Operator.And).Query(systemFilter))) : null) .WithQuery(userFilter) .WithPaging(paging) .WithSort(e => e.OnField(sort).Order(sortOrder == SortOrder.Descending ? Nest.SortOrder.Descending : Nest.SortOrder.Ascending)); return(Find(search)); }
public Task <FindResults <Stack> > GetByFilterAsync(string systemFilter, string userFilter, SortingOptions sorting, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging) { if (sorting.Fields.Count == 0) { sorting.Fields.Add(new FieldSort { Field = StackIndex.Fields.Stack.LastOccurrence, Order = SortOrder.Descending }); } var search = new ExceptionlessQuery() .WithDateRange(utcStart, utcEnd, field ?? StackIndex.Fields.Stack.LastOccurrence) .WithSystemFilter(systemFilter) .WithFilter(userFilter) .WithPaging(paging) .WithSort(sorting); return(FindAsync(search)); }
public static ElasticSearchOptions <T> WithPaging <T>(this ElasticSearchOptions <T> options, PagingOptions paging) where T : class { if (paging == null) { return(options); } var elasticSearchPagingOptions = paging as ElasticSearchPagingOptions <T>; if (elasticSearchPagingOptions != null) { options.SortBy.AddRange(elasticSearchPagingOptions.SortBy); } options.Page = paging.Page; options.Limit = paging.Limit; options.HasMore = false; options.HasMoreChanged += (source, args) => paging.HasMore = args.Value; return(options); }
public Task <FindResults <Stack> > GetNewAsync(string projectId, DateTime utcStart, DateTime utcEnd, PagingOptions paging, string filter) { var filterContainer = Filter <Stack> .Range(r => r.OnField(s => s.FirstOccurrence).GreaterOrEquals(utcStart)) && Filter <Stack> .Range(r => r.OnField(s => s.FirstOccurrence).LowerOrEquals(utcEnd)); var query = new ExceptionlessQuery() .WithProjectId(projectId) .WithElasticFilter(filterContainer) .WithFilter(filter) .WithSort(StackIndex.Fields.Stack.FirstOccurrence, SortOrder.Descending) .WithPaging(paging); return(FindAsync(query)); }
private Task <FindResults <PersistentEvent> > GetOldestEventsAsync(string stackId, PagingOptions options) { return(FindAsync(new ElasticSearchOptions <PersistentEvent>() .WithStackId(stackId) .WithFields("id", "organization_id", "project_id", "stack_id") .WithSort(s => s.OnField(e => e.Date).Descending()) .WithPaging(options))); }
public override Task <FindResults <Token> > GetByProjectIdAsync(string projectId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { var filter = Filter <Token> .And(and => (Filter <Token> .Term(t => t.ProjectId, projectId) || Filter <Token> .Term(t => t.DefaultProjectId, projectId))); return(FindAsync(new ElasticSearchOptions <Token>() .WithFilter(filter) .WithPaging(paging) .WithCacheKey(useCache ? String.Concat("project:", projectId) : null) .WithExpiresIn(expiresIn))); }
public override Task <FindResults <PersistentEvent> > GetByOrganizationIdsAsync(ICollection <string> organizationIds, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(base.GetByOrganizationIdsAsync(organizationIds, GetPagingWithSortingOptions(paging), useCache, expiresIn)); }
public Task <FindResults <Token> > GetByTypeAndOrganizationIdAsync(TokenType type, string organizationId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(FindAsync(new ElasticSearchOptions <Token>() .WithOrganizationId(organizationId) .WithFilter(Filter <Token> .Term(t => t.Type, type)) .WithPaging(paging) .WithCacheKey(useCache ? String.Concat("type:", type, "-org:", organizationId) : null) .WithExpiresIn(expiresIn))); }
public override Task <FindResults <PersistentEvent> > GetByProjectIdAsync(string projectId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(base.GetByProjectIdAsync(projectId, GetPagingWithSortingOptions(paging), useCache, expiresIn)); }
public Task <FindResults <Token> > GetByTypeAndOrganizationIdsAsync(TokenType type, ICollection <string> organizationIds, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (organizationIds == null || organizationIds.Count == 0) { return(Task.FromResult(new FindResults <Token>())); } string cacheKey = String.Concat("type:", type, "-org:", String.Join("", organizationIds).GetHashCode().ToString()); return(FindAsync(new ElasticSearchOptions <Token>() .WithOrganizationIds(organizationIds) .WithFilter(Filter <Token> .Term(t => t.Type, type)) .WithPaging(paging) .WithCacheKey(useCache ? cacheKey : null) .WithExpiresIn(expiresIn))); }
public Task <FindResults <PersistentEvent> > GetByFilterAsync(string systemFilter, string userFilter, string sort, SortOrder sortOrder, string field, DateTime utcStart, DateTime utcEnd, PagingOptions paging) { if (String.IsNullOrEmpty(sort)) { sort = "date"; sortOrder = SortOrder.Descending; } var search = new ElasticSearchOptions <PersistentEvent>() .WithDateRange(utcStart, utcEnd, field ?? "date") .WithIndicesFromDateRange($"'{_index.VersionedName}-'yyyyMM") .WithFilter(!String.IsNullOrEmpty(systemFilter) ? Filter <PersistentEvent> .Query(q => q.QueryString(qs => qs.DefaultOperator(Operator.And).Query(systemFilter))) : null) .WithQuery(userFilter) .WithPaging(paging) .WithSort(e => e.OnField(sort).Order(sortOrder == SortOrder.Descending ? Nest.SortOrder.Descending : Nest.SortOrder.Ascending)); return(FindAsync(search)); }
public Task <FindResults <Token> > GetByTypeAndOrganizationIdOrProjectIdAsync(TokenType type, string organizationId, string projectId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { var filter = Filter <Token> .And(and => ( Filter <Token> .Term(t => t.OrganizationId, organizationId) || Filter <Token> .Term(t => t.ProjectId, projectId) || Filter <Token> .Term(t => t.DefaultProjectId, projectId) ) && Filter <Token> .Term(t => t.Type, type)); return(FindAsync(new ElasticSearchOptions <Token>() .WithFilter(filter) .WithPaging(paging) .WithCacheKey(String.Concat("type:", type, "-org:", organizationId, "-project:", projectId)) .WithExpiresIn(expiresIn))); }
public virtual ICollection <T> GetByOrganizationId(string organizationId, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { return(GetByOrganizationIds(new[] { organizationId }, paging, useCache, expiresIn)); }
public ICollection <Stack> GetNew(string projectId, DateTime utcStart, DateTime utcEnd, PagingOptions paging, bool includeHidden = false, bool includeFixed = false, bool includeNotFound = true) { var options = new MultiOptions().WithProjectId(projectId).WithSort(SortBy.Descending(FieldNames.FirstOccurrence)).WithPaging(paging); options.Query = options.Query.And(Query.GTE(FieldNames.FirstOccurrence, utcStart), Query.LTE(FieldNames.FirstOccurrence, utcEnd)); if (!includeFixed) { options.Query = options.Query.And(Query.NotExists(FieldNames.DateFixed)); } if (!includeHidden) { options.Query = options.Query.And(Query.NE(FieldNames.IsHidden, true)); } if (!includeNotFound) { options.Query = options.Query.And(Query.NotExists(FieldNames.SignatureInfo_Path)); } return(Find <Stack>(options)); }
public ICollection <T> GetByIds(ICollection <string> ids, PagingOptions paging = null, bool useCache = false, TimeSpan?expiresIn = null) { if (ids == null || ids.Count == 0) { return(new List <T>()); } var results = new List <T>(); if (EnableCache && useCache) { results.AddRange(ids.Select(id => Cache.Get <T>(GetScopedCacheKey(id))).Where(cacheHit => cacheHit != null)); var notCachedIds = ids.Except(results.Select(i => i.Id)).ToArray(); if (notCachedIds.Length == 0) { return(results); } } // try using the object id to figure out what index the entity is located in var foundItems = new List <T>(); var itemsToFind = new List <string>(); var multiGet = new MultiGetDescriptor(); foreach (var id in ids.Except(results.Select(i => i.Id))) { string index = GetIndexName(id); if (index != null) { multiGet.Get <T>(f => f.Id(id).Index(index).Source(s => s.Exclude("idx"))); } else { itemsToFind.Add(id); } } _elasticClient.EnableTrace(); foreach (var doc in _elasticClient.MultiGet(multiGet).Documents) { if (doc.Found) { foundItems.Add(doc.Source as T); } else { itemsToFind.Add(doc.Id); } } _elasticClient.DisableTrace(); // fallback to doing a find if (itemsToFind.Count > 0) { foundItems.AddRange(Find(new ElasticSearchOptions <T>().WithIds(itemsToFind))); } if (EnableCache && useCache && foundItems.Count > 0) { foreach (var item in foundItems) { Cache.Set(GetScopedCacheKey(item.Id), item, expiresIn.HasValue ? DateTime.Now.Add(expiresIn.Value) : DateTime.Now.AddSeconds(RepositoryConstants.DEFAULT_CACHE_EXPIRATION_SECONDS)); } } results.AddRange(foundItems); return(results); }
private async Task ProcessSummaryNotificationAsync(SummaryNotification data) { var project = await _projectRepository.GetByIdAsync(data.Id, true).AnyContext(); var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, true).AnyContext(); var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary).Select(n => n.Key).ToList(); if (userIds.Count == 0) { Log.Info().Message("Project \"{0}\" has no users to send summary to.", project.Id).Write(); return; } var users = (await _userRepository.GetByIdsAsync(userIds).AnyContext()).Documents.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(organization.Id)).ToList(); if (users.Count == 0) { Log.Info().Message("Project \"{0}\" has no users to send summary to.", project.Id).Write(); return; } Log.Info().Message("Sending daily summary: users={0} project={1}", users.Count, project.Id).Write(); var paging = new PagingOptions { Limit = 5 }; List<Stack> newest = (await _stackRepository.GetNewAsync(project.Id, data.UtcStartTime, data.UtcEndTime, paging).AnyContext()).Documents.ToList(); var result = await _stats.GetTermsStatsAsync(data.UtcStartTime, data.UtcEndTime, "stack_id", "type:error project:" + data.Id, max: 5).AnyContext(); //var termStatsList = result.Terms.Take(5).ToList(); //var stacks = _stackRepository.GetByIds(termStatsList.Select(s => s.Term).ToList()); bool hasSubmittedErrors = result.Total > 0; if (!hasSubmittedErrors) hasSubmittedErrors = await _eventRepository.GetCountByProjectIdAsync(project.Id).AnyContext() > 0; var mostFrequent = new List<EventStackResult>(); //foreach (var termStats in termStatsList) { // var stack = stacks.SingleOrDefault(s => s.Id == termStats.Term); // if (stack == null) // continue; // mostFrequent.Add(new EventStackResult { // First = termStats.FirstOccurrence, // Last = termStats.LastOccurrence, // Id = stack.Id, // Title = stack.Title, // Total = termStats.Total, // Type = stack.SignatureInfo.ContainsKey("ExceptionType") ? stack.SignatureInfo["ExceptionType"] : null, // Method = stack.SignatureInfo.ContainsKey("Method") ? stack.SignatureInfo["Method"] : null, // Path = stack.SignatureInfo.ContainsKey("Source") ? stack.SignatureInfo["Source"] : null, // Is404 = stack.SignatureInfo.ContainsKey("Type") && stack.SignatureInfo["Type"] == "404" // }); //} var notification = new DailySummaryModel { ProjectId = project.Id, ProjectName = project.Name, StartDate = data.UtcStartTime, EndDate = data.UtcEndTime, Total = result.Total, PerHourAverage = result.Total / data.UtcEndTime.Subtract(data.UtcStartTime).TotalHours, NewTotal = result.New, New = newest, UniqueTotal = result.Unique, MostFrequent = mostFrequent, HasSubmittedEvents = hasSubmittedErrors, IsFreePlan = organization.PlanId == BillingManager.FreePlan.Id }; foreach (var user in users) await _mailer.SendDailySummaryAsync(user.EmailAddress, notification).AnyContext(); Log.Info().Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Id, notification.Total).Write(); }