Microsoft Owin Logging - Web Api 2 - How to Create a Logger?

I'm trying to add a log to my application using Web Api 2 and Owin, so I started using Microsoft Owin Logging, which requires ILogger and ILoggerFactory , which was implemented, and it works fine when I need to register something inside the STARTUP or any of the Owin middleware components.

For example, when I use the Startup method, I can create a logger using:

  public void Configuration(IAppBuilder app) { // Creates configuration var configuration = new HttpConfiguration(); // Configure WebApi Settings WebApiConfig.Register(configuration); app.SetLoggerFactory(new OwinLog4NetLoggerFactory("Default")); var logger = app.CreateLogger<Startup>(); logger.WriteInformation("test log"); // Enabled WebApi in OWIN app.UseWebApi(configuration); } 

Where "OwinLog4NetLoggerFactory" is my usual implementation of ILoggerFactory.

So far, so good ... but ... How can I create a registrar when I am in the actual web api method? ... I tried to access Request.GetOwinEnvironment() , and the logger factory in the dictionary.

For instance:

 public class AccountController : ApiController { public int Get(int id) { // Create logger here return id + 1; } } 

I know that I can create a static class with a link to a Logger factory or even Injection to add a registrar to the api controller, but this seems too complicated for what should already be there.

Any ideas would be appreciated.

+5
source share
3 answers

I would recommend writing your middleware so that you can register outside the controller:

 public class LoggingMiddleware : OwinMiddleware { public LoggingMiddleware(OwinMiddleware next) : base(next) { } public override async Task Invoke(IOwinContext context) { //handle request logging await Next.Invoke(context); //handle response logging } } 

Then in the Startup class:

 public class Startup { // ReSharper disable once UnusedMember.Global public void Configuration(IAppBuilder appBuilder) { HttpConfiguration config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); appBuilder.Use<LoggingMiddleware>(); appBuilder.UseWebApi(config); } } 

Then the request will go in, hit the registration code of the request in LoggingMiddleware, hit the controller code, and then the response will be written to LoggingMiddleware on the way back.

However, if all you want to do is send the object via middleware to the controller, you can use context.Set("loggingObject", loggingObject); in middleware and then var loggingObject = Request.GetOwinContext().Get<LoggerClass>("loggingObject"); in the controller.

Edit: fixed a}

+1
source

I would recommend using the Common.Logging library in your applications available on NuGet. Common.Logging gives you a common interface for using your preferred logging solution. It solves a lot of problems like yours. Here is an example of using Common.Logging with NLog:

In your controller, you will access it as follows:

 public class MyController : ApiController { private static readonly ILog Log = LogManager.GetLogger<MyController>(); public async Task<IHttpActionResult> Get([FromUri] int id) { Log.Debug("Called Get with id " + id.ToString()); return Ok(); } } 

Lift the latest Common.Logging.NLog package to NuGet (starting with this entry, it should be Common.Logging.NLog41). Then in your web.config you must configure Common.Logging to use your NLog configuration:

 <common> <logging> <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog41"> <arg key="configType" value="FILE" /> <arg key="configFile" value="~/NLog.config" /> </factoryAdapter> </logging> </common> 

Here are some additional links:

https://github.com/net-commons/common-logging

https://cmatskas.com/an-introduction-to-common-logging-api-2/

0
source

instead of adding registration codes in each method, I create a MessageLoggingHandler, which can be registered in Global.asax.cs once, and then logs each request and response.

Here is the code that I use, you can change according to your requirements:

First create a MessageHandler class that inherits from DelegationHandler:

  public abstract class MessageHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var corrId = Guid.NewGuid(); var requestMethod = request.Method.Method.ToString(); var requestUri = request.RequestUri.ToString(); var ipAddress = request.GetOwinContext().Request.RemoteIpAddress; var requestMessage = await request.Content.ReadAsByteArrayAsync(); await LogMessageAsync(corrId, requestUri, ipAddress, "Request", requestMethod, request.Headers.ToString(), requestMessage, string.Empty); var response = await base.SendAsync(request, cancellationToken); var responseMessage = await response.Content.ReadAsByteArrayAsync(); await LogMessageAsync(corrId, requestUri, ipAddress, "Response", requestMethod, response.Headers.ToString(), responseMessage, ((int)response.StatusCode).ToString() + "-" + response.ReasonPhrase); return response; } protected abstract Task LogMessageAsync(Guid CorrelationId, string APIUrl, string ClientIPAddress, string RequestResponse, string HttpMethod, string HttpHeaders, byte[] HttpMessage, string HttpStatusCode); } public class MessageLoggingHandler : MessageHandler { protected override async Task LogMessageAsync(Guid CorrelationId, string APIUrl, string ClientIPAddress, string RequestResponse, string HttpMethod, string HttpHeaders, byte[] HttpMessage, string HttpStatusCode) { // Create logger here //Do your logging here } } 

Then, in your Global.asax.cs file, you need to register the MessageLoggingHandler created above:

 GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageLoggingHandler()); 

Just keep in mind that this will log every request and response, there will be a full message. This can take up a lot of space very quickly (depending on the use of the API). Therefore, you may need to configure it (for example, keep records for a month or so or ignore 200-OK responses, etc.)

-1
source

All Articles