using NLog; using Sony.Filtr.Database; using Sony.Filtr.Tasks.Models; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sony.Filtr.Utility.Extensions; using Sony.Filtr.Tasks.Models.ExportLogs; using Sentry; namespace Sony.Filtr.Tasks.Tasks { public class ExportLogsTask : IScheduledTask { private readonly Logger _logger; public string CurrentApplicationName { get; set; } public ExportLogsTask() { _logger = LogManager.GetLogger("ExportLogsTask"); } public async Task ExecuteAsync(Guid scheduledTaskLogId) { var exportLogSettings = await ReadSettings(); var elmahErrors = await ReadErrors(exportLogSettings.Sequence, exportLogSettings.Limit); var sortedErrors = SortErrors(exportLogSettings.FilterExpression, elmahErrors); if (sortedErrors.Count() == 0) { if (elmahErrors.Count() > 0) { await ModifySettings(exportLogSettings.Sequence, elmahErrors.Max(x => x.Sequence)); } return null; } await ExportErrors(sortedErrors, exportLogSettings); var lastSequence = elmahErrors.Max(x => x.Sequence); await ModifySettings(exportLogSettings.Sequence, lastSequence); return null; } private async Task ReadSettings() { long? sequence = 0; string filterExpression = string.Empty; int? destination = 0; string sentryJobsDestination = string.Empty; string sentryApiDestination = string.Empty; string jobHosts = string.Empty; string apiHosts = string.Empty; int? limit = 0; _logger.Debug($"Begin read settings"); using (var connection = await DatabaseHandler.GetOpenReadOnlyConnectionAsync()) { var cmd = connection.CreateCommand(); cmd.CommandText = "SELECT * FROM tblExportLogs WHERE ExportDestination = 1"; var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { sequence = reader.GetLongOrDefault("Sequence"); filterExpression = reader.GetString("FilterExpressions"); destination = reader.GetIntOrDefault("ExportDestination"); sentryJobsDestination = reader.GetString("SentryJobsDestination"); sentryApiDestination = reader.GetString("SentryApiDestination"); jobHosts = reader.GetString("JobHosts"); apiHosts = reader.GetString("ApiHosts"); limit = reader.GetIntOrDefault("ErrorsLimit"); } } if (sequence == null || destination == null) { _logger.Error($"Data in tblExportLogs table corrupted"); return null; } _logger.Debug($"Done read settings"); return new ExportLogSettings { Sequence = sequence ?? default(long), FilterExpression = filterExpression, Destination = destination ?? default(int), SentryJobsDestination = sentryJobsDestination, SentryApiDestination = sentryApiDestination, JobHosts = jobHosts, ApiHosts = apiHosts, Limit = limit ?? default(int) }; } private async Task> ReadErrors(long? sequence, int limit) { _logger.Debug($"Begin read errors"); List elmahErrors = new List(); using (var connection = await DatabaseHandler.GetOpenReadOnlyConnectionAsync()) { var cmd = connection.CreateCommand(); cmd.CommandText = "SELECT * FROM elmah.elmah_error WHERE Sequence > @sequence ORDER BY Sequence ASC LIMIT @limit"; cmd.Parameters.AddWithValue("@sequence", sequence); cmd.Parameters.AddWithValue("@limit", limit); var reader = await cmd.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var elmahError = new ExportLog(reader); elmahErrors.Add(elmahError); } } _logger.Debug($"Done read errors"); return elmahErrors; } private async Task ModifySettings(long? sequence, long lastSequence) { _logger.Debug($"Begin modify settings"); using (var connection = await DatabaseHandler.GetOpenConnectionAsync()) { var cmd = connection.CreateCommand(); if (sequence == 0) { _logger.Debug($"No records in tbExportLogs table. Initial Insert"); cmd.CommandText = "INSERT INTO tblExportLogs (Sequence,Date, ExportDestination) VALUES (@sequence, @date, @exportDestination)"; cmd.Parameters.AddWithValue("@sequence", lastSequence); cmd.Parameters.AddWithValue("@date", DateTime.UtcNow); cmd.Parameters.AddWithValue("@exportDestination", (int)ExportDestination.Sentry); await cmd.ExecuteReaderAsync(); } else { cmd.CommandText = "UPDATE tblExportLogs SET Sequence = @sequence, Date = @date, ExportDestination = @exportDestination"; cmd.Parameters.AddWithValue("@sequence", lastSequence); cmd.Parameters.AddWithValue("@date", DateTime.UtcNow); cmd.Parameters.AddWithValue("@exportDestination", (int)ExportDestination.Sentry); await cmd.ExecuteReaderAsync(); } _logger.Debug($"Done modify settings"); } } private List SortErrors(string filterExpression, List errors) { if (filterExpression == null) { return errors; } List filters = filterExpression.Split(',').ToList(); return errors.Where(t2 => !filters.Any(t1 => t2.Message.Contains(t1))).ToList(); } private async Task ExportErrors (List elmahErrors, ExportLogSettings settings) { List jobHostsList = settings.JobHosts.Split(',').ToList(); List apiHostsList = settings.ApiHosts.Split(',').ToList(); var jobErrors = elmahErrors.Where(x => jobHostsList.Contains(x.HostName)).ToList(); var apiErrors = elmahErrors.Where(x => apiHostsList.Contains(x.HostName)).ToList(); using (SentrySdk.Init(o => { o.Dsn =new Dsn(settings.SentryJobsDestination); o.Debug = true; o.SampleRate = 1; o.MaxQueueItems = settings.Limit; o.SendDefaultPii = true; })) { foreach (var jobError in jobErrors) { var clsr = jobError; SentrySdk.CaptureException(clsr); } await SentrySdk.FlushAsync(TimeSpan.FromDays(1)); } using (SentrySdk.Init(o => { o.Dsn = new Dsn(settings.SentryApiDestination); o.Debug = true; o.SampleRate = 1; o.MaxQueueItems = settings.Limit; o.SendDefaultPii = true; })) { foreach (var apiError in apiErrors) { var clsr = apiError; SentrySdk.CaptureException(clsr); } await SentrySdk.FlushAsync(TimeSpan.FromDays(1)); } } } }