Loading...
Loading...
Elasticsearch and Elastic APM integration with Serilog structured logging for .NET applications. Use when: (1) Implementing or configuring Serilog with Elasticsearch sink, (2) Setting up Elastic APM with data streams and authentication, (3) Creating logging extension methods in Infrastructure layer, (4) Enriching logs with app-name and app-type properties, (5) Configuring log levels and environment-specific logging, (6) Questions about logging security (PII, credentials), or (7) Troubleshooting observability and monitoring setup.
npx skill4agent add analistadesarrollo4/skills dotnet-elastic-apmapp-nameapp-typeProgram.csInfrastructure/Extensions/ExtensionLogging.csusing Serilog;
using Serilog.Events;
using Serilog.Sinks.Elasticsearch;
using Elastic.Ingest.Elasticsearch.DataStreams;
using Elastic.Ingest.Elasticsearch;
using Elastic.Transport;
namespace Infrastructure.Extensions
{
/// <summary>
/// Extension class for configuring Serilog with Elasticsearch and Elastic APM.
/// </summary>
public static class ExtensionLogging
{
/// <summary>
/// Configures Serilog with Elasticsearch using Elastic APM.
/// </summary>
/// <param name="configuration">Application configuration.</param>
public static void AddLog(IConfiguration configuration)
{
string? elasticUrl = configuration.GetValue<string>("Global:Elastic:Url");
string? environment = configuration.GetValue<string>("Global:Elastic:Env");
string? elasticUser = configuration.GetValue<string>("Global:Elastic:User");
string? elasticPass = configuration.GetValue<string>("Global:Elastic:Pass");
string? logLevelEnv = configuration.GetValue<string>("Global:Elastic:LogLevel");
LogEventLevel logEventLevel = (LogEventLevel)int.Parse(logLevelEnv!);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithProperty("app-name", configuration.GetSection("Elastic").GetValue<string>("app-name"))
.Enrich.WithProperty("app-type", configuration.GetSection("Elastic").GetValue<string>("app-type"))
.WriteTo.Console()
.WriteTo.Elasticsearch([new Uri(elasticUrl!)], opts =>
{
// Use DataStream for Elastic APM compatibility
opts.DataStream = new DataStreamName("app", environment!, "logs");
opts.BootstrapMethod = BootstrapMethod.None;
opts.MinimumLevel = logEventLevel;
}, transport =>
{
// Basic Authentication
transport.Authentication(new BasicAuthentication(elasticUser!, elasticPass!));
// Callback to accept certificates (e.g., in development)
transport.ServerCertificateValidationCallback((a, b, c, d) => true);
})
.CreateLogger();
}
}
}Program.csif (app.Environment.IsDevelopment())
{
builder.Services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
ExtensionLogging.AddLog(builder.Configuration);
builder.Services.AddAllElasticApm();
}{
"Elastic": {
"app-name": "your-app-name",
"app-type": "api",
"Url": "https://your-elastic-url:9200",
"Env": "development",
"User": "elastic_user",
"Pass": "elastic_password",
"LogLevel": "2"
}
}Log.Information("User {UserId} logged in", userId);