I would like to insert a middleware to Azure Durable Functions v4 (.NET 6) which gets a correlation id from the HttpTrigger and registers that into logger factory so that it is visible in application insights. Also vice versa; attaches correlation id to all outgoing requests. I do have multiple Azure Functions (some call each other) so I want to track a particular request by its CorrelationId.
I have tried guides here and here. However all of them has Program.cs class and register middleware by using that class. I only have startup and it looks like this:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services
.AddLogging()
.AddHttpClient();
}
}
How do I create a solution which fetches/attaches correlation id to requests/responses?
Something like: ...UseMiddleware<CorrelationIdFactory>()
Middlewares can only be registered in Azure Isolated Functions but not durable functions. Because host builder cannot be configured in Durable functions. However, MS team has just released support for Isolated Durable functions which can register middlewares and configure the host builder.
Here is the released library for Azure Isolated Durable functions.
This SDK can be used to build Durable Functions apps that run in the Azure Functions .NET Isolated worker process.
Here is how to create an Azure Isolated Durable function which sets correlationId on every http request. Program.cs
file:
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(workerApplication =>
{
// Register our custom middlewares with the worker
workerApplication.UseWhen<StampHttpHeaderMiddleware>((context) =>
{
// We want to use this middleware only for http trigger invocations.
return context.FunctionDefinition.InputBindings.Values
.First(a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
});
})
.Build();
//</docsnippet_middleware_register>
host.Run();
StampHttpHeaderMiddleware.cs
file:
internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
var requestData = await context.GetHttpRequestDataAsync();
string correlationId;
if (requestData!.Headers.TryGetValues("x-correlationId", out var values))
{
correlationId = values.First();
}
else
{
correlationId = Guid.NewGuid().ToString();
}
await next(context);
context.GetHttpResponseData()?.Headers.Add("x-correlationId", correlationId);
}
}
And this is our Http Trigger which you can get/set correlationId into:
static class HelloSequenceUntyped
{
[Function(nameof(StartHelloCitiesUntyped))]
public static async Task<HttpResponseData> StartHelloCitiesUntyped(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(StartHelloCitiesUntyped));
var correlationId = req.Headers.GetValues("x-correlationId").FirstOrDefault();
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(nameof(HelloCitiesUntyped));
logger.LogInformation("Created new orchestration with instance ID = {instanceId}", instanceId);
return client.CreateCheckStatusResponse(req, instanceId);
}
[Function(nameof(HelloCitiesUntyped))]
public static async Task<string> HelloCitiesUntyped([OrchestrationTrigger] TaskOrchestrationContext context)
{
string result = "";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "Tokyo") + " ";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "London") + " ";
result += await context.CallActivityAsync<string>(nameof(SayHelloUntyped), "Seattle");
return result;
}
[Function(nameof(SayHelloUntyped))]
public static string SayHelloUntyped([ActivityTrigger] string cityName, FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(SayHelloUntyped));
logger.LogInformation("Saying hello to {name}", cityName);
return $"Hello, {cityName}!";
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With