Introduction

In modern enterprise applications, logs are your first line of defense against production issues.
When your system runs across multiple APIs, microservices, and background jobs, collecting and analyzing logs becomes a challenge.

That’s where Centralized Logging comes in — a single place to collect, search, and analyze logs in real time.

In this article, you’ll learn how to build a Centralized Logging and Monitoring system using:

Why Centralized Logging?

Let’s say you’re running a web application with multiple APIs.

When a user reports,

“Something failed when placing an order,”

you might have to check multiple log files across servers to find what went wrong.

Centralized logging solves that by:

Architecture Overview

Here’s how everything connects:

  
    ASP.NET Core App
     │
     ▼
 [Serilog]
     │
     ▼
 [Logstash]
     │
     ▼
 [Elasticsearch]
     │
     ▼
 [Kibana Dashboard]
  

Explanation

  1. ASP.NET Core app writes structured logs via Serilog .

  2. Logs are sent to Logstash , which parses and processes them.

  3. Elasticsearch stores and indexes logs efficiently.

  4. Kibana visualizes the logs in dashboards and reports.

Step 1: Setting Up ELK Stack

Option 1: Using Docker (Recommended for Local Setup)

Create a docker-compose.yml file:

  
    version: '3.3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.10.0
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms1g -Xmx1g
    ports:
      - "9200:9200"

  logstash:
    image: docker.elastic.co/logstash/logstash:8.10.0
    ports:
      - "5044:5044"
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.10.0
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch
  

Logstash Configuration Example ( logstash.conf )

  
    input {
  tcp {
    port => 5044
    codec => json_lines
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "aspnetcore-logs-%{+YYYY.MM.dd}"
  }
}
  

Step 2: Add Serilog to an ASP.NET Core Project

Install NuGet packages

  
    dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Network
  

Step 3: Configure Serilog in Program.cs

  
    using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Configure Serilog
Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("Logs/app-.log", rollingInterval: RollingInterval.Day)
    .WriteTo.TCPSink("localhost", 5044) // Send to Logstash
    .CreateLogger();

builder.Host.UseSerilog();

builder.Services.AddControllers();
var app = builder.Build();

app.MapControllers();
app.Run();
  

What this does

Step 4: Create a Sample Controller

Log Example

  
    using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
    private readonly ILogger<OrderController> _logger;

    public OrderController(ILogger<OrderController> logger)
    {
        _logger = logger;
    }

    [HttpPost("place")]
    public IActionResult PlaceOrder()
    {
        _logger.LogInformation("Order placed successfully at {time}", DateTime.UtcNow);
        return Ok("Order created");
    }

    [HttpGet("error")]
    public IActionResult ThrowError()
    {
        try
        {
            throw new Exception("Test exception in order processing");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Order processing failed");
            return StatusCode(500, "Error");
        }
    }
}
  

Step 5: Verify Logs in Kibana

Once your ASP.NET Core app starts sending logs, open Kibana :

👉 http://localhost:5601

Create a new index pattern — aspnetcore-logs-*

You’ll now see logs from your .NET app appear live in Kibana’s “Discover” tab.
You can also:

Step 6: Adding More Context with Enrichment

Serilog lets you enrich logs with contextual data such as:

Example

  
    Log.Logger = new LoggerConfiguration()
    .Enrich.WithProperty("Application", "OrderService")
    .Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.TCPSink("localhost", 5044)
    .CreateLogger();
  

This helps you filter and analyze logs by app or environment directly in Kibana.

Step 7: Visualizing Metrics & Alerts in Kibana

Kibana isn’t just for log browsing. You can:

This transforms your logs into an observability system , not just error tracking.

Step 8: Security & Maintenance Tips

Real-World Use Cases

Flow Diagram – Serilog + ELK Stack Integration

  
    +------------------------+
|   ASP.NET Core App     |
| (Serilog Integration)  |
+-----------+------------+
            |
            v
+------------------------+
|     Logstash (Parser)  |
+-----------+------------+
            |
            v
+------------------------+
|  Elasticsearch (Index) |
+-----------+------------+
            |
            v
+------------------------+
|     Kibana Dashboard   |
| (Search, Visualize)    |
+------------------------+
  

Conclusion

Centralized logging with Serilog and ELK Stack brings structure, visibility, and control to your ASP.NET Core applications.
You no longer need to jump between servers or check log files manually — everything is in one place, searchable, visual, and intelligent.

If you’re running a large enterprise or cloud-based system, setting up this pipeline is one of the best investments you can make for reliability and operational insight.