first commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OpenTelemetry.Resources;
|
||||
using OpenTelemetry.Trace;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MyNewProjectName.Infrastructure.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for configuring OpenTelemetry
|
||||
/// </summary>
|
||||
public static class OpenTelemetryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Add OpenTelemetry distributed tracing
|
||||
/// </summary>
|
||||
public static IServiceCollection AddOpenTelemetryTracing(
|
||||
this IServiceCollection services,
|
||||
string serviceName = "MyNewProjectName")
|
||||
{
|
||||
services.AddOpenTelemetry()
|
||||
.WithTracing(builder =>
|
||||
{
|
||||
builder
|
||||
.SetResourceBuilder(ResourceBuilder
|
||||
.CreateDefault()
|
||||
.AddService(serviceName)
|
||||
.AddAttributes(new Dictionary<string, object>
|
||||
{
|
||||
["service.version"] = Assembly.GetExecutingAssembly()
|
||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
||||
.InformationalVersion ?? "1.0.0"
|
||||
}))
|
||||
.AddAspNetCoreInstrumentation(options =>
|
||||
{
|
||||
// Capture HTTP request/response details
|
||||
options.RecordException = true;
|
||||
options.EnrichWithHttpRequest = (activity, request) =>
|
||||
{
|
||||
activity.SetTag("http.request.method", request.Method);
|
||||
activity.SetTag("http.request.path", request.Path);
|
||||
activity.SetTag("http.request.query_string", request.QueryString);
|
||||
};
|
||||
options.EnrichWithHttpResponse = (activity, response) =>
|
||||
{
|
||||
activity.SetTag("http.response.status_code", response.StatusCode);
|
||||
};
|
||||
})
|
||||
.AddHttpClientInstrumentation(options =>
|
||||
{
|
||||
options.RecordException = true;
|
||||
options.EnrichWithHttpRequestMessage = (activity, request) =>
|
||||
{
|
||||
activity.SetTag("http.client.request.method", request.Method?.ToString());
|
||||
activity.SetTag("http.client.request.uri", request.RequestUri?.ToString());
|
||||
};
|
||||
})
|
||||
.AddEntityFrameworkCoreInstrumentation(options =>
|
||||
{
|
||||
options.SetDbStatementForText = true;
|
||||
options.EnrichWithIDbCommand = (activity, command) =>
|
||||
{
|
||||
activity.SetTag("db.command.text", command.CommandText);
|
||||
};
|
||||
})
|
||||
.AddSource(serviceName)
|
||||
// Export to console (for development)
|
||||
.AddConsoleExporter()
|
||||
// Export to OTLP (for production - requires OTLP collector)
|
||||
.AddOtlpExporter(options =>
|
||||
{
|
||||
// Configure OTLP endpoint if needed
|
||||
// options.Endpoint = new Uri("http://localhost:4317");
|
||||
});
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MyNewProjectName.Infrastructure.Options;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using Serilog.Formatting.Compact;
|
||||
|
||||
namespace MyNewProjectName.Infrastructure.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for configuring Serilog
|
||||
/// </summary>
|
||||
public static class SerilogExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Configure Serilog with structured JSON logging
|
||||
/// </summary>
|
||||
public static IHostBuilder UseSerilogLogging(this IHostBuilder hostBuilder, IConfiguration configuration)
|
||||
{
|
||||
var serilogOptions = configuration.GetSection(SerilogOptions.SectionName).Get<SerilogOptions>()
|
||||
?? new SerilogOptions();
|
||||
|
||||
var loggerConfiguration = new LoggerConfiguration()
|
||||
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
|
||||
.MinimumLevel.Override("System", LogEventLevel.Warning)
|
||||
.Enrich.FromLogContext()
|
||||
.Enrich.WithEnvironmentName()
|
||||
.Enrich.WithMachineName()
|
||||
.Enrich.WithThreadId()
|
||||
.Enrich.WithProperty("Application", "MyNewProjectName");
|
||||
|
||||
// Set minimum level from configuration
|
||||
if (Enum.TryParse<LogEventLevel>(serilogOptions.MinimumLevel, out var minLevel))
|
||||
{
|
||||
loggerConfiguration.MinimumLevel.Is(minLevel);
|
||||
}
|
||||
|
||||
// Apply overrides from configuration
|
||||
foreach (var overrideConfig in serilogOptions.Override)
|
||||
{
|
||||
if (Enum.TryParse<LogEventLevel>(overrideConfig.Value, out var overrideLevel))
|
||||
{
|
||||
loggerConfiguration.MinimumLevel.Override(overrideConfig.Key, overrideLevel);
|
||||
}
|
||||
}
|
||||
|
||||
// Console sink with JSON formatting (Compact JSON format)
|
||||
if (serilogOptions.WriteToConsole)
|
||||
{
|
||||
loggerConfiguration.WriteTo.Console(new CompactJsonFormatter());
|
||||
}
|
||||
|
||||
// File sink with rolling
|
||||
if (serilogOptions.WriteToFile)
|
||||
{
|
||||
var rollingInterval = Enum.TryParse<RollingInterval>(serilogOptions.RollingInterval, out var interval)
|
||||
? interval
|
||||
: RollingInterval.Day;
|
||||
|
||||
loggerConfiguration.WriteTo.File(
|
||||
new CompactJsonFormatter(),
|
||||
serilogOptions.FilePath,
|
||||
rollingInterval: rollingInterval,
|
||||
retainedFileCountLimit: serilogOptions.RetainedFileCountLimit,
|
||||
shared: true);
|
||||
}
|
||||
|
||||
// Seq sink (optional)
|
||||
if (!string.IsNullOrWhiteSpace(serilogOptions.SeqUrl))
|
||||
{
|
||||
loggerConfiguration.WriteTo.Seq(serilogOptions.SeqUrl);
|
||||
}
|
||||
|
||||
// Elasticsearch sink (optional)
|
||||
if (!string.IsNullOrWhiteSpace(serilogOptions.ElasticsearchUrl))
|
||||
{
|
||||
// Note: Add Serilog.Sinks.Elasticsearch package if needed
|
||||
// loggerConfiguration.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(serilogOptions.ElasticsearchUrl)));
|
||||
}
|
||||
|
||||
Log.Logger = loggerConfiguration.CreateLogger();
|
||||
|
||||
return hostBuilder.UseSerilog();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user