I have an Azure Function app (using the newer .net class library
approach) that I initialize with a static constructor so as to share generated resources.
Official documentation recommends sharing resources like an HttpClient
in a web api.
The discussion at the bottom of the docs on Azure Functions C# script developer reference mentions placing an HttpClient
in a static variable to prevent re-instantiation on each request since it is thread-safe.
I'm wondering two things.
Is a static constructor ok for initializing my expensive to 'set-up' resources used by all requests?
If this approach is ok, how should error logging be configured in a static constructor if the initialization of these resources fails?
Here is my class definition
public static class HttpSubmissionTrigger
{
private static readonly SendGridClient sendGridClient;
private static readonly Func<IDictionary<string, object>, string> template;
private static readonly EmailAddress senderEmail;
private static readonly string emailTitle;
private static readonly HttpResponseMessage errorResponse;
static HttpSubmissionTrigger()
{
// ... initialization of above static members here
}
public static async Task<HttpResponseMessage> Run(...)
{
// ... use static members here to send emails, respond to client
}
}
I perform error logging in my Run
method using the DI of the TraceWriter
, which works fine. I can use this to view errors in the Azure portal console for the function, but static constructors can't have parameters, so that approach won't work for resource initialization.
There is another reference to this question in the Azure function docs but the response was to ask the question here.
A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed only once. It is called automatically before the first instance is created or any static members are referenced.
Static Constructors should not have any parameters. static constructor does not contain parameters. static constructor is called when the execution of the class is started. It is the first member to be execute in the class.
Also, you can have a static constructor in a static class or a non-static class. A static constructor is used to initialize the static members of a class. The static constructor of a class is invoked the first time a static member of the class is accessed.
That's why you can see in the output that Static Constructor is called first. Times of Execution: A static constructor will always execute once in the entire life cycle of a class. But a non-static constructor can execute zero time if no instance of the class is created and n times if the n instances are created.
You're not limited to the static constructor to perform initialization logic for shared resources.
One approach, of a few possible, would be to have a class managing those resources for you, where you'd perform static initialization when your function is invoked, passing loggers and other relevant information, ensuring appropriate checks to avoid double initialization.
The function filters feature we'll be releasing soon will help with these scenarios as well: https://github.com/Azure/azure-webjobs-sdk/wiki/Function-Filters
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