public IActionResult Get() { var userData = new User { Name = "Farhad", Family = "Zamani" }; _logger.LogInformation($"ValuesController called. Name:{userData.Name}, Family:{userData.Family}"); return Ok(); }
اگر بخواهیم مرتب سازی و یا فیلتری را بر روی Name و یا Family انجام دهیم، کار آسانی نخواهد بود و وقتگیر خواهد بود؛ زیرا باید با یک فیلد رشته ( message )، که تمامی لاگ درون آن قرار دارد، کار کنیم. اما با استفاده از قابلیت Structured Logging مربوط به Serilog، میتوانیم آبجکت userData را به ILogger پاس دهیم و پراپرتیهای آن را به صورت فیلدهای جدا نمایش دهیم.
برای این کار باید آبجکت موردنظر خود را درون {} قرار دهیم و قبل از نام متغییر آن یک @ قرار دهیم. بدین صورت: {userData@} و سپس دیتای موردنظر را در پارامتر دوم logger قرار دهیم.
_logger.LogInformation("ValuesController called. {@userData}", userData);
اگر کد نوشته شده مربوط به ثبت لاگ را به صورت زیر اصلاح کنیم:
public IActionResult Get() { var userData = new User { Name = "Farhad", Family = "Zamani" }; _logger.LogInformation("ValuesController called. {@userData}", userData); return Ok(); }
در پنل کیبانا به راحتی میتوان عملیات مرتب سازی و یا فیلتر را بر روی پراپرتیهای Name و Family انجام دهیم. اکنون اگر پنل کیبانا را تماشا کنید چنین لاگی را مشاهده میکنیم:
هرکدام از پراپرتیهای userData به صورت یک فیلد جدا ارسال شدهاست که به راحتی میتوانید مرتب سازی، فیلتر و... را بر روی هرکدام از فیلدها انجام دهید.
تنظیمات مربوط به Serilog:
public static void Main(string[] args) { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); Log.Logger = new LoggerConfiguration() .Enrich.FromLogContext() .Enrich.WithMachineName() .Filter.ByExcluding(Matching.FromSource("Serilog")) .Filter.ByExcluding(Matching.FromSource("System.Net.Http")) .Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore")) .WriteTo.Console() .ReadFrom.Configuration(configuration) .CreateLogger(); CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSerilog() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
فایل appsettings.json:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Serilog": { "WriteTo": [ { "Name": "Elasticsearch", "Args": { "nodeUris": "http://127.0.0.1:9200;", "indexFormat": "structuredlogging-{0:yyyy.MM}", "templateName": "structuredlogging" } } ] } }
فایل docker-compose برای اجرای Elasticsearch و Kibana:
version: '3' services: elasticsearch: container_name: elasticsearch image: elasticsearch:7.14.2 environment: - discovery.type=single-node ports: - 9200:9200 - 9300:9300 - 8200:8200 kibana: container_name: kibana image: kibana:7.14.2 ports: - 5601:5601
منابع استفاده شده: