Skip to main content
Version: v1.7.0

Correlation Between HTTP Requests (W3C)

The Arcus.WebApi.Logging library provides a way to add correlation between HTTP requests.

🚩 This page describes W3C Trace-Context correlation, see this page for information on the (deprecated) Hierarchical HTTP correlation.

How This Works​

This diagram shows an example of a user interacting with service A that calls another service B.

HTTP correlation diagram

Three kind of correlation ID's are used to create the relationship:

  • Transaction ID: this ID is the one constant in the diagram. This ID is used to describe the entire transaction, from begin to end. All telemetry will be tracked under this ID.
  • Operation ID: this ID describes a single operation within the transaction. This ID is used within a service to link all telemetry correctly together.
  • Operation Parent ID: this ID is create the parent/child link across services. When service A calls service B, then service A is the so called 'parent' of service B.

The following list shows each step in the diagram:

  1. The initial call in this example doesn't contain any correlation headers. This can be seen as a first interaction call to a service.
  2. Upon receiving at service A, the application will generate new correlation information. This correlation info will be used when telemetry is tracked on the service.
  3. When a call is made to service B, the transaction ID is sent but also the operation parent ID in the form of a W3C structure: 00-transactionId-parentId-00.
  4. The def part of this ID, describes the new parent ID for service B (when service B calls service C, then it will use a different parent ID)
  5. Service B responds to service A with the same information as the call to service B.
  6. The user receives both the transaction ID and operation ID in their final response.

💡 This correlation is based on the traceparent HTTP request/response header.

Additional configuration is available to tweak this functionality.

⚡ Automatic dependency tracking​

When choosing for the W3C HTTP correlation format, Arcus and Microsoft technology works seemingly together. When a HTTP request is received on a service that uses the Arcus W3C HTTP correlation, all remote dependencies managed my Microsoft (HTTP, ServiceBus, EventHubs...) are tracked automatically, without additional configuration.

Installation​

This feature requires to install our NuGet package:

PM > Install-Package Arcus.WebApi.Logging

Usage​

To fully benefit from the Arcus' HTTP correlation functionality, both sending and receiving HTTP endpoints should be configured. These three things need to be added on both sides:

  1. Adding HTTP correlation to application services with services.AddHttpCorrelation().
  2. Adding HTTP correlation to application middleware with app.UseHttpCorrelation() and app.UseRequestTracking() (more info on request tracking).
  3. Adding HTTP correlation enricher to Serilog configuration with Enrich.WithHttpCorrelationInfo(app.Services) (more info).
using Microsoft.AspNetCore.Builder;
using Serilog;
using Serilog.Configuration;

WebApplication builder = WebApplication.CreateBuilder();
builder.Services.AddHttpCorrelation();
builder.Services.AddHttpClient("from-service-a-to-service-b");

builder.Host.UseSerilog((context, serviceProvider, config) =>
{
config.Enrich.WithHttpCorrelationInfo(serviceProvider)
.WriteTo.Console()
.CreateLogger();
});

WebApplication app = builder.Build();
app.UseHttpCorrelation();

// âš  Because the correlation is based on <span>ASP.NET</span> Core middleware, it's recommended to place it before the `.UseRouting` call.
app.UseRouting();
app.UseRequestTracking();

âš¡ The UseRequestTracking extension will make sure that the incoming HTTP request will be tracked as a 'request' in Application Insights (if configured). For more information on HTTP request tracking, see our dedicated feature documentation page;

âš¡ As an additional feature, we provide an extension to use the HTTP correlation directly in a Serilog configuration as an enricher. This adds the correlation information of the current request to the log event as a log property called TransactionId, OperationId, and OperationParentId. Example

  • TransactionId: 4b1c0c8d608f57db7bd0b13c88ef865e
  • OperationId: 4a3c1c8d
  • OperationParentId: 4c6893cc6c6cad10

âš¡ To use HTTP correlation in Azure Functions, see this dedicated page, as the configuration on the receiving side is slightly different.

Configuration​

The HTTP correlation can be configured with different options to work for your needs.

Configuring HTTP correlation services​

The HTTP correlation is available throughout the application via the registered IHttpCorrelationInfoAccessor. This HTTP correlation accessor is both used in sending/receiving functionality. Some extra options are available to alter the functionality of the correlation:

using Microsoft.AspNetCore.Builder;

WebApplicationBuilder builder = WebApplication.CreateBuilder();
builder.Services.AddHttpCorrelation(options =>
{
// Configuration on the transaction ID (`X-Transaction-ID`) response header.
// ---------------------------------------------------------------------------------

// Whether to include the transaction ID in the response (default: true).
options.Transaction.IncludeInResponse = true;

// The header will be set in the HTTP response (default: X-Transaction-ID).
options.Transaction.HeaderName = "X-Transaction-ID";

// Configuration on the operation ID (`X-Operation-Id`) response header.
// ----------------------------------------------------------------

// Whether to include the operation ID in the response (default: true).
options.Operation.IncludeInResponse = true;

// The header that will contain the operation ID in the HTTP response (default: X-Operation-Id).
options.Operation.HeaderName = "X-MyOperation-Id";
});

Dependency injection​

To use the HTTP correlation in your application code, you can use a dedicated marker interface called IHttpCorrelationInfoAccessor. This will help you with accessing and setting the HTTP correlation.

Note that the correlation is a scoped dependency, so will be the same instance across the HTTP request.

using Microsoft.AspNetCore.Mvc;
using Arcus.WebApi.Logging.Core.Correlation;

[ApiController]
[Route("api/v1/order")]
public class OrderController : ControllerBase
{
private readonly IHttpCorrelationInfoAccessor _accessor;

public OrderController(IHttpCorrelationInfoAccessor accessor)
{
_accessor = accessor;
}

[HttpPost]
public IActionResult Post([FromBody] Order order)
{
CorrelationInfo correlation = _accessor.GetCorrelationInfo();

_accessor.SetCorrelationInfo(correlation);
}
}