﻿
{"id":11242,"date":"2019-06-18T19:08:02","date_gmt":"2019-06-18T19:08:02","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=11242"},"modified":"2019-06-18T19:08:02","modified_gmt":"2019-06-18T19:08:02","slug":"asp-net-core-3-0-logging","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-3-0-logging\/","title":{"rendered":"Asp.NET Core 3.0 &#8211; Logging"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Nas\u0131l ki; bir kaya par\u00e7as\u0131 tarihsel bir muammay\u0131 g\u00fcn\u00fcm\u00fcze ayd\u0131nlat\u0131c\u0131 bir bilgi ta\u015f\u0131yabiliyorsa, nas\u0131l ki; insan v\u00fccudundaki bir reaksiyon sa\u011fl\u0131\u011f\u0131na dair ge\u00e7mi\u015fini g\u00f6zler \u00f6n\u00fcne serebiliyorsa yahut nas\u0131l ki; be\u015feri hayatta devletler vatanda\u015flar\u0131 hakk\u0131nda istedi\u011fi zaman istedi\u011fi -zamana dair- verilere eri\u015febiliyorsa i\u015fte bunlara benzer bir \u015fekilde herhangi bir yaz\u0131l\u0131mda yar\u0131nlar\u0131na, ge\u00e7mi\u015fine dair izler b\u0131rakabilmelidir&#8230; En nihayetinde yukar\u0131da verilen bu \u00f6rnekler nihai olarak t\u00fcm varolu\u015fun d\u00fcn\u00fcne dair bizlere b\u0131rakt\u0131\u011f\u0131 ayd\u0131nlat\u0131c\u0131 bilgilerdir. \u0130\u015fte biz yaz\u0131l\u0131mc\u0131lar, nesnenin yahut olaylar\u0131n tabiat\u0131nda olan do\u011fal iz mekanizmalar\u0131n\u0131 irademizle yaz\u0131l\u0131mlar\u0131m\u0131za i\u015fleyerek sistemin i\u015fleyi\u015fini ad\u0131m ad\u0131m kay\u0131t alt\u0131na almakta ve bu yap\u0131lan\u0131da &#8220;Raporlama&#8221; ya da birba\u015fka deyi\u015fle &#8220;Loglama&#8221; \u015feklinde ifade ederek, yaz\u0131l\u0131m\u0131n bug\u00fcn\u00fcndeki i\u015fleyi\u015fi hakk\u0131nda yar\u0131nlara bilgiler ta\u015f\u0131maktay\u0131z.<\/p>\n<p>Asl\u0131nda yukar\u0131daki giri\u015fin biraz derin oldu\u011funu d\u00fc\u015f\u00fcnebilirsiniz, hatta aran\u0131zdan b\u00f6yle bir konuya abart\u0131l\u0131 bir giri\u015f oldu\u011funu dahi s\u00f6yleyenler olabilir. T\u00fcm bu fikirlere a\u00e7\u0131k ve sayg\u0131l\u0131 oldu\u011fum kadar bir o kadar da susam\u0131\u015f oldu\u011fumu bilmenizi isterim. Lakin bunun yan\u0131nda da \u015funu ifade etmek isterim ki, \u015fahsen ben bir konunun ya kuramsal ya da kavramsal olarak alt\u0131n\u0131 doldurmad\u0131k\u00e7a yapt\u0131\u011f\u0131m i\u015fin dayand\u0131\u011f\u0131 kolonlardan birinin eksik oldu\u011funu d\u00fc\u015f\u00fcnmekteyim. &#8220;Evet&#8221; birazdan Asp.NET Core mimarisinde Logging mekanizmas\u0131na dair &#8211;<em>nas\u0131l uygulan\u0131r?<\/em>&#8211; sorusunun cevab\u0131 i\u00e7in hususi didiniyor olaca\u011f\u0131z ama bunun yan\u0131nda kavramsal a\u00e7\u0131dan raporlama yahut loglama terimlerini hi\u00e7 bilmeyenler i\u00e7in m\u00fcmk\u00fcn mertebe olay\u0131 tabiatla ili\u015fkilendirmenin eksiltici yan\u0131n\u0131 g\u00f6rmemekteyim.<\/p>\n<p>Her neyse&#8230;<\/p>\n<p>\u015eunu unutmamak gerekiyor ki loglama bir stratejidir. Yani sistemin herhangi bir &#8216;T&#8217; zaman\u0131nda yapt\u0131\u011f\u0131 i\u015flemleri ad\u0131m ad\u0131m kayda almas\u0131d\u0131r. Ve yine herhangi bir &#8216;T + n&#8217; zamanda ise ge\u00e7mi\u015fe dair -s\u00fcre\u00e7te neler olmu\u015f?- sorusuna kar\u015f\u0131l\u0131k metinsel ya da say\u0131sal istatiksel bilgiler veren mekanizmay\u0131 in\u015fa etmektir. \u0130\u015fte bizler bu stratejiyi bir\u00e7ok y\u00f6ntemle icra edebilece\u011fimiz gibi bu i\u00e7eri\u011fimizde bunlardan (iyi k\u00f6t\u00fc) birini ele alaca\u011f\u0131z. Asp.NET Core mimarisinde Logging mekanizmas\u0131n\u0131&#8230;<\/p>\n<h3>Asp.NET Core \u0130le Logging<\/h3>\n<p>Bir uygulama i\u00e7in olmazsa olmaz \u00f6zelliklerinden birisi olan log mekanizmas\u0131, Asp.NET Core mimarisinde Logging framework\u00fc ile mod\u00fcler bir \u015fekilde uygulamaya dahil edilebilmekte ve sisteme entegresyonu ger\u00e7ekle\u015ftirilebilmektedir.<\/p>\n<blockquote><p>Asp.NET Core mimarisinde Logging ara\u00e7lar\u0131na <span style=\"color:green;font-size:13px;\">Microsoft.Extensions.Logging<\/span> k\u00fct\u00fcphanesinden eri\u015filmektedir.<\/p><\/blockquote>\n<p>Tabi devam etmeden \u00f6nce \u015funu belirtmek isterim ki, Asp.NET Core mimarisindeki dahili Logging mekanizmas\u0131 haz\u0131r sistemler i\u00e7erisinde genellikle kullan\u0131lan bir mekanizmaya sahip olmakla beraber olmazsa olmaz \u015feklinde d\u00fc\u015f\u00fcn\u00fclecek i\u015flevselli\u011fide sahip de\u011fildir. Bizler bu i\u00e7eri\u011fimizde bir Asp.NET Core uygulamas\u0131nda log i\u015flemleri i\u00e7in dahili olan Logging k\u00fct\u00fcphanesini sadece inceleyecek ve nas\u0131l entegrasyonun ger\u00e7ekle\u015ftirilece\u011fi \u00fczerine konu\u015faca\u011f\u0131z. Zira yaz\u0131l\u0131m projelerinde loglama mekanizmalar\u0131n\u0131 ilgili ekibin\/geli\u015fticinin ihtiyaca d\u00f6n\u00fck bir \u015fekilde kendilerinin tasarlamas\u0131 ve in\u015fa etmesi taraf\u0131mca tavsiye edilmektedir.<\/p>\n<p>Evet&#8230; \u015eimdi konumuza d\u00f6nersek e\u011fer Logging k\u00fct\u00fcphanesinde kullanaca\u011f\u0131m\u0131z enstr\u00fcnmanlar\u0131 inceleyerek ba\u015flayal\u0131m;<\/p>\n<ul>\n<li>\n<strong>ILogger<\/strong><br \/>\nLoglama sorumlulu\u011funu \u00fcstlenecek olan s\u0131n\u0131f\u0131n imzas\u0131d\u0131r.\n<\/li>\n<li>\n<strong>Logger<\/strong><br \/>\nLoglama sorumlulu\u011funu \u00fcstlenecek olan s\u0131n\u0131ft\u0131r.\n<\/li>\n<li>\n<strong>ILoggerProvider<\/strong><br \/>\nSa\u011flay\u0131c\u0131 sorumlulu\u011funu \u00fcstlenecek olan s\u0131n\u0131f\u0131n imzas\u0131d\u0131r.\n<\/li>\n<li>\n<strong>LoggerProvider<\/strong><br \/>\nSa\u011flay\u0131c\u0131 sorumlulu\u011funu \u00fcstlenecek olan s\u0131n\u0131ft\u0131r. G\u00f6revi &#8220;Logger&#8221; s\u0131n\u0131f\u0131n\u0131 \u00fcretmektir.\n<\/li>\n<li>\n<strong>ILoggerFactory<\/strong><br \/>\nLog mekanizmas\u0131n\u0131 uygulamaya dahil eden ve g\u00f6rev olarakta &#8220;LoggerProvider&#8221; s\u0131n\u0131f\u0131n\u0131 \u00fcreterek sisteme dahil eden aray\u00fczd\u00fcr. Esas\u0131nda Asp.NET Core \u00e7ekirde\u011fi bu aray\u00fcz\u00fc implement eden <em>&#8220;LoggerFactory&#8221;<\/em> isimli bir s\u0131n\u0131f bar\u0131nd\u0131rmaktad\u0131r. Runtime&#8217;da uygulama bu s\u0131n\u0131ftan olu\u015fturulan bir instance \u00fczerinden gerekli tan\u0131mlamalar\u0131 sa\u011flamaktad\u0131r.\n<\/li>\n<\/ul>\n<h3>\u00d6rnek Uygulama<\/h3>\n<p>\u015eimdi yukar\u0131daki yap\u0131lanmay\u0131 g\u00f6z \u00f6n\u00fcne alarak bir \u00f6rnek icra edelim. \u0130lgili i\u00e7eri\u011fimizde Asp.NET Core 3.0 \u00e7ekirde\u011finde bir uygulama ile birlikte MVC deseni kullan\u0131lacakt\u0131r.<\/p>\n<ul>\n<li>\n<strong><em style=\"color: orange;\">Ad\u0131m 1<\/em><\/strong><br \/>\n\u0130lk olarak loglama sorumlulu\u011funu \u00fcstlenecek olan &#8220;Logger&#8221; s\u0131n\u0131f\u0131n\u0131 olu\u015ftural\u0131m.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Logger : ILogger\r\n    {\r\n        IHostingEnvironment _hostingEnvironment;\r\n        public Logger(IHostingEnvironment hostingEnvironment) =&gt; _hostingEnvironment = hostingEnvironment;\r\n        public IDisposable BeginScope&lt;TState&gt;(TState state) =&gt; null;\r\n        public bool IsEnabled(LogLevel logLevel) =&gt; true;\r\n        public async void Log&lt;TState&gt;(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func&lt;TState, Exception, string&gt; formatter)\r\n        {\r\n            using (StreamWriter streamWriter = new StreamWriter($&quot;{_hostingEnvironment.ContentRootPath}\/log.txt&quot;, true))\r\n            {\r\n                await streamWriter.WriteLineAsync($&quot;Log Level : {logLevel.ToString()} | Event ID : {eventId.Id} | Event Name : {eventId.Name} | Formatter : {formatter(state, exception)}&quot;);\r\n                streamWriter.Close();\r\n                await streamWriter.DisposeAsync();\r\n            }\r\n        }\r\n    }\r\n<\/pre>\n<p>Dikkat ederseniz e\u011fer &#8220;Logger&#8221; s\u0131n\u0131f\u0131 &#8220;ILogger&#8221; aray\u00fcz\u00fcn\u00fc implemente etmekte ve &#8220;Log&#8221; isimli generic metot i\u00e7erisinde proje dizininde bulunan bir &#8220;.txt&#8221; uzant\u0131l\u0131 dosyaya gerekli loglamay\u0131 ger\u00e7ekle\u015ftirmektedir.\n<\/li>\n<li>\n<strong><em style=\"color: orange;\">Ad\u0131m 2<\/em><\/strong><br \/>\nSa\u011flay\u0131c\u0131 sorumlulu\u011funu \u00fcstlenecek olan &#8220;LoggerProvider&#8221; s\u0131n\u0131f\u0131n\u0131 \u00fcretelim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class LoggerProvider : ILoggerProvider\r\n    {\r\n        public IHostingEnvironment _hostingEnvironment;\r\n        public LoggerProvider(IHostingEnvironment hostingEnvironment) =&gt; _hostingEnvironment = hostingEnvironment;\r\n        public ILogger CreateLogger(string categoryName) =&gt; new Logger(_hostingEnvironment);\r\n        public void Dispose() =&gt; throw new NotImplementedException();\r\n    }\r\n<\/pre>\n<p>Buradaki \u00f6nemli nokta, &#8220;CreateLogger&#8221; metodu i\u00e7erisinde yukar\u0131da olu\u015fturdu\u011fumuz &#8220;Logger&#8221; s\u0131n\u0131f\u0131ndan bir nesne \u00fcretilip geriye d\u00f6nd\u00fcr\u00fclmesidir.\n<\/li>\n<li>\n<strong><em style=\"color: orange;\">Ad\u0131m 3<\/em><\/strong><br \/>\nOlu\u015fturdu\u011fumuz yap\u0131lar neticesinde yukar\u0131daki &#8220;LoggerProvider&#8221; isimli sa\u011flay\u0131c\u0131 s\u0131n\u0131f\u0131 arac\u0131l\u0131\u011f\u0131yla &#8220;Logger&#8221; s\u0131n\u0131f\u0131ndan bir instance&#8217;i uygulamaya dahil etmemiz gerekmektedir. Bunun i\u00e7in &#8220;Startup.cs&#8221; dosyas\u0131ndaki &#8220;Configure&#8221; metodunda a\u015fa\u011f\u0131daki \u00e7al\u0131\u015fmay\u0131 yapmam\u0131z gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public Microsoft.AspNetCore.Hosting.IHostingEnvironment _hostingEnvironment { get; set; }\r\n        public Startup(Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment) =&gt; _hostingEnvironment = hostingEnvironment;\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddControllersWithViews();\r\n        }\r\n        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)\r\n        {\r\n            loggerFactory.AddProvider(new LoggerProvider(_hostingEnvironment));\r\n            if (env.IsDevelopment())\r\n                app.UseDeveloperExceptionPage();\r\n            app.UseRouting();\r\n            app.UseEndpoints(_ =&gt; _.MapControllerRoute(&quot;default&quot;, &quot;{controller=Home}\/{action=Index}\/{id?}&quot;));\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer &#8220;Configure&#8221; metoduna &#8220;ILoggerFactory&#8221; parametresi eklenmi\u015ftir. \u0130lgili parametreye uygulama \u00e7ekirde\u011finden Runtime&#8217;da bir adet &#8220;LoggerFactory&#8221; instance&#8217;\u0131 ba\u011flanacak ve bu instance \u00fczerinden sisteme &#8220;LoggerProvider&#8221; nesnesi ile log mekanizmas\u0131 entegre edilmi\u015f olacakt\u0131r.\n<\/li>\n<li>\n<strong><em style=\"color: orange;\">Ad\u0131m 4<\/em><\/strong><br \/>\nArt\u0131k uygulamada hali haz\u0131rda kullan\u0131lmay\u0131 bekleyen bir log mekanizmas\u0131 mevcuttur. \u015eimdi yapmam\u0131z gereken ilgili Controller&#8217;da Dependency Injection ile &#8220;Logger&#8221; nesnesine talepte bulunmak ve istenilen noktada bu nesne \u00fczerinden gerekli loglar\u0131 almakt\u0131r.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class HomeController : Controller\r\n    {\r\n        public ILogger&lt;HomeController&gt; _logger;\r\n        public HomeController(ILogger&lt;HomeController&gt; logger) =&gt; _logger = logger;\r\n        public IActionResult Information()\r\n        {\r\n            _logger.LogInformation(&quot;Information mesaj\u0131...&quot;);\r\n            return View();\r\n        }\r\n        public IActionResult Error()\r\n        {\r\n            _logger.LogError(&quot;Error mesaj\u0131...&quot;);\r\n            return View();\r\n        }\r\n        public IActionResult Warning()\r\n        {\r\n            _logger.LogWarning(&quot;Warning mesaj\u0131...&quot;);\r\n            return View();\r\n        }\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funda g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere &#8220;Home(Controller).cs&#8221; s\u0131n\u0131f\u0131 i\u00e7erisinde &#8220;Information&#8221;, &#8220;Error&#8221; ve &#8220;Warning&#8221; olmak \u00fczere \u00fc\u00e7 farkl\u0131 action \u00fczerinde farkl\u0131 log fonksiyonlar\u0131 \u00e7a\u011fr\u0131lm\u0131\u015ft\u0131r. Uygulamaya derlenip, \u00e7al\u0131\u015ft\u0131r\u0131ld\u0131\u011f\u0131 vakit yukar\u0131daki actionlara yap\u0131lan birer request neticesinde uygulama dizininde olu\u015fturulan &#8220;log.txt&#8221; dosyas\u0131n\u0131n i\u00e7eri\u011fi a\u015fa\u011f\u0131daki gibi doldurulmu\u015f olacakt\u0131r.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging.jpg\" alt=\"Asp.NET Core - Logging\" width=\"1595\" height=\"494\" class=\"aligncenter size-full wp-image-11281\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging.jpg 1595w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging-300x93.jpg 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging-768x238.jpg 768w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/06\/Asp.NET-Core-Logging-1024x317.jpg 1024w\" sizes=\"auto, (max-width: 1595px) 100vw, 1595px\" \/><\/a>\n<\/li>\n<\/ul>\n<p>Nihai olarak; hangi platform yahut proje olursa olsun bir uygulaman\u0131n olmazsa olmaz ana organlar\u0131ndan biri olan log mekanizmas\u0131 sisteme uygun e\u015flik edebilecek \u015fekilde tasarlanmal\u0131 ve yukar\u0131da belirtti\u011fim gibi tekrar ifade ediyorum ki m\u00fcmk\u00fcnse ilgili proje ihtiya\u00e7lar\u0131na \u00f6zel bir log mekanizmas\u0131 ortaya koyulmal\u0131d\u0131r. Tabi isterseniz de bu i\u00e7eri\u011fimizde oldu\u011fu gibi haz\u0131r olan Logging mekanizmas\u0131yla birlikte piyasada bulunan bir\u00e7ok haz\u0131r log mekanizmas\u0131n\u0131 uygulamalar\u0131n\u0131za entegre ederek kullanabilirsiniz.<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Nas\u0131l ki; bir kaya par\u00e7as\u0131 tarihsel bir muammay\u0131 g\u00fcn\u00fcm\u00fcze ayd\u0131nlat\u0131c\u0131 bir bilgi ta\u015f\u0131yabiliyorsa, nas\u0131l ki; insan v\u00fccudundaki bir reaksiyon sa\u011fl\u0131\u011f\u0131na dair ge\u00e7mi\u015fini g\u00f6zler \u00f6n\u00fcne serebiliyorsa yahut nas\u0131l ki; be\u015feri hayatta devletler vatanda\u015flar\u0131 hakk\u0131nda&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":9596,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2898],"tags":[2891,2893,2897,2895,2894,2896,2892],"class_list":["post-11242","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-asp-net-core-3-0","tag-asp-net-core-3-0","tag-ilogger","tag-iloggerfactory","tag-iloggerprovider","tag-logger","tag-loggerprovider","tag-logging"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=11242"}],"version-history":[{"count":40,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11242\/revisions"}],"predecessor-version":[{"id":11283,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11242\/revisions\/11283"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/9596"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=11242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=11242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=11242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}