Implications of separating Http Request-triggered Azure Functions by http verb - azure

I'm still trying to learn about Azure Functions and best practices, but as I understand there are two ways to separate logic by http verb (GET, POST, etc.). Is there a standard or best practice that would prefer either of the two below methods? And more importantly, is there a cost difference between the two methods when running in Azure, assuming the underlying logic stays the same?
Method A:
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req)
{
if (req.Method == HttpMethods.Get)
{
// do stuff here
}
else if (req.Method == HttpMethods.Post)
{
// do stuff here
}
}
}
Method B:
public static class GetFunction
{
[FunctionName("GetFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req)
{
// do stuff here
}
}
public static class PostFunction
{
[FunctionName("PostFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req)
{
// do stuff here
}
}

In short the answer to your question about pricing is, IT will be the same for both. It will be equal to the time your logic runs. You should use Consumption plan. If you are looking for cost savings. Microsoft says
"
Azure Functions consumption plan is billed based on per-second resource consumption and executions. Consumption plan pricing includes a monthly free grant of 1 million requests and 400,000 GB-s of resource consumption per month per subscription in pay-as-you-go pricing across all function apps in that subscription."
Here is a link to more details.
https://azure.microsoft.com/en-us/pricing/details/functions/
As far as your second question is concerned. IMO you should use separate functions for get and post. In this way you can separate the endpoints and handle both calls differently. But this kind a breaks the RESTful API practice. So its give and take. :)

You had asked if there is a standard or best practice for using GET or POST. Generally, in REST world, you use GET if you are fetching a resource and POST when you want to create a new resource. So, it basically depends on what you are trying to achieve using the Function. Found a similar questions here > https://stackoverflow.com/a/504993/5344880 and When do you use POST and when do you use GET?
Regarding the pricing, it is based on the number of executions and memory and not by logic. This link will provide more details https://azure.microsoft.com/en-in/pricing/details/functions/ Please do note that there is hard timeout of 10 minutes for Azure Functions
Hope this helps.

Related

Supported bindings for Singleton scopeId on HTTP Trigger Azure Function

I am unclear on how the scopeId parameter of the SingletonAttribute works. Specifically does the scopeId parameter work for HTTP Trigger Azure Functions when you bind it to a route parameter? How does the binding work? What variables/values can I bind to?
For example:
[Singleton("{input}", Mode = SingletonMode.Listener)]
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "v1/{input:length(1,30)}")] Microsoft.AspNetCore.Http.HttpRequest req, string input, ILogger log) {
return new OkObjectResult(input + " world");
}
A HTTP POST request to this function with the URI 'v1/hello' would return: "Hello world".
But would the Singleton attribute work such that all requests to 'v1/hello' would run serially whereas two simultaneous requests with one to 'v1/first' and the other to 'v1/second' would run in parallel?
I see from this answer that for Service Bus Triggers you can bind to properties within the Message object directly.
Also in the documentation there is an example of a Queue Trigger Function with scopeId binding to a property in the WorkItem object.
It's unclear what's supported for HTTP Trigger Functions.
You have two ways to implement singleton mode in Azure function.
The first:
You can do this by setting WEBSITE_MAX_DYNAMIC_APPLICATION_SCALE_OUT or maxConcurrentCalls.
Singleton Azure function running as separate instances
The second type:
Create a complete Function project, similar to webapp, and implement it in Configure.
Use dependency injection in .NET Azure Functions
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient();
builder.Services.AddSingleton<IMyService>((s) => {
return new MyService();
});
builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
}
}
I got a reply from Microsoft on GitHub: https://github.com/MicrosoftDocs/azure-docs/issues/69011#issuecomment-771922910
"Binding expressions for Singleton have the same behavior as those for general input/output bindings. That is, any binding data from the trigger is available for reference.
In the case of HttpTrigger, that includes any POCO members if you’re binding to a POCO type, as well as any route parameters.
In regards to your code, SingletonMode.Listener is not what you want for your requirement. If you're just trying to serialize individual invocations of the function then you should use the default mode, i.e. [Singleton(“{input}”)].
To answer your question – yes, this would serialize all invocations of v1/hello, allowing v1/first and v1/second to run concurrently."

Usage of Azure App Configuration's Feature Flags in Azure Functions

I'm working on exploring the following 2 features of Azure App Configuration in Azure Function's Http Trigger
Externalizing the App Settings
Feature Flags
Below is how i'm getting the reference of the configuration
So, when I use _configuration["SomeAppSettingKey"], I'm able to retrieve the value. So, I'm able to achieve #1 feature mentioned above.
My Question is, How do we retrieve the Feature Flag information? I have tried the below ways.
I would appreciate if someone could help me in understanding how to retrieve it in Azure Functions (I'm using V3)? A Sample code or any reference to documentation would be helpful.
Thanks.
Update1:
I can deserialize the json content as shown below. But, is this is the right approach?
Where FeatureManager is a class that I have defined as shown below.
all you need is to call UseFeatureFlags() function as part of AddAzureAppConfiguration to let the App Configuration provider know you want to use feature flags. An example can be found following the link below. It uses the FunctionsStartup and dependency injection (DI) of Azure Functions. An instance of a feature manager is put into the DI.
https://github.com/Azure/AppConfiguration/blob/master/examples/DotNetCore/AzureFunction/FunctionApp/Startup.cs
The link below shows how you can obtain the instance of IFeatureManagerSnapshot from DI and use it as part of your Azure Functions call.
https://github.com/Azure/AppConfiguration/blob/master/examples/DotNetCore/AzureFunction/FunctionApp/ShowBetaFeature.cs
Deserialize JSON is not a good idea, every time you will add new key you need to modify your class.
private static IConfiguration Configuration { set; get; }
static Function1()
{
var builder = new ConfigurationBuilder();
builder.AddAzureAppConfiguration(Environment.GetEnvironmentVariable("ConnectionString"));
Configuration = builder.Build();
}
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string keyName = "TestApp:Settings:Message";
string message = Configuration[keyName];
return message != null
? (ActionResult)new OkObjectResult(message)
: new BadRequestObjectResult($"Please create a key-value with the key '{keyName}' in App Configuration.");
}

Does Azure Function App run several instances at the same time?

If I have a Function app like so
public static class Function1
{
private static readonly HttpClient httpClient = new HttpClient();
[FunctionName("SomeRandomFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
ulong i = 0;
Thread.Sleep(10000);
return (ActionResult)new OkObjectResult($"Hello thread Finished.");
}
}
Are different instances of the function created if different e.g. mobile devices trigger the function at the same time?
I had inferred this from this quote "When you're using the Premium plan, instances of the Azure Functions host are added and removed based on the number of incoming events just like the Consumption plan". I'm on S1 plan.
However when I tested a thread.sleep in function "SomeRandomFunction" like above with two calls for this same function from two different private browser windows, the second call only starts when the first one finished. Why does this happen if it's possible to create several instances of the same function app?
Or is a multi-threading implementation required to have several instances running at the same time?
Thank you
Are different instances of the function created if different e.g. mobile devices trigger the function at the same time?
Yes. From the docs:
The unit of scale for Azure Functions is the function app. When the
function app is scaled out, additional resources are allocated to run
multiple instances of the Azure Functions host. Conversely, as compute
demand is reduced, the scale controller removes function host
instances. The number of instances is eventually scaled in to zero
when no functions are running within a function app.
Azure Functions scale and hosting

Can I create non static Azure function class in C#, what are the consequences?

This non static class is required for constructor injection in Azure function and collection of custom telemetry events.
If we create an azure function app in visual studio, it creates default with static keyword like this:
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
telemetryClient.TrackEvent(new Exception("Function started"));
}
But to use constructor dependency injection (for Temeltry client, i am using it), we need to remove static keyword.
public Function1(TelemetryClient telemetryClient)
{
_telemetryClient = telemetryClient;
}
Previously, Azure Functions only supported static classes/methods. This restriction made DI via constructor impossible. However later the support for non-static classes/methods was implemented (see Support Instance Functions).
So if you need to use DI via constructor, just change it to non-static. There are no consequences.
This is not entirely true though - I just ran into some trouble with non static timer triggered functions. In my case I needed dependency injection in terms of entity framework, but this non static instance is now causing me trouble in order to call the admin endpoint to trigger the function when doing development locally.
See more on how to normally invoke static timer triggered functions here:
What is the simplest way to run a timer-triggered Azure Function locally once?

Azure Functions - How to change the Invocation ID within the function?

I have a series of Azure Functions, and I'd like to keep track of them by the InovcationId. In Application Insights, the InvocationId is called the operation_Id.
What I'm trying to do is set the operation_Id to be the same across several different Azure Functions.
I can read this property inside the Azure Function when I pass in ExecutionContext by following this answer, but I can't seem to alter it. Is there some way to change this value from inside the Azure Function?
public static class TestOperationId
{
[FunctionName("TestOperationId")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
ILogger log,
ExecutionContext exeCtx
)
{
var input = await req.Content.ReadAsStringAsync();
log.Info(input);
exeCtx.InvocationId = Guid.Parse(input);
return req.CreateResponse(HttpStatusCode.OK);
}
}
The definition for the InvocationId field is defined as
Provides the invocation ID, uniquely identifying the current invocation
Azure Functions doesn't provide changing this, as it would mean that code could override the platform's methods to detect unique invocations of Functions, which would interfere with things like Billing and Metrics for the platform.
It sounds like what you really want is cross-function correlation. There is work being done with the Application Insights team to help support this, but in the meantime, you can see solutions that others are currently utilizing, like here.

Resources