diff --git a/PepperBot/Application/Services/DealService.cs b/PepperBot/Application/Services/DealService.cs index 69ea153..759dcc5 100644 --- a/PepperBot/Application/Services/DealService.cs +++ b/PepperBot/Application/Services/DealService.cs @@ -33,19 +33,24 @@ public class DealService { var deals = await _pepperClient.GetLatestDealsAsync(cancellationToken); + _logger.LogInformation("Начата обработка полученных скидок: всего {DealCount}", deals.Count); + // Хелсчек: успешный запрос, вернувший более одной скидки (пусть и не новой) if (deals.Count > 1) { _healthMonitor.ReportSuccess(DateTimeOffset.UtcNow); + _logger.LogDebug("HealthCheck: успешно получено более одной скидки ({DealCount})", deals.Count); } // Загружаем активные подписки один раз на проход var subscriptions = await _subscriptionRepository.GetAllActiveAsync(cancellationToken); + _logger.LogInformation("Загружено активных подписок: {SubscriptionCount}", subscriptions.Count); foreach (var deal in deals) { if (await _repository.ExistsAsync(deal.Id, cancellationToken)) { + _logger.LogDebug("Скидка уже есть в репозитории и будет пропущена: {DealId}", deal.Id); continue; } @@ -58,6 +63,7 @@ public class DealService if (subscriptions.Count == 0) { + _logger.LogDebug("Активные подписки отсутствуют. Фильтрация по ключевым словам пропущена для скидки {DealId}", deal.Id); continue; } @@ -67,16 +73,29 @@ public class DealService { if (!subscription.IsActive) { + _logger.LogDebug("Подписка {SubscriptionId} неактивна и будет пропущена", subscription.Id); continue; } var keywords = ParseKeywords(subscription.Keywords); if (keywords.Count == 0) { + _logger.LogDebug("У подписки {SubscriptionId} не удалось извлечь ключевые слова из строки: \"{RawKeywords}\"", + subscription.Id, + subscription.Keywords); continue; } - if (IsMatch(searchableText, keywords)) + var isMatch = IsMatch(searchableText, keywords); + _logger.LogDebug( + "Результат фильтрации скидки {DealId} по подписке {SubscriptionId}: {IsMatch}. Текст: \"{Text}\"; ключевые слова: {Keywords}", + deal.Id, + subscription.Id, + isMatch, + searchableText, + string.Join(", ", keywords)); + + if (isMatch) { await _notifier.NotifyDealToChatAsync(deal, subscription.ChatId, cancellationToken); } diff --git a/PepperBot/Infrastructure/Pepper/PepperClient.cs b/PepperBot/Infrastructure/Pepper/PepperClient.cs index 7dd8ab5..fd55299 100644 --- a/PepperBot/Infrastructure/Pepper/PepperClient.cs +++ b/PepperBot/Infrastructure/Pepper/PepperClient.cs @@ -45,7 +45,10 @@ public class PepperClient : IPepperClient public async Task> GetLatestDealsAsync(CancellationToken cancellationToken) { using var request = new HttpRequestMessage(HttpMethod.Get, Url); + _logger.LogDebug("Отправка запроса за последними скидками Pepper: {Url}", Url); + using var response = await _httpClient.SendAsync(request, cancellationToken); + _logger.LogDebug("Получен ответ от Pepper: {StatusCode}", (int)response.StatusCode); response.EnsureSuccessStatusCode(); @@ -58,7 +61,12 @@ public class PepperClient : IPepperClient return Array.Empty(); } - return dto.Deals.Select(MapToDeal).ToArray(); + _logger.LogInformation("Успешно распарсен ответ Pepper: всего сделок в ответе {DealCount}", dto.Deals.Count); + + var mappedDeals = dto.Deals.Select(MapToDeal).ToArray(); + _logger.LogDebug("После маппинга в доменную модель осталось сделок: {MappedCount}", mappedDeals.Length); + + return mappedDeals; } private static Deal MapToDeal(PepperDeal dto) diff --git a/PepperBot/PepperBot.csproj b/PepperBot/PepperBot.csproj index fab46d5..5494f1f 100644 --- a/PepperBot/PepperBot.csproj +++ b/PepperBot/PepperBot.csproj @@ -14,7 +14,7 @@ - + diff --git a/PepperBot/Program.cs b/PepperBot/Program.cs index 029ddbb..bfb695f 100644 --- a/PepperBot/Program.cs +++ b/PepperBot/Program.cs @@ -10,14 +10,16 @@ using PepperBot.Infrastructure.Health; using PepperBot.Infrastructure.Pepper; using PepperBot.Infrastructure.Telegram; using Telegram.Bot; +using NLog.Web; -var builder = WebApplication.CreateBuilder(args); +var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); -builder.Services.AddLogging(logging => +try { - logging.ClearProviders(); - logging.AddConsole(); -}); + var builder = WebApplication.CreateBuilder(args); + + builder.Logging.ClearProviders(); + builder.Host.UseNLog(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); @@ -33,25 +35,36 @@ builder.Services.AddSingleton(_ => return new TelegramBotClient(token); }); -builder.Services.AddHostedService(); + builder.Services.AddHostedService(); -var app = builder.Build(); + var app = builder.Build(); -app.MapGet("/health", (IHealthMonitor healthMonitor) => -{ - var successTtl = TimeSpan.FromMinutes(15); - var isHealthy = healthMonitor.IsHealthy(successTtl); - - if (isHealthy) + app.MapGet("/health", (IHealthMonitor healthMonitor) => { - return Results.Ok(new + var successTtl = TimeSpan.FromMinutes(15); + var isHealthy = healthMonitor.IsHealthy(successTtl); + + if (isHealthy) { - status = "Healthy", - lastSuccessfulRequestAt = healthMonitor.LastSuccessfulRequestAt - }); - } + return Results.Ok(new + { + status = "Healthy", + lastSuccessfulRequestAt = healthMonitor.LastSuccessfulRequestAt + }); + } - return Results.StatusCode(StatusCodes.Status503ServiceUnavailable); -}); + return Results.StatusCode(StatusCodes.Status503ServiceUnavailable); + }); -await app.RunAsync(); + logger.LogInformation("Запуск PepperBot приложения"); + await app.RunAsync(); +} +catch (Exception ex) +{ + logger.LogError(ex, "Приложение остановлено из-за необработанного исключения"); + throw; +} +finally +{ + global::NLog.LogManager.Shutdown(); +} diff --git a/PepperBot/nlog.config b/PepperBot/nlog.config new file mode 100644 index 0000000..1bb6f93 --- /dev/null +++ b/PepperBot/nlog.config @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + +