Configure ELK stack in .NET Core 6

Bogdan Hatis
2 min readMay 22, 2022

Every application needs a log centralized log system and for that, in this article, I will configure ElasticSearch and Kibana in .NET core 6 using Serilog.

The first step is to install the docker desktop application on our machine (for production purposes it is recommended to use a VM).

Now let’s create a yml file for Elastic search and Kibana and save it as elk.yml:

services:elasticsearch:
container_name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
ports:
- 9200:9200
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
environment:
- xpack.monitoring.enabled=true
- xpack.watcher.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- discovery.type=single-node
networks:
- customNetwork
kibana:
container_name: kibana
image: docker.elastic.co/kibana/kibana:7.6.2
ports:
- 5601:5601
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_URL=http://localhost:9200
networks:
- customNetwork

Now let’s run it on docker, using docker-compose up -d, and in the docker app, we’ll have 2 containers, 1 for Elastic search and 1 for Kibana. If everything is ready then we should have access to localhost:9200 for Elastic search and localhost:5601 for Kibana

Now, let’s start coding 🙂

In our .NET Core 6 application, we need to install some NuGet packages:

  1. Serilog.AspNetCore
  2. Serilog.Enrichers.Environment
  3. Serilog.Sinks.Debug
  4. Serilog.Sinks.ElasticSearch

Now configure in our program.cs file, add 2 new methods and after that call:

ConfigureLogging(); 
builder.Host.UseSerilog(); ................................................................ void ConfigureLogging()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json",optional: true)
.Build();
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithEnvironmentName()
.WriteTo.Debug()
.WriteTo.Console()
.WriteTo.Elasticsearch(ConfigureElasticSink(configuration, environment!))
.Enrich.WithProperty("Environment", environment!)
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
ElasticsearchSinkOptions ConfigureElasticSink(IConfigurationRoot configuration, string environment){
return new ElasticsearchSinkOptions(new Uri(configuration["ElasticConfiguration:Uri"]))
{
AutoRegisterTemplate = true,
IndexFormat = $
{Assembly.GetExecutingAssembly().GetName().Name?.ToLower().Replace(".", "-")}-{environment?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}"
};
}

Now in the appsettings.json change the Logging section with the code below and add the configuration for ElasticSearch:

"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Error",
"System": "Warning"
}
}
},
"ElasticConfiguration": {
"Uri": "http://localhost:9200"
}

We are going to use Microsoft Error level because we want to define custom logs in our application. If you want to keep all the information from Microsoft you should keep Information.

Now, let’s create some logs in our application:

private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) 
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("This is a wow message to test the logs");
return View();
}

Now let’s check in Kibana, to see our log message.

In this article, I used docker desktop to configure Elastic search and Kibana and Serilog in a .NET Core application.

Originally published at https://bogdanhatis.com on May 22, 2022.

--

--

Bogdan Hatis

Experienced developer, product manager and CTO with a demonstrated history of working in the information technology, services and fintech industry.