I suspect this is not possible, but someone may have an interesting solution.
I want to set the TraceId on a gRPC call. This will allow me continuity of trace across a variety of boundaries. For example a bunch of requests that have been stored to file, and now need processing.
The destination is a C# ASP.NET Core gRPC service. The source is a c# console app that uses an ASP.NET Core WebApplicationBuilder as the source of the client. i.e.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddGrpcClient<Greeter.GreeterClient>(options =>
{options.Address = new (serviceAddress);});
//logging stuff
var serilog = new LoggerConfiguration();
serilog.WriteTo.Console();
serilog.WriteTo.File(new CompactJsonFormatter(), @"D:\Log\Consumer.json", rollingInterval: RollingInterval.Day);
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(serilog.CreateLogger());
var app = builder.Build();
using var scope = app.Services.CreateScope();
var client = scope.ServiceProvider.GetRequiredService<Greeter.GreeterClient>();
client.SayHello(new HelloRequest());
The json log output then contains lines such as:
{"@t":"2025-06-27T10:37:05.7886907Z","@mt":"Start processing HTTP request {HttpMethod} {Uri}","@tr":"9b14662ca75754818cc8cac1a61924b7","@sp":"896f4d5f87913065","HttpMethod":"POST","Uri":"https://localhost:7156/greet.Greeter/SayHello","EventId":{"Id":100,"Name":"RequestPipelineStart"},"SourceContext":"System.Net.Http.HttpClient.GreeterClient.LogicalHandler","SpanId":"896f4d5f87913065","TraceId":"9b14662ca75754818cc8cac1a61924b7","ParentId":"0000000000000000", ....
Using the ASP.NET Core wrapper adds a load of useful log enriching to the client, including a TraceId that will propagate along the chain. In my case however the client is not the originator of the request, just of the the gRPC section.
I know that using a CorrelationId as additional metadata will get me the majority of the functionality. I have already tried it and I expect that may well be the best available solution. But it would be much neater if I could tie into the existing infrastructure and not have to included a load of additional interceptors.
What I have tried:
I have tried adding ASP.NET Core middleware, but it seems to not get hit on the client outbound. gRPC interceptors are of course hit, but these do not have edit access to the HTTP context.
I have tried adding in
traceIdandtraceparentto the metadata of the call from the client. This does override thetrace-id(viatraceparent) at the server end, but not in the logging at the client end. It also seems to not override correctly.
I believe that the only way to do it is to get in at the point that the client is generated. I suspect that somewhere in the chain there is a service that provides the trace data to the client that would need to be overridden or manipulated, but I can't find it.
Context:
- Windows 11,
- .NET 8
Grpc.AspNetCorev2.71.0- everything latest stable as of posting date
AddOpenTelemetrycalls. .NET's Observability with OpenTelemetry goes into more details, using Aspire Dashboard as a way to visualize the traces, no matter what app is used.