Asked by:
webapi logging with serilog help

Question
-
User-154169686 posted
Hi
I am using serilog and SEQ in my project web api. I am new to both.
1) How can I make sure every time I write error, information, debug it should contain ClassName.Method Name. I know I have to create Enrich but not sure how to get ClassName.Method Name
2) I have created Logger class which has static method which return me logger. Is there any better way such as Dependency inject. so that I can use in multiple classes
public partial class Logger
{
public static ILogger ConfigureLogging(){
return Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.Enrich.WithProperty("Host", host)
.Enrich.FromLogContext()
.WriteTo.Seq(serilogUrl)
.CreateLogger();}
Thursday, September 20, 2018 6:41 AM
All replies
-
User1120430333 posted
I use Serilog for .NET Core WebAPI and I use Log4net for non WebAPI.
So what type of WebAPI are you using?
I use Serilog in the .NET Core WebAPI global exception handling to log the exception, and I do the same thing with GEH for non Core WebAPI and doing the logging with Log4net, which means there are no try/catches in the WebAPI(s) or in any code a WebAPI(s) uses. The stack trace on an exception thrown caught by the GEH gives the class name, method name and like number where the execution is thrown. I just log exception errors in either case of what WebAPI type is being used.
Yes, you can do a lot of things with Serilog, like capturing information for debugging, error, informational, statistics, usage and all kinds of logging. I took a Pluralsight course on Serilog. I can tell you now that you don't have Serilog implemented to do it. It may be best that you take the $39 Pluralsight course on Serilog if you what to do some logging other than error logging.
Thursday, September 20, 2018 1:23 PM -
User-154169686 posted
Hi
Thanks for reply. I found a solution of using DI and I am using Autofac.
However, I am still not sure how to get ClassName.Method name everytime I write a error usin serilog.
Regards,
Monday, September 24, 2018 6:34 AM -
User1120430333 posted
Hi
Thanks for reply. I found a solution of using DI and I am using Autofac.
However, I am still not sure how to get ClassName.Method name everytime I write a error usin serilog.
Regards,
Here is how I use Serilog to do global exception handling in WebAPI Core 2, which means there are no try/catch in any WebAPI code or any DLL code the WebAPI is referencing.
https://stackify.com/csharp-catch-all-exceptions/
using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Serilog; namespace ProgMgmntCore2Api { public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseSerilog(); } }
using System.Net; using DAL; using Entities; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; namespace ProgMgmntCore2Api { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger(); } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //DAL services.AddTransient<IDaoProject, DaoProject>(); services.AddTransient<IDaoTask, DaoTask>(); services.AddTransient<IDaoCache, DaoCache>(); //Configuration services.Configure<ConnectionStrings>(Configuration.GetSection("ConnectionStrings")); // Add framework services. services.AddMvc(options => { options.Filters.Add(new ErrorHandlingFilter(Configuration)); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory, IApplicationLifetime appLifetime) { //this is used by Postmon and Global Exception handelling to show exception. app.UseExceptionHandler( options => { options.Run( async context => { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "text/html"; var ex = context.Features.Get<IExceptionHandlerFeature>(); if (ex != null) { var err = $"<h1>Error: {ex.Error.Message} </h1>{ex.Error.StackTrace } {ex.Error.InnerException.Message} "; await context.Response.WriteAsync(err).ConfigureAwait(false); } }); } ); loggerfactory.AddSerilog(); app.UseHttpsRedirection(); app.UseMvc(); } } }
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Configuration; using Serilog; namespace ProgMgmntCore2Api { public class ErrorHandlingFilter : ExceptionFilterAttribute { private readonly IConfiguration _configuration; public ErrorHandlingFilter(IConfiguration configuration) { _configuration = configuration; } public override void OnException(ExceptionContext context) { var log = new LoggerConfiguration().ReadFrom.Configuration(_configuration).CreateLogger(); var exception = context.Exception; if (exception.InnerException != null) { log.Error("Message = " + exception.Message + " Inner.Exception.Message = " + exception.InnerException.Message + " Stack Trace = " + exception.StackTrace); } else { log.Error("Message = " + exception.Message + " Stack Trace = " + exception.StackTrace); } context.ExceptionHandled = false; //optional } } }
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Configuration; using Serilog; namespace ProgMgmntCore2Api { public class ErrorHandlingFilter : ExceptionFilterAttribute { private readonly IConfiguration _configuration; public ErrorHandlingFilter(IConfiguration configuration) { _configuration = configuration; } public override void OnException(ExceptionContext context) { var log = new LoggerConfiguration().ReadFrom.Configuration(_configuration).CreateLogger(); var exception = context.Exception; if (exception.InnerException != null) { log.Error("Message = " + exception.Message + " Inner.Exception.Message = " + exception.InnerException.Message + " Stack Trace = " + exception.StackTrace); } else { log.Error("Message = " + exception.Message + " Stack Trace = " + exception.StackTrace); } context.ExceptionHandled = false; //optional } } }
2018-08-04 16:10:42.699 -04:00 [Error] An exception was thrown attempting to execute the error handler. System.NullReferenceException: Object reference not set to an instance of an object. at ProgMgmntCore2Api.Startup.<>c.<<Configure>b__5_1>d.MoveNext() in C:\Projects\ProgMgmntCore2\ProgMgmntCore2Api\Startup.cs:line 62 --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context) 2018-08-04 16:10:42.704 -04:00 [Error] Connection id ""0HLFQ8P67SHVQ"", Request id ""0HLFQ8P67SHVQ:00000005"": An unhandled exception was thrown by the application. System.Exception: Cache Test
at DAL.DaoCache.GetCache() in
C:\Projects\ProgMgmntCore2\DAL\DaoCache.cs:line 34 at ProgMgmntCore2Api.Controllers.CacheController.Get_Cache() in C:\Projects\ProgMgmntCore2\ProgMgmntCore2Api\Controllers\CacheController.cs:line 24 at lambda_method(Closure , Object , Object[] ) at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters) at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ExceptionContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)Monday, September 24, 2018 7:25 PM