Currently I can retrieve ExecutionContext inside the function method, like this:
public async Task <IActionResult> Run ([HttpTrigger (AuthorizationLevel.Anonymous, "post", Route = null)], ILogger log, ExecutionContext context)
Is there any way I can retrieve ExecutionContext from my function startup?
I am sorry that you will not be able to get the ExecutionContext in startup. Because the ExecutionContext enables interaction with the Azure Functions execution environment when a function call is made.
However, in your function startup, your Azure Function is not yet processing an actual function call.
Related
I am running a v4 Azure Function in an isolated process. It is triggered by a message coming from a Service Bus queue. I have created a simple middleware and would like to get my hands on the incoming data (a simple string). How can I do that from the middleware itself? It doesn't seem FunctionContext is of use in this case.
public class SimpleMiddleware : IFunctionsWorkerMiddleware
{
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
await next(context);
}
}
The service bus message data and metadata is extracted and placed into the BindingData dictionary. Try looking at context.BindingContext.BindingData and find the key that exposes your message's data.
I have a console application which I want to convert to an Azure Function Timer Trigger app which will run every hour after some data processing and uploads are done. The data processing and uploads are being done via classes which are injected in the program.cs file of the console application. Somewhere in the classes I have a task.delay by 1hour where it will query new data after the data has been queried and uploaded for the first time. So, I copied the entire code of the console application with its packages to the Azure Function Timer trigger app. What I am trying to do is to run the program.cs file of the console application first in the azure function app in order to do its job (data processing, querying data, uploading data to azure...). and then initiate the timer trigger. Is that doable ? What line of code can I add in the run method of the azure function app to execute the program.cs file first and then initiate the trigger. You can find here the startup code of the azure function time trigger app.
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
namespace ExportServiceFunctionApp
{
public static class ExportServiceFunctionApp
{
[FunctionName("ExportServiceFunctionApp")]
public static void Run([TimerTrigger("0 0 */1 * * * ")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
}
}
There are a few solutions to achieve this.
Solution 1. Temporarily replace the timer trigger with http trigger
While debugging the app we just comment the first line of the original Run function and add an http trigger instead like this:
public static async Task Run([HttpTrigger] Microsoft.AspNetCore.Http.HttpRequest req, ILogger log)
// public static async Task Run([TimerTrigger("0 0 * * * *")] TimerInfo myTimer, ILogger log)
{
// YOUR REGULAR CODE HERE
}
Then when running the app you'll see an endpoint like this:
Just open the endpoint in browser (or postman) and the function will get called.
And right before pushing the code to the repo, just bring back the original Run function and remove the http trigger one.
Solution 2: Add another http trigger that calls the timer function
Add the following function to your app to expose an http trigger.
[FunctionName("Test")]
public static async Task Test([HttpTrigger] Microsoft.AspNetCore.Http.HttpRequest req, ILogger log)
{
Run(null, log);
}
The function basically calls the Run function.
So when you run the app, again you'll get an endpoint from the console that can be used from the browser to trigger the function.
The url will look like this:
http://localhost:7071/api/Test
Azure functions is event driven in nature. If function trigger means the event handled.
Run method of function means that function has triggered and its entry point for it.
If you want any processing or code execution before it you may need to write one more function and perform the steps and then trigger another function of either timer trigger or ant different type.
This code comes directly from the Durable Function startup in Visual Studio 2019
[FunctionName("Orchestrator_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
string instanceId = await starter.StartNewAsync("Orchestrator", null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
Where are the values for IDurableOrchestationClient starter & ILogger log coming from? Since these parameters wont be passed in the HTTP request, I'm assuming that there must be some IoC magic happening behind the scenes, but I'm not entirely sure what/where it is.
I'm assuming that there must be some IoC magic happening behind the scenes.
Correct.
Where is the value for IDurableOrchestrationClient coming from?
The IoC is from AddDurableTask (source). IDurableClientFactory creates IDurableClient which inherits from IDurableOrchestrationClient. You can find an example on usage of AddDurableTask here.
serviceCollection.TryAddSingleton<IDurableClientFactory, DurableClientFactory>();
Where is the value for ILogger coming from?
(as #Ian Kemp and #Nkosi already pointed out)
The IoC is from AddWebScriptHost (source). ILoggerFactory creates ILogger.
loggingBuilder.Services.AddSingleton<ILoggerFactory, ScriptLoggerFactory>();
I have a very simple function and boiled it down further more to trouble shoot this issue, I read some previous questions on SO about similar issues but they dont apply to my issue I believe.
Function code
[FunctionName("XXXItems")]
public static async System.Threading.Tasks.Task RunAsync([TimerTrigger("0 45 6 * * 1-5")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"XXXItems --> Timer trigger function executed at: {DateTime.Now}");
}
I have configure the APPINSIGHTS_INSTRUMENTATIONKEY in the function settings
But nothing gets logged and I am a bit lost as how to debug this
I am looking to use Microsoft.Azure.WebJobs.ExecutionContext to get the InvocationId while a function is running, but is there a way to get this while outside of the actual function call.
So if a calling class needs to have some kind of context it can use this. Is it possible?
When you run a function you have ExecutionContext
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log, ExecutionContext context)
{
return req.CreateResponse(System.Net.HttpStatusCode.OK, context.InvocationId);
}
So if you call any method you probably will need to path this id to it. I am not sure if there is any kind of static helper for that.
You have to thread that as a parameter through all your calls, trying to solve this with some kind of ambient storage, like TLS or AsyncLocal is probably not the best approach but it will probably work.
If you don't use async APIs you might get away with:
[ThreadLocal]
public static Guid InvocationId;
...but if you do use async, you can try:
public static AsyncLocal<Guid> InvocationId = new AsyncLocal<Guid>();
Good luck!