OpenTelemetry Configuration
Configure OpenTelemetry to work with ByteHide Logger for comprehensive observability across your .NET applications. This setup enables automatic trace correlation and standardized log export.
Basic Setup
Program.cs Configuration
using OpenTelemetry;
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;
using Bytehide.Logger;
var builder = WebApplication.CreateBuilder(args);
// Configure ByteHide Logger
Log.SetProjectToken("your-project-token");
// Configure OpenTelemetry
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddSource("YourApp"))
.WithLogging(logging => logging
.AddConsoleExporter())
.WithMetrics(metrics => metrics
.AddAspNetCoreInstrumentation());
var app = builder.Build();
Activity Source Setup
public class OrderService
{
private static readonly ActivitySource ActivitySource = new("OrderService");
public async Task ProcessOrderAsync(Order order)
{
using var activity = ActivitySource.StartActivity("ProcessOrder");
activity?.SetTag("order.id", order.Id);
Log.WithCorrelationId(Activity.Current?.TraceId.ToString())
.WithMetadata("orderId", order.Id)
.Info("Starting order processing");
try
{
await ValidateOrderAsync(order);
await SaveOrderAsync(order);
Log.WithCorrelationId(Activity.Current?.TraceId.ToString())
.Info("Order processing completed");
}
catch (Exception ex)
{
Log.WithCorrelationId(Activity.Current?.TraceId.ToString())
.Error("Order processing failed", ex);
throw;
}
}
}
ASP.NET Core Integration
Startup Configuration
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// Configure ByteHide Logger
Log.SetProjectToken(Configuration["ByteHide:ProjectToken"]);
// Add OpenTelemetry
services.AddOpenTelemetry()
.WithTracing(builder => builder
.SetSampler(new AlwaysOnSampler())
.AddAspNetCoreInstrumentation(options =>
{
options.RecordException = true;
options.Filter = httpContext =>
!httpContext.Request.Path.StartsWithSegments("/health");
})
.AddHttpClientInstrumentation()
.AddEntityFrameworkCoreInstrumentation()
.AddJaegerExporter());
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Add correlation middleware
app.UseMiddleware<CorrelationMiddleware>();
// Other middleware...
}
}
Correlation Middleware
public class CorrelationMiddleware
{
private readonly RequestDelegate _next;
public CorrelationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var correlationId = context.TraceIdentifier;
// Set correlation ID for all logs in this request
using var scope = new CorrelationScope(correlationId);
Log.WithCorrelationId(correlationId)
.WithMetadata("requestPath", context.Request.Path)
.WithMetadata("requestMethod", context.Request.Method)
.Info("Request started");
try
{
await _next(context);
Log.WithCorrelationId(correlationId)
.WithMetadata("statusCode", context.Response.StatusCode)
.Info("Request completed");
}
catch (Exception ex)
{
Log.WithCorrelationId(correlationId)
.Error("Request failed", ex);
throw;
}
}
}
Configuration Options
ByteHide Logger Settings
// Configure ByteHide Logger for OpenTelemetry
var logSettings = new LogSettings
{
Persist = true,
FilePath = "logs/app.log",
ConsoleEnabled = true,
IncludeCallerInfo = true,
MinimumLevel = LogLevel.Info
};
Log.Configure(logSettings);
Log.SetProjectToken("your-project-token");
OpenTelemetry Trace Configuration
services.AddOpenTelemetry()
.WithTracing(builder => builder
.SetSampler(new TraceIdRatioBasedSampler(0.1)) // Sample 10% of traces
.AddAspNetCoreInstrumentation(options =>
{
options.RecordException = true;
options.EnrichWithHttpRequest = (activity, request) =>
{
activity.SetTag("http.request.user_agent", request.Headers.UserAgent.ToString());
};
options.EnrichWithHttpResponse = (activity, response) =>
{
activity.SetTag("http.response.content_type", response.ContentType);
};
})
.AddHttpClientInstrumentation(options =>
{
options.RecordException = true;
}));
Environment-Specific Configuration
Development Environment
if (builder.Environment.IsDevelopment())
{
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddConsoleExporter()
.SetSampler(new AlwaysOnSampler()));
// Enable detailed logging
Log.Configure(new LogSettings
{
ConsoleEnabled = true,
MinimumLevel = LogLevel.Debug,
IncludeCallerInfo = true
});
}
Production Environment
if (builder.Environment.IsProduction())
{
builder.Services.AddOpenTelemetry()
.WithTracing(tracing => tracing
.AddJaegerExporter(options =>
{
options.AgentHost = "jaeger-agent";
options.AgentPort = 6831;
})
.SetSampler(new TraceIdRatioBasedSampler(0.05))); // 5% sampling
// Production logging settings
Log.Configure(new LogSettings
{
Persist = true,
FilePath = "/var/log/app/application.log",
RollingInterval = RollingInterval.Day,
MinimumLevel = LogLevel.Warn,
ConsoleEnabled = false
});
}
Automatic Correlation
HTTP Client Correlation
public class ApiClient
{
private readonly HttpClient _httpClient;
public ApiClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<T> GetAsync<T>(string endpoint)
{
using var activity = ActivitySource.StartActivity($"GET {endpoint}");
var correlationId = Activity.Current?.TraceId.ToString();
Log.WithCorrelationId(correlationId)
.WithMetadata("endpoint", endpoint)
.WithTags("http-client", "api-call")
.Info("Making API request");
try
{
var response = await _httpClient.GetAsync(endpoint);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<T>(content);
Log.WithCorrelationId(correlationId)
.WithMetadata("statusCode", (int)response.StatusCode)
.Info("API request completed");
return result;
}
catch (Exception ex)
{
Log.WithCorrelationId(correlationId)
.Error("API request failed", ex);
throw;
}
}
}
Database Operation Correlation
public class OrderRepository
{
private static readonly ActivitySource ActivitySource = new("OrderRepository");
public async Task<Order> GetOrderAsync(int orderId)
{
using var activity = ActivitySource.StartActivity("GetOrder");
activity?.SetTag("order.id", orderId);
var correlationId = Activity.Current?.TraceId.ToString();
Log.WithCorrelationId(correlationId)
.WithMetadata("orderId", orderId)
.WithTags("database", "query")
.Debug("Querying order from database");
try
{
var order = await _context.Orders.FindAsync(orderId);
if (order == null)
{
Log.WithCorrelationId(correlationId)
.WithMetadata("orderId", orderId)
.Warn("Order not found");
throw new OrderNotFoundException(orderId);
}
Log.WithCorrelationId(correlationId)
.Debug("Order retrieved successfully");
return order;
}
catch (Exception ex)
{
Log.WithCorrelationId(correlationId)
.Error("Database query failed", ex);
throw;
}
}
}
Configuration Best Practices
Configuration Best Practices
- Use environment variables: Store sensitive configuration in environment variables
- Configure sampling: Use appropriate sampling rates for production (5-10%)
- Enable exception recording: Set
RecordException = true
for better error tracking - Filter health checks: Exclude health check endpoints from tracing
- Set resource attributes: Include service name, version, and environment information
- Use correlation IDs consistently: Apply correlation IDs to all related operations
Troubleshooting
Missing Trace Correlation
// Ensure Activity.Current is available
if (Activity.Current == null)
{
Log.Warn("No active Activity found - trace correlation may be missing");
}
// Use manual correlation ID if needed
var correlationId = Activity.Current?.TraceId.ToString() ?? Guid.NewGuid().ToString();
Log.WithCorrelationId(correlationId).Info("Manual correlation applied");
Performance Impact
// Use appropriate sampling to reduce overhead
services.AddOpenTelemetry()
.WithTracing(builder => builder
.SetSampler(new ParentBasedSampler(new TraceIdRatioBasedSampler(0.1))));
// Configure ByteHide Logger for production
Log.Configure(new LogSettings
{
MinimumLevel = LogLevel.Warn, // Reduce log volume
DuplicateSuppressionWindow = TimeSpan.FromMinutes(5) // Suppress duplicates
});
Next Steps
- Exporter Setup - Configure exporters for different backends
- Best Practices - Optimize your observability setup
- Correlation IDs - Learn more about correlation strategies