Interview question
Trace an unexpected API error by correlation ID
Tests that an unexpected failure returns a safe correlation identifier and records the same value in structured logs.
TL;DR
Tests that an unexpected failure returns a safe correlation identifier and records the same value in structured logs.
Exception boundaries, correlation IDs, structured logs, safe ProblemDetails, and log capture.
Practice the problem like a real interview: restate, reason, implement, and test.
Replace one service with a deterministic throwing fake. Call the endpoint with a known X-Correlation-ID. Assert the response is safe, contains the id, and captured structured logs contain the same id and exception type without sensitive request data.
Support can take the response trace id and find the exact error event, while the client never receives a stack trace or database message.
I turn an intermittent symptom into a controlled failure, then prove the diagnostic bridge from client response to server evidence. The test checks structured properties rather than rendered log text.
[Fact]
public async Task Unexpected_error_is_safe_and_correlated_with_logs()
{
var logs = new TestLogSink();
await using var factory = new ApiTestFactory(services =>
{
services.AddSingleton<IPricingService>(new ThrowingPricingService());
services.AddSingleton(logs);
});
var client = factory.CreateAuthenticatedClient("user-1", "quotes.create");
client.DefaultRequestHeaders.Add("X-Correlation-ID", "incident-test-123");
var response = await client.PostAsJsonAsync("/api/quotes", new { ProductId = "p-1" });
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
var problem = await response.Content.ReadFromJsonAsync<ProblemDetails>();
Assert.Equal("incident-test-123", problem!.Extensions["traceId"]?.ToString());
Assert.DoesNotContain("stack", problem.Detail ?? "", StringComparison.OrdinalIgnoreCase);
Assert.Contains(logs.Events, entry =>
entry.CorrelationId == "incident-test-123" &&
entry.Exception is PricingUnavailableException);
}
The test uses a fake dependency and in-memory log sink, so it is deterministic and does not need a database. It verifies observability as a user-support contract without locking the application to one log renderer.
Next in API Testing Labs: Trace Propagation