While using Azure functions, I have a situation where I want a few functions in "disabled" mode for a function app, while others to be enabled. The thing is, I don't want to do it manually using the functions screen where individual functions could be enabled/disabled easily. There is this article that says Functions 2.x supports this (Functions 1.x is not a choice for me).
https://learn.microsoft.com/en-us/azure/azure-functions/disable-function
It is just that the article is a little vague about what needs to be done. It says and I quote >
In Functions 2.x you disable a function by using an app setting. For example, to disable a function named QueueTrigger, you create an app setting named AzureWebJobs.QueueTrigger.Disabled, and set it to true. To enable the function, set the app setting to false.
I tried this, but it doesn't work as documented. I have a function app called foo and a function called bar. I have tried both:
disabled: true in function.json
as well as:
foo: {
bar: {
disabled: true
}
}
After making these changes and redeploying there is no effect on the UI. What am I missing?
The recommended approach is by using app settings, which you can do by going to the portal. [Note: They don't mean function.json when they say app settings.]
Option 1: Using App Settings
In azure portal, navigate to your function app foo -> Confuguration, and you should see Application Settings tab with a few variables already defined. You need to create a new variable by clicking New application setting button. Set name as AzureWebJobs.bar.Disabled and value as true. Note that the function app name foo doesn't figure in the variable name.
Option 2: Using host.json
Because you are looking for disabling a function from code, you can try doing this in host.json. Note that this is intended for local development, and not recommended for prod, but it works.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-host-json#functions
{
"functions": [ "function1", "function2" ] // Don't list function "bar" here, and it would get disabled.
}
Note that the portal will not show this correctly, and list "bar" as enabled, but you will get 404 when hitting that function.
Option 3: Using Disable attribute
If you are using C# You can also use the [Disable] attribute. This is a Functions 1.x construct, but it works in 2.x as well. Similar to above, the portal UI will not show this correctly.
[Disable]
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
}
Option 4: By removing FunctionName attribute
Only if you are using C#. This might sound counter-intuitive, but if you remove the FunctionName attribute from your function, it won't be treated as such.
// [FunctionName("Function1")] // Comment this or delete this line to disable this function
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
}
This should work in both runtimes. The function wouldn't show in the azure portal.
I used the [Disable("myAppSetting")], but it did not disable my function at first. Turns out the app settings from the App Config Azure resource do not have an impact on this behavior. It needs to be put directly in the app settings of the Azure Function itself for it to work. The Azure portal however does show correctly that the function is disabled.
Related
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.");
}
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?
I am working through replacing some WebJobs with Azure Functions and appear to have all working OK except for logging of what is going on.
I have tried using the default function created within VS2017 and have run it locally with no problems. When deployed to Azure I cannot see the detail of the log entries anywhere.
Using Kudu to view the logs seemed OK except that I noticed that the log param of a function invocation is always null. This can't be the case as the function does run, and gives the expected output, and would fail if log was really null.
Here's what the function looks like:
public static class Function1
{
[FunctionName("Function1")]
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 name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
}
I would have expected to see the output of the log within Kudu by going to https://xxx.scm.azurewebsites.net/azurejobs/#/functions but I can't see the details when I toggle the output - it never loads (and it shows the log param as being null - perhaps is being resolved by DI though).
Whilst this function is simply a test I do have other more complicated functions that I need the logging details for.
I am not keen on investigating Application Insights as this seems way, way overkill for such simple functions that will not be used very heavily.
For v2 functions in runtime 2.x, doc explains
the WebJobs dashboard in the portal, which used the AzureWebJobsDashboard setting is replaced with Azure Application Insights, which uses the APPINSIGHTS_INSTRUMENTATIONKEY setting.
Like what you have seen, with AzureWebJobsDashboard setting, the log param is null and no log there. I am afraid the replaced with was enforced and Dashboard has been deprecated.
As for the usage of Application insights, we could just leverage the basic log monitoring without any further investigation. After creating it and add its instrumentationkey in Application settings, we could see the Monitor view is similar to Dashboard.
If we don't like it anyway, logs in kudu(https://<functionAppName>.scm.azurewebsites.net/DebugConsole) are ready there(D:\home\LogFiles\Application\Functions\function\<functoinName>).
Create a new Azure Function App from the Azure Portal. Add a new function to it. You will be presented with a warning icon with the following text:
Cannot Upgrade with Existing Functions
Major version upgrades can introduce breaking changes to languages and bindings. When upgrading major versions of the runtime, consider creating a new function app and migrate your functions to this new app.
My question is what action is required? Is it simply a warning that a future upgrade might cause issues? Perhaps is it related to the GitHub commentary about new template versions in Visual Studio
Note: deleting the all functions from the function app, causes the issue to disappear.
You are right, it's just a tip for you to refer, no action required.
When you create a function app in portal, the app uses the runtime ~1 by default.
Before you create any function in the app, you are allowed to change the runtime version in the function app settings panel.
After that, it's not recommended and also not allowed to change as the button is grey in this panel, with the warning you see. Because the runtime upgrade may cause error to your code depending on the specific runtime.
And as you see, once no function exists in the app, the warning disappears and is able to change the runtime again.
The application settings panel allows us to change FUNCTIONS_EXTENSION_VERSION (i.e. the runtime)between ~1 and beta despite existing functions, but still remember the runtime switch may cause breaking changes.
Update
Preview beta runtime has been GA and corresponding FUNCTIONS_EXTENSION_VERSION is changed to ~2, when we create a function app, default runtime is changed to ~2 as well.
The warning is there so you wouldn't go and possibly break your current v1 functions when upgrading the runtime to v2.
Consider for example the following code examples:
V2 template:
[FunctionName('Function1')]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, 'get', 'post', Route = null)]HttpRequest req, TraceWriter log)
{
V1 template:
[FunctionName('Function1')]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, 'post', Route = null)]
HttpRequestMessage req,
TraceWriter log)
These two function definitions use different versions of the runtime.
If you'd, at the press of a button, go and update the runtime, then you'd break your code. Hence the suggestion, create a new function app entirely using the new version and migrate your code to it instead of just updating the runtime.
Code snippet I found here.
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.