Skip to main content

correlation-id-tracking

Manages correlation-id in .NET applications using AsyncLocal for async context isolation. Use when implementing correlation-id tracking, HTTP request/response correlation, logging integration, or when working with distributed tracing in .NET applications.

インストールへ移動

ソース情報

リポジトリ
whitebeardit/.cursor
ソースの最終更新活動
2026年1月31日 23:09
検出された SKILL.md の言語
英語
スター
12
フォーク
6

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
correlation-id-tracking
description
Manages correlation-id in .NET applications using AsyncLocal for async context isolation. Use when implementing correlation-id tracking, HTTP request/response correlation, logging integration, or when working with distributed tracing in .NET applications.
# Using Traceability Package for Correlation-ID Tracking This skill helps you use the **WhiteBeard.Traceability** NuGet package to implement correlation-id tracking in .NET applications. The package provides automatic correlation-id management with zero-configuration setup. ## Installation ```bash dotnet add package WhiteBeard.Traceability ``` Or via Package Manager: ```powershell Install-Package WhiteBeard.Traceability ``` ## Quick Setup ### ASP.NET Core (.NET 8) - Zero Configuration **Minimal setup (one line!):** ```csharp using Traceability.Extensions; var builder = WebApplication.CreateBuilder(args); // Zero configuration - everything is automatic! // - Middleware registered automatically // - HttpClient configured automatically // - Source from TRACEABILITY_SERVICENAME or assembly name builder.Services.AddTraceability(); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllers(); app.Run(); ``` **With explicit service name:** ```csharp builder.Services.AddTraceability("MyService"); ``` **Done!** Correlation-id is now automatically: - ✅ Generated on each request (if not provided via `X-Correlation-Id` header) - ✅ Available via `CorrelationContext.Current` - ✅ Added to response headers as `X-Correlation-Id` - ✅ Propagated in HttpClient calls automatically - ✅ Included in logs (when logging is configured) ### ASP.NET Framework 4.8 - Zero Code **Just install the package - no code needed!** The library automatically: - ✅ Registers `CorrelationIdHttpModule` via `PreApplicationStartMethod` - ✅ Manages correlation-id automatically **Optional: Configure Serilog** ```csharp // Global.asax.cs using Traceability.Extensions; using Serilog; protected void Application_Start() { Log.Logger = new LoggerConfiguration() .WithTraceability("MyService") .WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Source} {CorrelationId} {Message:lj}{NewLine}{Exception}") .CreateLogger(); } ``` ## Using Correlation-ID in Code ### In Controllers ```csharp using Traceability; using Microsoft.AspNetCore.Mvc; [ApiController] [Route("api/[controller]")] public class ApiController : ControllerBase { [HttpGet("test")] public IActionResult Test() { // Correlation-id is automatically available var correlationId = CorrelationContext.Current; return Ok(new { CorrelationId = correlationId }); } } ``` ### In Console Applications ```csharp using Traceability; // Get or create correlation-ID var correlationId = CorrelationContext.GetOrCreate(); Console.WriteLine($"Correlation ID: {correlationId}"); // Correlation-id is preserved across async operations await SomeAsyncMethod(); var sameId = CorrelationContext.Current; // Still the same! ``` ### CorrelationContext API ```csharp // Get current (auto-creates if missing) var id = CorrelationContext.Current; // Check if exists without creating if (CorrelationContext.TryGetValue(out var correlationId)) { // Use existing correlation-ID } // Set explicitly CorrelationContext.Current = "existing-correlation-id"; // Clear context CorrelationContext.Clear(); ``` ## HttpClient Integration **Automatic propagation - no extra code needed!** ```csharp // In Program.cs builder.Services.AddTraceability(); builder.Services.AddHttpClient("ExternalApi", client => { client.BaseAddress = new Uri("https://api.example.com/"); }); // In Controller var client = _httpClientFactory.CreateClient("ExternalApi"); // Correlation-id is automatically added to X-Correlation-Id header! var response = await client.GetAsync("posts/1"); ``` The `CorrelationIdHandler` is automatically registered - all HttpClient instances created via `IHttpClientFactory` will include the correlation-ID header. ## Logging Integration ### Serilog ```csharp using Traceability.Logging; using Serilog; Log.Logger = new LoggerConfiguration() .Enrich.With<CorrelationIdEnricher>() .WriteTo.Console( outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {CorrelationId} {Message:lj}{NewLine}{Exception}") .CreateLogger(); // Now all logs automatically include CorrelationId property logger.LogInformation("Processing request"); // Output: [12:34:56 INF] a1b2c3d4e5f6789012345678901234ab Processing request ``` ### Microsoft.Extensions.Logging ```csharp using Traceability.Logging; builder.Services.AddTraceability(); builder.Logging.AddConsole(options => options.IncludeScopes = true); // CorrelationIdScopeProvider is automatically registered // Logs automatically include correlation-ID in scope logger.LogInformation("Processing request"); ``` ## Logging Best Practices ### Log Levels: When to Use Each **DEBUG** - Development and troubleshooting only: - Detailed execution flow - Variable values and intermediate states - Step-by-step process information - **Not visible in production** (typically filtered out) **INFO** - Production-ready, important events: - Request start/completion - Business operations (create, update, delete) - External API calls (start/end) - Important state changes - **Visible in production** **WARNING** - Potential issues that don't break functionality: - Retry attempts - Fallback to default values - Deprecated API usage - Performance degradation **ERROR** - Failures that need attention: - Exceptions and errors - Failed operations - External service failures ### What to Log (and What NOT to Log) **✅ DO Log:** - Request identifiers (correlation-ID, user ID, request ID) - Business operations (what happened) - External service calls (start, end, duration) - Important state changes - Errors with context (correlation-ID, user, operation) **❌ DON'T Log:** - Sensitive data (passwords, tokens, PII, credit cards) - Large payloads (use summaries instead) - Every iteration in loops (log once per operation) - Redundant information (correlation-ID is already in context) - Excessive detail in production (use DEBUG for that) ### Structured Logging with Correlation-ID Always include correlation-ID in logs for traceability: ```csharp // ✅ Good: Structured logging with correlation-ID _logger.LogInformation( "Processing order {OrderId} for user {UserId}. CorrelationId: {CorrelationId}", orderId, userId, CorrelationContext.Current); // ✅ Good: Using structured properties _logger.LogInformation( "External API call completed. Endpoint: {Endpoint}, Duration: {Duration}ms, StatusCode: {StatusCode}", endpoint, duration, statusCode); // ❌ Bad: Logging without correlation-ID context _logger.LogInformation($"Processing order {orderId}"); // Missing correlation-ID! // ❌ Bad: Logging sensitive data _logger.LogInformation($"User password: {password}"); // NEVER log passwords! ``` ### Production vs Development Logging **Production Configuration:** ```csharp // appsettings.Production.json { "Logging": { "LogLevel": { "Default": "Information", // INFO and above "Microsoft": "Warning", // Reduce framework noise "System": "Warning" } } } ``` **Development Configuration:** ```csharp // appsettings.Development.json { "Logging": { "LogLevel": { "Default": "Debug", // DEBUG and above "Microsoft": "Information", "System": "Information" } } } ``` ### Logging Patterns for Debugging **Pattern 1: Request Lifecycle** ```csharp [HttpGet("orders/{id}")] public async Task<IActionResult> GetOrder(int id) { var correlationId = CorrelationContext.Current; // ✅ INFO: Request start (production-visible) _logger.LogInformation( "Getting order {OrderId}. CorrelationId: {CorrelationId}", id, correlationId); try { // ✅ DEBUG: Detailed steps (development only) _logger.LogDebug( "Querying database for order {OrderId}. CorrelationId: {CorrelationId}", id, correlationId); var order = await _repository.GetByIdAsync(id); if (order == null) { // ✅ WARNING: Expected but notable condition _logger.LogWarning( "Order {OrderId} not found. CorrelationId: {CorrelationId}", id, correlationId); return NotFound(); } // ✅ INFO: Successful completion (production-visible) _logger.LogInformation( "Order {OrderId} retrieved successfully. CorrelationId: {CorrelationId}", id, correlationId); return Ok(order); } catch (Exception ex) { // ✅ ERROR: Always log exceptions with correlation-ID _logger.LogError(ex, "Error retrieving order {OrderId}. CorrelationId: {CorrelationId}", id, correlationId); return StatusCode(500); } } ``` **Pattern 2: External Service Calls** ```csharp public async Task<PaymentResult> ProcessPayment(PaymentRequest request) { var correlationId = CorrelationContext.Current; // ✅ INFO: External call start (production-visible) _logger.LogInformation( "Calling payment service. Amount: {Amount}, Currency: {Currency}. CorrelationId: {CorrelationId}", request.Amount, request.Currency, correlationId); var stopwatch = Stopwatch.StartNew(); try { var response = await _paymentClient.ProcessAsync(request); stopwatch.Stop(); // ✅ INFO: Success with duration (production-visible) _logger.LogInformation( "Payment service call completed. Status: {Status}, Duration: {Duration}ms. CorrelationId: {CorrelationId}", response.Status, stopwatch.ElapsedMilliseconds, correlationId); return response; } catch (Exception ex) { stopwatch.Stop(); // ✅ ERROR: Failure with context (production-visible) _logger.LogError(ex, "Payment service call failed. Duration: {Duration}ms. CorrelationId: {CorrelationId}", stopwatch.ElapsedMilliseconds, correlationId); throw; } } ``` **Pattern 3: Conditional Debug Logging** ```csharp public async Task ProcessItems(List<Item> items) { var correlationId = CorrelationContext.Current; // ✅ INFO: Operation start (production-visible) _logger.LogInformation( "Processing {Count} items. CorrelationId: {CorrelationId}", items.Count, correlationId); for (int i = 0; i < items.Count; i++) { // ✅ DEBUG: Detailed per-item info (development only) _logger.LogDebug( "Processing item {Index}/{Total}: {ItemId}. CorrelationId: {CorrelationId}", i + 1, items.Count, items[i].Id, correlationId); await ProcessItem(items[i]); } // ✅ INFO: Operation completion (production-visible) _logger.LogInformation( "Processed {Count} items successfully. CorrelationId: {CorrelationId}", items.Count, correlationId); } ``` ### Key Principles 1. **Correlation-ID Always**: Every log should include correlation-ID (automatically via enricher/scope) 2. **Structured Properties**: Use structured logging with named properties, not string interpolation 3. **Context Matters**: Include relevant context (user ID, operation, IDs) but not sensitive data 4. **Level Appropriately**: Use DEBUG for detailed troubleshooting, INFO for production visibility 5. **Performance Aware**: Don't log in tight loops; summarize instead 6. **Error Context**: Always include correlation-ID and relevant context in error logs ## Environment Variables Set service name via environment variable to reduce code: **Linux/Mac:** ```bash export TRACEABILITY_SERVICENAME="UserService" ``` **Windows PowerShell:** ```powershell $env:TRACEABILITY_SERVICENAME="UserService" ``` Then use: ```csharp // Source comes automatically from TRACEABILITY_SERVICENAME builder.Services.AddTraceability(); ``` ## Common Patterns ### Pattern 1: Reading Correlation-ID from Request The middleware automatically: 1. Reads `X-Correlation-Id` from incoming request headers 2. If present, uses that value 3. If missing, generates new GUID (32 chars, no hyphens) 4. Sets `CorrelationContext.Current` 5. Adds to response headers **No code needed** - this happens automatically! ### Pattern 2: Preserving Across Async Operations ```csharp var correlationId = CorrelationContext.Current; // "abc123" await SomeAsyncMethod(); var sameId = CorrelationContext.Current; // Still "abc123" - preserved! ``` ### Pattern 3: Isolated Contexts ```csharp var mainId = CorrelationContext.Current; // "id1" await Task.Run(async () => { // New isolated context - no correlation-ID unless set if (!CorrelationContext.HasValue) { CorrelationContext.Current = "id2"; } }); ``` ### Pattern 4: Manual Propagation ```csharp // Set correlation-ID from external source CorrelationContext.Current = externalCorrelationId; // Now all operations use this correlation-ID await ProcessRequest(); ``` ## Key Features 1. **Zero Configuration**: Works out of the box with minimal setup 2. **Async-Safe**: Uses `AsyncLocal<string>` to preserve correlation-ID across async/await
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る