Search code examples
c#.net-coreserilog

How to add elapsed time in log using dotnet serilog?


I have a web application. And I wnant to log the response of serivces using logger.

public class PrivacyModel : PageModel
{
    private readonly ILogger<PrivacyModel> _logger;
    private readonly MyService _service;

    public PrivacyModel(ILogger<PrivacyModel> logger, MyService service)
    {
        _logger = logger;
        _service = service;
    }

    public void OnGet(string question)
    {
        var answer = service.Execute(question);
        _logger.LogInformation("{@a}", answer);
    }
}

The serilog logs this information. And writes api execution elapsed time logs as new log lines.

[12:01:43 INF] Starting web application
[12:01:44 INF] Now listening on: http://localhost:5000
[12:01:44 INF] Application started. Press Ctrl+C to shut down.
[12:01:44 INF] Hosting environment: Development
[12:01:44 INF] Content root path: serilog-aspnetcore/samples/Sample
[12:01:47 WRN] Failed to determine the https port for redirect.
[12:01:47 INF] { "answer": "hello" }
[12:01:47 INF] HTTP GET / responded 200 in 95.0581 ms

I am adding logs to elasticsearch and grafana. So I need to join elapsed time of action execution elapsed time and answer response in same json.

Can I join using serilog enrich or another way?


Solution

  • using Serilog.Core;
    using Serilog.Events;
    using System;
    
    // Custom enricher:
    
    public class ElapsedTimeEnricher : ILogEventEnricher
    {
        private readonly string _propertyName;
        private readonly DateTime _startTime;
    
        public ElapsedTimeEnricher(string propertyName = "ElapsedTime")
        {
            _propertyName = propertyName;
            _startTime = DateTime.UtcNow;
        }
    
        public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        {
            var elapsed = DateTime.UtcNow - _startTime;
            var elapsedSeconds = elapsed.TotalSeconds;
    
            var elapsedProperty = new LogEventProperty(_propertyName, new ScalarValue(elapsedSeconds));
            logEvent.AddPropertyIfAbsent(elapsedProperty);
        }
    }
    

    Example usage

    try
    {
        // Configure Serilog to use the custom enricher:
        Log.Logger = new LoggerConfiguration()
            .Enrich.With(new ElapsedTimeEnricher())
            .WriteTo.Console()
            .CreateLogger();
    
        Log.Information("Starting web application");
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddSerilog(); // <-- Add this line     
        var app = builder.Build();
        app.MapGet("/", () => "Hello World!");
    
        app.Run();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "Application startup failed");
    }
    finally
    {
        Log.CloseAndFlush();
    }