Refactor logging messages for consistency and clarity
CI / Backend (build + test) (push) Successful in 1m14s
CI / Frontend (lint + typecheck + build) (push) Successful in 43s

- Updated various logging messages across the application to replace Russian text with English equivalents, ensuring consistency in error and information logs.
- Enhanced clarity in log messages related to Telegram bot operations, user management commands, and health check services, improving overall traceability and understanding of application behavior.
This commit is contained in:
Leonid Pershin
2026-07-02 15:04:10 +03:00
parent 3cdd3adf5e
commit 48f620b964
10 changed files with 22 additions and 22 deletions
+2 -2
View File
@@ -100,8 +100,8 @@ var app = builder.Build();
if (string.IsNullOrWhiteSpace(builder.Configuration["DataProtection:KeyRingPath"])) if (string.IsNullOrWhiteSpace(builder.Configuration["DataProtection:KeyRingPath"]))
{ {
app.Logger.LogWarning( app.Logger.LogWarning(
"DataProtection:KeyRingPath не задан — ключи шифрования секретов нод не персистентны " + "DataProtection:KeyRingPath is not set — node secret encryption keys are not persistent " +
"и будут потеряны при пересоздании контейнера. В проде обязательно смонтируй том и укажи путь."); "and will be lost when the container is recreated. Mount a volume and set the path in production.");
} }
// Авто-применение миграций и идемпотентный сидинг (роли + админ из env) на старте. // Авто-применение миграций и идемпотентный сидинг (роли + админ из env) на старте.
@@ -36,13 +36,13 @@ public sealed class PnvBotUpdateHandler(
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "Ошибка обработки Telegram-апдейта {UpdateId}", update.Id); logger.LogError(ex, "Failed to process Telegram update {UpdateId}", update.Id);
} }
} }
public Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, HandleErrorSource source, CancellationToken cancellationToken) public Task HandleErrorAsync(ITelegramBotClient botClient, Exception exception, HandleErrorSource source, CancellationToken cancellationToken)
{ {
logger.LogError(exception, "Ошибка Telegram-бота (источник {Source})", source); logger.LogError(exception, "Telegram bot error (source {Source})", source);
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -21,7 +21,7 @@ public sealed class TelegramBotHostedService(
{ {
if (string.IsNullOrWhiteSpace(options.Value.BotToken)) if (string.IsNullOrWhiteSpace(options.Value.BotToken))
{ {
logger.LogWarning("Telegram__BotToken не задан — бот не стартует."); logger.LogWarning("Telegram__BotToken is not set — bot will not start.");
return; return;
} }
@@ -31,7 +31,7 @@ public sealed class TelegramBotHostedService(
DropPendingUpdates = true, DropPendingUpdates = true,
}; };
logger.LogInformation("Telegram-бот запускается (long polling)..."); logger.LogInformation("Telegram bot starting (long polling)...");
try try
{ {
@@ -44,7 +44,7 @@ public sealed class BlockUserCommandHandler(
// с реальным состоянием клиента в 3x-ui (пользователь решит, что VPN погашен, а он жив). // с реальным состоянием клиента в 3x-ui (пользователь решит, что VPN погашен, а он жив).
// Конфиг останется Active и будет подхвачен повторным BlockUserCommand (идемпотентен). // Конфиг останется Active и будет подхвачен повторным BlockUserCommand (идемпотентен).
logger.LogWarning( logger.LogWarning(
"Не удалось отключить клиента конфига {ConfigId} на ноде {NodeId} при блокировке пользователя {UserId}: {Error}", "Failed to disable client for config {ConfigId} on node {NodeId} while blocking user {UserId}: {Error}",
config.Id, node.Id, command.UserId, updateResult.Error); config.Id, node.Id, command.UserId, updateResult.Error);
continue; continue;
} }
@@ -43,7 +43,7 @@ public sealed class UnblockUserCommandHandler(
// с реальным состоянием клиента в 3x-ui. Конфиг останется Disabled и будет подхвачен // с реальным состоянием клиента в 3x-ui. Конфиг останется Disabled и будет подхвачен
// повторным UnblockUserCommand (идемпотентен). // повторным UnblockUserCommand (идемпотентен).
logger.LogWarning( logger.LogWarning(
"Не удалось включить клиента конфига {ConfigId} на ноде {NodeId} при разблокировке пользователя {UserId}: {Error}", "Failed to enable client for config {ConfigId} on node {NodeId} while unblocking user {UserId}: {Error}",
config.Id, node.Id, command.UserId, updateResult.Error); config.Id, node.Id, command.UserId, updateResult.Error);
continue; continue;
} }
@@ -10,11 +10,11 @@ public sealed class LoggingBehavior<TRequest, TResponse>(ILogger<LoggingBehavior
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{ {
var requestName = typeof(TRequest).Name; var requestName = typeof(TRequest).Name;
logger.LogInformation("Обработка {RequestName}", requestName); logger.LogInformation("Handling {RequestName}", requestName);
var response = await next(); var response = await next();
logger.LogInformation("Обработан {RequestName}", requestName); logger.LogInformation("Handled {RequestName}", requestName);
return response; return response;
} }
} }
@@ -23,7 +23,7 @@ public sealed class NodeHealthCheckService(IServiceScopeFactory scopeFactory, IL
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "Ошибка health-check нод"); logger.LogError(ex, "Node health-check failed");
} }
} }
while (await timer.WaitForNextTickAsync(stoppingToken)); while (await timer.WaitForNextTickAsync(stoppingToken));
@@ -25,7 +25,7 @@ public sealed class TrafficRetentionService(
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "Ошибка ретеншна истории трафика"); logger.LogError(ex, "Traffic history retention failed");
} }
} }
while (await timer.WaitForNextTickAsync(stoppingToken)); while (await timer.WaitForNextTickAsync(stoppingToken));
@@ -40,6 +40,6 @@ public sealed class TrafficRetentionService(
var deleted = await dbContext.TrafficSamples.Where(s => s.Timestamp < cutoff).ExecuteDeleteAsync(cancellationToken); var deleted = await dbContext.TrafficSamples.Where(s => s.Timestamp < cutoff).ExecuteDeleteAsync(cancellationToken);
if (deleted > 0) if (deleted > 0)
logger.LogInformation("Удалено {Count} устаревших записей истории трафика", deleted); logger.LogInformation("Deleted {Count} expired traffic history records", deleted);
} }
} }
@@ -28,7 +28,7 @@ public sealed class TrafficSyncService(IServiceScopeFactory scopeFactory, ILogge
} }
catch (Exception ex) catch (Exception ex)
{ {
logger.LogError(ex, "Ошибка синхронизации трафика"); logger.LogError(ex, "Traffic sync failed");
} }
} }
while (await timer.WaitForNextTickAsync(stoppingToken)); while (await timer.WaitForNextTickAsync(stoppingToken));
@@ -38,10 +38,10 @@ public sealed class DbInitializer(
if (!result.Succeeded) if (!result.Succeeded)
{ {
throw new InvalidOperationException( throw new InvalidOperationException(
$"Не удалось создать роль '{name}': {string.Join(", ", result.Errors.Select(e => e.Description))}"); $"Failed to create role '{name}': {string.Join(", ", result.Errors.Select(e => e.Description))}");
} }
logger.LogInformation("Создана системная роль {RoleName}", name); logger.LogInformation("Created system role {RoleName}", name);
} }
private async Task SeedAdminAsync() private async Task SeedAdminAsync()
@@ -49,7 +49,7 @@ public sealed class DbInitializer(
var options = adminSeedOptions.Value; var options = adminSeedOptions.Value;
if (string.IsNullOrWhiteSpace(options.Username) || string.IsNullOrWhiteSpace(options.Password)) if (string.IsNullOrWhiteSpace(options.Username) || string.IsNullOrWhiteSpace(options.Password))
{ {
logger.LogWarning("AdminSeed__Username/AdminSeed__Password не заданы — учётка администратора не создана"); logger.LogWarning("AdminSeed__Username/AdminSeed__Password not set — admin account not created");
return; return;
} }
@@ -68,11 +68,11 @@ public sealed class DbInitializer(
if (!createResult.Succeeded) if (!createResult.Succeeded)
{ {
throw new InvalidOperationException( throw new InvalidOperationException(
$"Не удалось создать администратора: {string.Join(", ", createResult.Errors.Select(e => e.Description))}"); $"Failed to create admin account: {string.Join(", ", createResult.Errors.Select(e => e.Description))}");
} }
await userManager.AddToRoleAsync(admin, RoleNames.Admin); await userManager.AddToRoleAsync(admin, RoleNames.Admin);
logger.LogInformation("Создана учётка администратора {Username}", options.Username); logger.LogInformation("Created admin account {Username}", options.Username);
} }
private async Task SeedClientAppsAsync(CancellationToken cancellationToken) private async Task SeedClientAppsAsync(CancellationToken cancellationToken)
@@ -83,7 +83,7 @@ public sealed class DbInitializer(
var path = Path.Combine(AppContext.BaseDirectory, "seed", "client-apps.json"); var path = Path.Combine(AppContext.BaseDirectory, "seed", "client-apps.json");
if (!File.Exists(path)) if (!File.Exists(path))
{ {
logger.LogWarning("Файл сида каталога приложений не найден: {Path}", path); logger.LogWarning("Client app catalog seed file not found: {Path}", path);
return; return;
} }
@@ -94,7 +94,7 @@ public sealed class DbInitializer(
{ {
if (!Enum.TryParse<OsPlatform>(entry.OperatingSystem, ignoreCase: true, out var os)) if (!Enum.TryParse<OsPlatform>(entry.OperatingSystem, ignoreCase: true, out var os))
{ {
logger.LogWarning("Неизвестная ОС '{Os}' в сиде каталога приложений — пропущено", entry.OperatingSystem); logger.LogWarning("Unknown OS '{Os}' in client app catalog seed — skipped", entry.OperatingSystem);
continue; continue;
} }
@@ -104,7 +104,7 @@ public sealed class DbInitializer(
} }
await dbContext.SaveChangesAsync(cancellationToken); await dbContext.SaveChangesAsync(cancellationToken);
logger.LogInformation("Засеян каталог приложений: {Count} записей", entries.Count); logger.LogInformation("Seeded client app catalog: {Count} entries", entries.Count);
} }
private sealed record ClientAppSeedEntry( private sealed record ClientAppSeedEntry(