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) { _logger.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) { _logger.Info().Message("Project \"{0}\" has no users to send summary to.", project.Id).Write(); return; } _logger.Info().Message("Sending daily summary: users={0} project={1}", users.Count, project.Id).Write(); var result = await _stats.GetTermsStatsAsync(data.UtcStartTime, data.UtcEndTime, "stack_id", "type:error project:" + data.Id, max : 5).AnyContext(); bool hasSubmittedErrors = result.Total > 0; if (!hasSubmittedErrors) { hasSubmittedErrors = await _eventRepository.GetCountByProjectIdAsync(project.Id).AnyContext() > 0; } 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, UniqueTotal = result.Unique, HasSubmittedEvents = hasSubmittedErrors, IsFreePlan = organization.PlanId == BillingManager.FreePlan.Id }; foreach (var user in users) { await _mailer.SendDailySummaryAsync(user.EmailAddress, notification).AnyContext(); } _logger.Info().Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Id, notification.Total).Write(); }
public async Task SendSummaryNotificationAsync() { await _mailer.SendDailySummaryAsync(Settings.Current.TestEmailAddress, new DailySummaryModel { ProjectId = "1", BaseUrl = "http://be.exceptionless.io", StartDate = SystemClock.UtcNow.Date, EndDate = SystemClock.UtcNow.EndOfDay(), NewTotal = 1, PerHourAverage = 0.4, ProjectName = "Blah", Subject = "A daily summary", Total = 12, UniqueTotal = 1, HasSubmittedEvents = true, IsFreePlan = false }); await RunMailJobAsync(); }
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) { _logger.Info("Project \"{0}\" has no users to send summary to.", project.Id); 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) { _logger.Info("Project \"{0}\" has no users to send summary to.", project.Id); return; } _logger.Info("Sending daily summary: users={0} project={1}", users.Count, project.Id); var fields = new List <FieldAggregation> { new FieldAggregation { Type = FieldAggregationType.Distinct, Field = "stack_id" }, new TermFieldAggregation { Field = "is_first_occurrence", ExcludePattern = "F" } }; var result = await _stats.GetNumbersStatsAsync(fields, data.UtcStartTime, data.UtcEndTime, $"project:{data.Id} type:error").AnyContext(); bool hasSubmittedEvents = result.Total > 0; if (!hasSubmittedEvents) { hasSubmittedEvents = await _eventRepository.GetCountByProjectIdAsync(project.Id).AnyContext() > 0; } 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.Numbers[1], UniqueTotal = result.Numbers[0], HasSubmittedEvents = hasSubmittedEvents, IsFreePlan = organization.PlanId == BillingManager.FreePlan.Id }; foreach (var user in users) { await _mailer.SendDailySummaryAsync(user.EmailAddress, notification).AnyContext(); } _logger.Info("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Id, notification.Total); }
private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data) { var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary).Select(n => n.Key).ToList(); if (userIds.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name).Write(); return(false); } var results = await _userRepository.GetByIdsAsync(userIds, true).AnyContext(); var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList(); if (users.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name); return(false); } // TODO: What should we do about suspended organizations. var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, true).AnyContext(); if (organization == null) { _logger.Info().Project(project.Id).Message("The organization \"{0}\" for project \"{1}\" may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name); return(false); } _logger.Info("Sending daily summary: users={0} project={1}", users.Count, project.Id); var fields = new List <FieldAggregation> { new FieldAggregation { Type = FieldAggregationType.Distinct, Field = "stack_id" }, new TermFieldAggregation { Field = "is_first_occurrence", ExcludePattern = "F" } }; var sf = new ExceptionlessSystemFilterQuery(project, organization); var result = await _stats.GetNumbersStatsAsync(fields, data.UtcStartTime, data.UtcEndTime, sf, $"{EventIndexType.Fields.Type}:{Event.KnownTypes.Error}").AnyContext(); bool hasSubmittedEvents = result.Total > 0; if (!hasSubmittedEvents) { hasSubmittedEvents = await _eventRepository.GetCountByProjectIdAsync(project.Id).AnyContext() > 0; } 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.Numbers[1], UniqueTotal = result.Numbers[0], HasSubmittedEvents = hasSubmittedEvents, IsFreePlan = organization.PlanId == BillingManager.FreePlan.Id }; foreach (var user in users) { await _mailer.SendDailySummaryAsync(user.EmailAddress, notification).AnyContext(); } _logger.Info().Project(project.Id).Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Name, notification.Total); return(true); }
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) { Logger.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) { Logger.Info().Message("Project \"{0}\" has no users to send summary to.", project.Id).Write(); return; } Logger.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 newest = new List <Stack>(); 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(); } Logger.Info().Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Id, notification.Total).Write(); }
private async Task <bool> SendSummaryNotificationAsync(Project project, SummaryNotification data) { var userIds = project.NotificationSettings.Where(n => n.Value.SendDailySummary).Select(n => n.Key).ToList(); if (userIds.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name).Write(); return(false); } var results = await _userRepository.GetByIdsAsync(userIds, true).AnyContext(); var users = results.Where(u => u.IsEmailAddressVerified && u.EmailNotificationsEnabled && u.OrganizationIds.Contains(project.OrganizationId)).ToList(); if (users.Count == 0) { _logger.Info().Project(project.Id).Message("Project \"{0}\" has no users to send summary to.", project.Name); return(false); } // TODO: What should we do about suspended organizations. var organization = await _organizationRepository.GetByIdAsync(project.OrganizationId, true).AnyContext(); if (organization == null) { _logger.Info().Project(project.Id).Message("The organization \"{0}\" for project \"{1}\" may have been deleted. No summaries will be sent.", project.OrganizationId, project.Name); return(false); } _logger.Info("Sending daily summary: users={0} project={1}", users.Count, project.Id); var sf = new ExceptionlessSystemFilterQuery(project, organization); var systemFilter = new ElasticQuery().WithSystemFilter(sf).WithDateRange(data.UtcStartTime, data.UtcEndTime, (PersistentEvent e) => e.Date).WithIndexes(data.UtcStartTime, data.UtcEndTime); var result = await _eventRepository.CountBySearchAsync(systemFilter, $"{EventIndexType.Alias.Type}:{Event.KnownTypes.Error}", "terms:(is_first_occurrence @include:true) cardinality:stack_id").AnyContext(); bool hasSubmittedEvents = result.Total > 0; if (!hasSubmittedEvents) { hasSubmittedEvents = await _eventRepository.GetCountByProjectIdAsync(project.Id, true).AnyContext() > 0; } 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.Aggregations.Terms <double>("terms_is_first_occurrence")?.Buckets.FirstOrDefault()?.Total ?? 0, UniqueTotal = result.Aggregations.Cardinality("cardinality_stack_id")?.Value ?? 0, HasSubmittedEvents = hasSubmittedEvents, IsFreePlan = organization.PlanId == BillingManager.FreePlan.Id }; foreach (var user in users) { await _mailer.SendDailySummaryAsync(user.EmailAddress, notification).AnyContext(); } _logger.Info().Project(project.Id).Message("Done sending daily summary: users={0} project={1} events={2}", users.Count, project.Name, notification.Total); return(true); }