Asp.net core yazılarında daha önce asp.net core'a giriş yapmıştık ve devamında build-in container'dan bahsetmiştik. Kısaca tanımlayacak olursak; asp.net core microsoft tarafından open-source olarak geliştirilmiş asp.net'e göre daha modüler bir cross platform web kütüphanesidir.
Bu yazıda ise asp.net core'da logging nedir nasıl yapılır inceleyeceğiz.
Log bir uygulama için olmazsa olmazların başında gelir ve projeler için oldukça önemli bir feature'dır. Yukarıda da yazdığımız gibi asp.net core modüler bir framework dür ve logging de asp.net core uygulamanızda kolayca ayağa kaldırabileceğiniz bir service olarak yer almaktadır.
Öncelikle Vs'da AspCoreLogging adında bir web-api projesi oluşturalım. Eğer oluşturduğunuz proje asp.net core 1.x versiyonu ise projemize Microsoft.Extensions.Logging dll'ini referans olarak eklememiz gerekmekte ama eğer asp.net core 2.x versiyonlarından birine ait ise default olarak gelmekte.
Microsoft.Extensions.Logging namespace'i bizim asp.net core içerisinde logging için gerekli olan sınıf&arayüz ve metotları vs. içermekte.
Bunlara bakacak olursak;
- ILogger
- ILoggingFactory
- LoggingFactory
- ILoggingProvider
built-in class ve interface'leri bu namespace altında bulunmakta.
ILogger interface'i kullanacağımız log-storage'a log kaydetmemizi sağlayan gerekli metotları içerir.
public interface ILogger
{
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
bool IsEnabled(LogLevel logLevel);
IDisposable BeginScope<TState>(TState state);
}
Geliştireceğimiz custom-logger'ı oluşturmak için ILogger interface'ine ait metotları extend edip metotlarını kullanacağız.
ILoggerFactory interface'i ise yukarıda bahsettiğimiz ILogger arayüzünü extend eden custom-logger'ın instance'ını oluşturmada kullanacağımız interface'dir.
public interface ILoggerFactory : IDisposable
{
ILogger CreateLogger(string categoryName);
void AddProvider(ILoggerProvider provider);
}
Asp.net Core içerisinde yukarıda bahsettiğimiz ILoggerFactor interface'ini implement eden LoggerFactory sınıfı bulunmakta. Runtime'da asp.net core framework bu sınıfa ait instance yaratarak default gelen kendi built-in IoC container'ına register eder.
ILoggingProvider interface'i istenilen logging kategorisindeki gerekli logger sınıflarını yaratır ve yönetir. Framework içerisinde default olarak gelen provider'lar şu şekildedir;
- Console
- Debug
- EventSource
- EventLog
- TraceSource
- Azure App Service
public interface ILoggerProvider : IDisposable
{
ILogger CreateLogger(string categoryName);
}
Bu interface'i bize projede kullanacağımız customLogger'ın instance'ını oluşturmamızı sağlayacak sınıfı tanımlarken kullanacağız.
File Logging Impl.
Şimdi ise yukarıda bahsettiğimiz adımları fileLogging için geliştirmeye başlayalım. İlk olarak projemize ILogger interface'ini implement eden FileLogger sınıfını aşağıdaki gibi tanımlayalım.
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = string.Format("{0}: {1} - {2}", logLevel.ToString(), eventId.Id, formatter(state, exception));
WriteMessageToFile(message);
}
private static void WriteMessageToFile(string message)
{
const string filePath = "C:\\AspCoreFileLog.txt";
using (var streamWriter = new StreamWriter(filePath, true))
{
streamWriter.WriteLine(message);
streamWriter.Close();
}
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
Yukarıda da görüldüğü üzre projede üretilen loglar server'da bulunan C sürücüsünde AspCoreFileLog.txt adındaki dosyaya yazılacak. FileLogger sınıfını oluşturduktan sonra bu sınıfı projemize inject etmemizi sağlayacak olan ILoggerProvider interface'ini implement edecek olan FileLogProvider sınıfını tanımlayalım.
public class FileLogProvider : ILoggerProvider
{
public ILogger CreateLogger(string category)
{
return new FileLogger();
}
public void Dispose()
{
}
}
FileLogProvider sınıfı proje içerisinde tanımlanan logger'ın instance'ının create edilmesini sağlar.
Son adım olarak yukarıda tanımladığımız FileLogProvider'ı Startup.cs sınıfında bulunan Configure metodunda loggerFactory'nin provider'larına eklememiz kalıyor. Bu işlemi de aşağıdaki gibi startup.cs içerisinde yapalım.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//provider'ı ekledik
loggerFactory.AddProvider(new FileLogProvider());
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
Geliştirmemiz bitti artık yazdığımız kodları test edebiliriz. Bunun için ILogger interface'inin projede yer alan aşağıdaki controller'a constructor seviyesinde inject ettikten sonra end-point'lere sırasıyla browser üzerinden get işlemi yapalım.
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly ILogger<ValuesController> _logger;
public ValuesController(ILogger<ValuesController> logger)
{
this._logger = logger;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
_logger.LogInformation("Hi from logger !");
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
throw new NullReferenceException("Null exp. from myApp !");
return "value";
}
}
Http-Get request'i yolladıktan sonra C:\\AspCoreFileLog.txt adresine gittiğimizde içerisinde hem framework'ün ürettiği hemde bizim controller metodunda yazdırdığımız log row'larını görebilirsiniz.
Yazının başında da bahsettiğimiz üzre Asp.Net Core'da logging moduler bir şekilde ayrı bir service olarak gelmekte ve fileLog dışında database, flat file yada diğer log target türlerini kullanarak logging'i genişletebilirsiniz. Bunun dışında NLog, Serilog yada .net core desteği olan third-party logging provider'ları da kullanabilirsiniz.