PrimaLogger v2.0
Упрощенная обёртка над Serilog с конфигурацией через appsettings.json
или Web.config
. Поддержка Console, File и Elasticsearch с автоматическим определением совместимости.
Совместимость
PrimaLogger работает на всех современных и устаревших версиях .NET:
- ✅ .NET 8/7/6 - Полная поддержка (Minimal API)
- ✅ .NET 5 - Полная поддержка (Generic Host)
- ✅ .NET Core 3.1/3.0 - Полная поддержка (Generic Host)
- ✅ .NET Core 2.2/2.1 - Полная поддержка (WebHost)
- ✅ .NET Framework 4.8/4.7.x/4.6.1+ - Полная поддержка (классический ASP.NET)
- ✅ Mono 5.4+ - Поддерживается
- ✅ Xamarin - Поддерживается
Быстрый старт по версиям .NET
.NET 8/7/6 (Minimal API / Новый стиль)
Program.cs:
using PrimaLogger.Configuration;
var builder = WebApplication.CreateBuilder(args);
// или для консольных приложений:
// var builder = Host.CreateApplicationBuilder(args);
// Добавляем PrimaLogger
builder.Services.AddPrimaLogger(builder.Configuration);
// Остальные сервисы
builder.Services.AddControllers();
var app = builder.Build();
// Конфигурация pipeline
app.MapControllers();
app.Run();
appsettings.json:
{
"Logging": {
"PrimaLogger": {
"ApplicationName": "MyModernApp",
"Console": {
"Enabled": true,
"MinimumLevel": "Information"
}
}
}
}
.NET 5 (Generic Host)
Program.cs:
using Microsoft.Extensions.Hosting;
using PrimaLogger.Configuration;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// Добавляем PrimaLogger
services.AddPrimaLogger(hostContext.Configuration);
// Остальные сервисы
services.AddControllers();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
.NET Core 3.1/3.0 (Generic Host)
Program.cs:
using Microsoft.Extensions.Hosting;
using PrimaLogger.Configuration;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// Добавляем PrimaLogger
services.AddPrimaLogger(hostContext.Configuration);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
.NET Core 2.2/2.1 (WebHost)
Program.cs:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using PrimaLogger.Configuration;
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
// Добавляем PrimaLogger
services.AddPrimaLogger(hostContext.Configuration);
})
.UseStartup<Startup>();
}
.NET Framework 4.6.1+ (классический ASP.NET)
Установка пакетов:
<package id="PrimaLogger" version="2.0.2-compatible" />
<package id="Unity.AspNet.Mvc" version="5.11.1" />
<package id="Microsoft.Extensions.Configuration" version="2.1.0" />
<package id="Microsoft.Extensions.Configuration.Json" version="2.1.0" />
Web.config (секция appSettings):
<configuration>
<appSettings>
<add key="Logging:PrimaLogger:ApplicationName" value="MyLegacyApp" />
<add key="Logging:PrimaLogger:Console:Enabled" value="true" />
<add key="Logging:PrimaLogger:Console:MinimumLevel" value="Information" />
<add key="Logging:PrimaLogger:Console:OutputTemplate" value="[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" />
<add key="Logging:PrimaLogger:File:Path" value="App_Data/logs/app-.log" />
<add key="Logging:PrimaLogger:File:MinimumLevel" value="Debug" />
<add key="Logging:PrimaLogger:File:RollingInterval" value="Day" />
<add key="Logging:PrimaLogger:File:FileSizeLimitBytes" value="104857600" />
<add key="Logging:PrimaLogger:File:RetainedFileCountLimit" value="30" />
<add key="Logging:PrimaLogger:ErrorFile:Path" value="App_Data/logs/errors-.log" />
<add key="Logging:PrimaLogger:ErrorFile:MinimumLevel" value="Error" />
<add key="Logging:PrimaLogger:ErrorFile:RollingInterval" value="Day" />
<add key="Logging:PrimaLogger:ErrorFile:RetainedFileCountLimit" value="90" />
<add key="Logging:PrimaLogger:Elasticsearch:MinimumLevel" value="Debug" />
<add key="Logging:PrimaLogger:Elasticsearch:Options:Nodes:0" value="http://logs.prima-inform.ru:9200" />
<add key="Logging:PrimaLogger:Elasticsearch:Options:DataStreamName" value="dev-legacy-app" />
<add key="Logging:PrimaLogger:Elasticsearch:Options:BootstrapMethod" value="Silent" />
</appSettings>
</configuration>
Global.asax.cs (с Unity контейнером):
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Unity;
using Unity.AspNet.Mvc;
using Unity.Lifetime;
using PrimaLogger.Configuration;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Стандартная инициализация MVC
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Настройка DI
RegisterDependencies();
}
private void RegisterDependencies()
{
var container = new UnityContainer();
// Создаем конфигурацию из Web.config
var configBuilder = new ConfigurationBuilder()
.AddConfiguration(System.Configuration.ConfigurationManager.AppSettings);
var configuration = configBuilder.Build();
// Создаем ServiceCollection и добавляем PrimaLogger
var services = new ServiceCollection();
services.AddPrimaLogger(configuration);
// Регистрируем PrimaLogger сервисы в Unity
var serviceProvider = services.BuildServiceProvider();
container.RegisterInstance<Microsoft.Extensions.Logging.ILoggerFactory>(
serviceProvider.GetService<Microsoft.Extensions.Logging.ILoggerFactory>(),
new ContainerControlledLifetimeManager());
container.RegisterType(typeof(Microsoft.Extensions.Logging.ILogger<>),
typeof(Microsoft.Extensions.Logging.Logger<>),
new ContainerControlledLifetimeManager());
// Регистрируем ваши сервисы
container.RegisterType<IUserService, UserService>();
// Устанавливаем resolver
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Альтернативный вариант с Autofac:
// В Global.asax.cs
private void RegisterDependencies()
{
var builder = new ContainerBuilder();
// Создаем конфигурацию
var configBuilder = new ConfigurationBuilder()
.AddConfiguration(System.Configuration.ConfigurationManager.AppSettings);
var configuration = configBuilder.Build();
// Создаем ServiceCollection и добавляем PrimaLogger
var services = new ServiceCollection();
services.AddPrimaLogger(configuration);
// Регистрируем в Autofac
builder.Populate(services);
// Регистрируем контроллеры
builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
Конфигурация (универсальная для всех версий .NET Core/.NET 5+)
Минимальная конфигурация в appsettings.json:
{
"Logging": {
"PrimaLogger": {
"ApplicationName": "MyApp",
"Console": {
"Enabled": true,
"MinimumLevel": "Information"
}
}
}
}
Полная конфигурация в appsettings.json:
{
"Logging": {
"PrimaLogger": {
"ApplicationName": "UpdatersWebApp.Debug",
"CustomProperties": {
"Environment": "Development",
"Version": "1.0.0",
"ServiceName": "updaters-service"
},
"Console": {
"Enabled": true,
"MinimumLevel": "Information",
"OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
},
"File": {
"Path": "logs/app-.log",
"MinimumLevel": "Debug",
"OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}",
"RollingInterval": "Day",
"FileSizeLimitBytes": 104857600,
"RetainedFileCountLimit": 30,
"RollOnFileSizeLimit": true,
"Shared": false,
"Encoding": "UTF-8"
},
"ErrorFile": {
"Path": "logs/errors-.log",
"MinimumLevel": "Error",
"OutputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {SourceContext}: {Message:lj}{NewLine}{Exception}",
"RollingInterval": "Day",
"FileSizeLimitBytes": 104857600,
"RetainedFileCountLimit": 90,
"Encoding": "UTF-8"
},
"Elasticsearch": {
"MinimumLevel": "Debug",
"Options": {
"Nodes": [
"http://logs.prima-inform.ru:9200"
],
"DataStreamName": "dev-updaters-webapp",
"BootstrapMethod": "Silent",
"BufferOptions": {
"ConcurrentConsumers": 2,
"InboundBufferMaxSize": 100000,
"OutboundBufferMaxSize": 500
}
}
}
}
}
}
Использование в коде (одинаково для всех версий)
В контроллерах:
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Mvc; // или System.Web.Mvc для .NET Framework
public class UserController : Controller
{
private readonly ILogger<UserController> _logger;
public UserController(ILogger<UserController> logger)
{
_logger = logger;
}
public IActionResult Login(string userId)
{
_logger.LogInformation("User {UserId} attempting login", userId);
try
{
// Логика авторизации
_logger.LogDebug("Validating credentials for {UserId}", userId);
// Успешная авторизация
_logger.LogInformation("User {UserId} logged in successfully", userId);
return Ok();
}
catch (Exception ex)
{
_logger.LogError(ex, "Login failed for user {UserId}", userId);
return BadRequest("Login failed");
}
}
}
В сервисах:
public class UserService
{
private readonly ILogger<UserService> _logger;
public UserService(ILogger<UserService> logger)
{
_logger = logger;
}
public async Task ProcessUserAsync(string userId)
{
_logger.LogDebug("Starting user processing for {UserId}", userId);
using (_logger.BeginScope("UserId: {UserId}", userId))
{
try
{
await DoSomeWorkAsync(userId);
_logger.LogInformation("User processing completed successfully");
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process user");
throw;
}
}
}
}
В консольных приложениях:
public class Program
{
private static ILogger<Program> _logger;
public static async Task Main(string[] args)
{
// Настройка для консольного приложения
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddPrimaLogger(builder.Configuration);
var host = builder.Build();
_logger = host.Services.GetRequiredService<ILogger<Program>>();
_logger.LogInformation("Application starting");
try
{
await RunApplicationLogicAsync();
_logger.LogInformation("Application completed successfully");
}
catch (Exception ex)
{
_logger.LogFatal(ex, "Application terminated unexpectedly");
}
}
}
Структурированное логирование
Правильное использование параметров:
// ✅ Правильно - структурированные параметры
_logger.LogInformation("User {UserId} performed {Action} at {Timestamp}",
userId, "login", DateTime.UtcNow);
// ❌ Неправильно - строковая интерполяция
_logger.LogInformation($"User {userId} performed login at {DateTime.UtcNow}");
Использование Scopes для контекста:
using (_logger.BeginScope("RequestId: {RequestId}", requestId))
{
_logger.LogInformation("Processing request");
using (_logger.BeginScope("UserId: {UserId}", userId))
{
_logger.LogDebug("User-specific processing");
// Все логи будут содержать RequestId и UserId
}
}
Автоматическая совместимость с Elasticsearch
PrimaLogger автоматически определяет версию Elasticsearch и выбирает оптимальный режим работы:
Elasticsearch 7.9+ (Data Streams)
[INF] • Elasticsearch подключен: 7.17.0 (режим: Data Stream (Modern))
[INF] • Целевой индекс/поток: dev-updaters-webapp
Elasticsearch 7.3-7.8 (Legacy Index Templates)
[INF] • Elasticsearch подключен: 7.8.0 (режим: Index Template (Legacy))
[INF] • Целевой индекс/поток: dev-updaters-webapp-{yyyy.MM.dd}
Elasticsearch недоступен
[WAR] Elasticsearch недоступен: Cannot connect to any Elasticsearch nodes
[WAR] • URL: http://logs.prima-inform.ru:9200
[WAR] • Elasticsearch sink отключен
Различия в конфигурации между версиями .NET
Аспект |
.NET Core/.NET 5+ |
.NET Framework |
Файл конфигурации |
appsettings.json |
Web.config (appSettings) |
Инициализация |
services.AddPrimaLogger(configuration) |
Manual DI container setup |
Dependency Injection |
Встроенный |
Unity/Autofac/другой |
Hosting Model |
Generic Host / Minimal API |
Classical ASP.NET |
Пути к файлам |
logs/app-.log |
App_Data/logs/app-.log |
Справочник параметров конфигурации
PrimaLoggerConfig - основные настройки
Параметр |
Тип |
По умолчанию |
Описание |
ApplicationName |
string |
"webapp" |
Имя приложения, добавляется во все логи как свойство |
CustomProperties |
Dictionary<string, object> |
{} |
Дополнительные свойства, добавляемые во все логи |
Console |
ConsoleLoggerOptions |
null |
Настройки консольного вывода (отключен если null) |
File |
FileLoggerOptions |
null |
Настройки основного файла логов (отключен если null) |
ErrorFile |
FileLoggerOptions |
null |
Настройки файла только для ошибок (отключен если null) |
Elasticsearch |
ElasticsearchSinkOptions |
null |
Настройки Elasticsearch (отключен если null) |
ConsoleLoggerOptions - консольный вывод
Параметр |
Тип |
По умолчанию |
Описание |
Enabled |
bool |
true |
Включить/отключить консольный вывод |
MinimumLevel |
LogEventLevel |
Information |
Минимальный уровень для вывода в консоль |
OutputTemplate |
string |
"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}" |
Шаблон форматирования сообщений |
FileLoggerOptions - файловое логирование
Параметр |
Тип |
По умолчанию |
Описание |
Path |
string |
"logs/app-.log" |
Путь к файлу логов (поддерживает паттерны даты) |
MinimumLevel |
LogEventLevel |
Information |
Минимальный уровень для записи в файл |
OutputTemplate |
string |
"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}" |
Шаблон форматирования |
RollingInterval |
RollingInterval |
Day |
Интервал ротации: Infinite , Year , Month , Day , Hour , Minute |
FileSizeLimitBytes |
long? |
104857600 (100MB) |
Максимальный размер файла до ротации |
RollOnFileSizeLimit |
bool |
true |
Создавать новый файл при достижении лимита размера |
RetainedFileCountLimit |
int? |
31 |
Количество файлов для хранения (старые удаляются) |
Shared |
bool |
false |
Разрешить доступ к файлу из нескольких процессов |
Encoding |
Encoding |
UTF8 |
Кодировка файла |
ElasticsearchSinkOptions - настройки Elasticsearch
Параметр |
Тип |
По умолчанию |
Описание |
MinimumLevel |
LogEventLevel |
Information |
Минимальный уровень для отправки в Elasticsearch |
Options |
ElasticsearchLoggerOptions |
new() |
Детальные настройки подключения |
ElasticsearchLoggerOptions - подключение к Elasticsearch
Параметр |
Тип |
По умолчанию |
Описание |
Nodes |
List<Uri> |
["http://localhost:9200"] |
Список узлов Elasticsearch |
DataStreamName |
string |
"logs-myapp-default" |
Имя data stream (ES 7.9+) или префикс индекса (ES 7.3-7.8) |
BootstrapMethod |
BootstrapMethod |
Failure |
Режим создания индексов: None , Silent , Failure |
ApiKey |
string |
null |
API ключ для аутентификации |
Username |
string |
null |
Имя пользователя для Basic Auth |
Password |
string |
null |
Пароль для Basic Auth |
BufferOptions |
ElasticsearchBufferOptions |
null |
Настройки буферизации |
ElasticsearchBufferOptions - буферизация и производительность
Параметр |
Тип |
По умолчанию |
Описание |
Влияние |
ConcurrentConsumers |
int |
1 |
Количество потоков отправки |
Больше = быстрее отправка, больше нагрузка |
InboundBufferMaxSize |
int |
100000 |
Размер входящего буфера |
Больше = устойчивость к пикам, больше памяти |
OutboundBufferMaxSize |
int |
1000 |
Размер пакета для отправки |
Больше = меньше HTTP запросов, больше задержка |
Уровни логирования
Уровень |
Назначение |
Использование |
Пример |
Verbose |
Максимальная детализация |
Глубокая отладка |
_logger.LogTrace("Entering method with param {Param}", param) |
Debug |
Отладочная информация |
Разработка |
_logger.LogDebug("Processing user {UserId}", userId) |
Information |
Общая информация |
Нормальная работа |
_logger.LogInformation("User logged in successfully") |
Warning |
Предупреждения |
Потенциальные проблемы |
_logger.LogWarning("Invalid input received: {Input}", input) |
Error |
Ошибки |
Проблемы в работе |
_logger.LogError(ex, "Failed to process request") |
Fatal |
Критические ошибки |
Аварийное завершение |
_logger.LogCritical(ex, "Application crash") |