I have Azure function with timer trigger.
public static void Run([TimerTrigger("0 */15 * * * *"), Disable("True")]TimerInfo myTimer, TraceWriter log)
Here the Disable("true") is not working. it generates the function.json as
"disabled": "True", which is not correct. It should be "disabled": True,
Disable only accepts string value.
Is there any way to change this? or any other way to disable function?
Disable properties default values is true.
Use Disable() instead of Disable("true").
So the code will look like
public static void Run([TimerTrigger("0 */15 * * * *"), Disable()]TimerInfo myTimer, TraceWriter log) .
If you want to enable the function use Disable("False").
Functions 2.x can be disabled individually via local.settings.json in the following manner
{
"IsEncrypted": false,
"Values": {
"AzureWebJobs.MyFunctionNameOne.Disabled": "true",
"AzureWebJobs.MyFunctionNameTwo.Disabled": "true",
...
}
}
Ref: https://learn.microsoft.com/en-us/azure/azure-functions/disable-function#functions-2x---all-languages
I wanted to add this answer, as I have been searching for it as well and I believe I found a good way to disable functions for debugging/development purposes (and to avoid these local changes get into the deployment pipelines/source control).
I combine the #if DEBUG statements with the Disable(string SettingsName) attribute:
The following piece of code shows different things at work:
The Disable attribute is not using the parameter to indicate True or False as a value, but it refers to an appsetting (that you can put in the local.settings.json file). See the second snippet in this post. So, just by changing that settings in the appsettings file, I can enable and disable triggers easily, without impacting my git repo or deployment pipelines.
The other interesting thing is the RunOnStartup = true parameter when using a TimerTrigger. This one (which I only enable with the DEBUG compiler directives), will allow me to trigger the timer function immediately, without waiting for the next CRON cycle to happen. (an alternative would be to do a post to your local functions endpoint, as described in this stackoverflow post). So again, when assuming you run your production workloads in the RELEASE configuration, this is only impacting your local development environment and not your development team or releases.
1st snippet (attributes)
#if DEBUG
[Disable("disable-transactioncrawler")]
#endif
[FunctionName("TransactionCrawler")]
public async Task Run([TimerTrigger("50 */10 * * * *"
#if DEBUG
, RunOnStartup = true
#endif
)]TimerInfo myTimer, ILogger log)
{
// Logic comes here
}
2nd snippet (local.appsettings.json)
{
"Values":
{
"disable-transactioncrawler": false
}
}
The following 'solutions' typically impact your production code, which can lead to issues:
Just using Disable() is not allowing you to configure/change it afterwards
Updating the host.json file to only include the triggers you want to run is also risking to have this change arriving in production.
Have you tried modifying the host.json inside your solution? It has the following properties for you to specify which functions to load on runtime.
// Array of functions to load. Only functions in this list will be enabled.
// If not specified, all functions are enabled.
"functions": ["QueueProcessor", "GitHubWebHook"]
Note that if you have multiple Function App projects in your solution, you will also need to make to change to their corresponding host.json (i.e. each project has their own host.json)
Documentation: https://github.com/Azure/azure-webjobs-sdk-script/wiki/host.json
The string typed value - "disabled": "true" also could disable the function. Please see the test result as following.
Here is my function definition.
public static void Run([TimerTrigger("0 */5 * * * *"),Disable("true")]TimerInfo myTimer, TraceWriter log)
Here is the published function on Azure portal.
I tried disabling using local.settings.json, and when debugging locally the emulator window actually says that the named function is disabled, but calls it anyway! This is the same in VS2017 and 2019.
The workaround I'm currently using is to test for this app setting as the first line in my function and return immediately:
if(ConfigurationManager.AppSettings["AzureWebJobs.TimerTriggeredFunction.Disabled"] == "true") return;
Related
I want to add Custom Properties to the RequestTelemetry generated for the Azure function(V3) written in C#.
Thanks to this StackOverflow post, I managed to achieve this for the function with HttpTrigger binding.
var requestTelemetry = req.HttpContext?.Features.Get<RequestTelemetry>();
requestTelemetry.Properties.Add("MyProp", "Some value");
However, when I try to do same thing for another function with BlobTrigger binding, it became confusing. The first challenge is:
How to get current RequestTelemetry in a function that is using
BlobTrigger binding?
In a function with HttpTrigger binding, the function is injected with HttpRequest parameter
public async Task<IActionResult> Upload(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "upload/{name}")] HttpRequest req,
string name,
ILogger log,
ExecutionContext context)
{
...
}
So we can get current RequestTelemetry using HttpRequest. However, what about a function with BlobTrigger:
[FunctionName("Create-Thumbnail")]
public async Task CreateThumbnail([BlobTrigger("input/{name}", Source = BlobTriggerSource.EventGrid, Connection = "AzureWebJobsStorage")] Stream image,
IDictionary<string,string> metadata,
string name,
ExecutionContext context)
{
...
}
I have tried injecting HttpRequest and using same way as HttpTrigger function. But it didn't work.
After hours extensive research, I couldn't find any documentation or posts that are related to this question.
Can anyone provide some tips for this?
AFAIK there is no http request when using a blob trigger. You can still add custom properties to the telemetry generated during the execution by setting properties like this:
// The current telemetry item gets a property.
// Useful if the function is not triggered by an http request
Activity.Current.AddTag("setUsingTag", "setUsingTag");
// Subsequent telemetry gets this property attached
Activity.Current.AddBaggage("setUsingActivityBaggage", "setUsingActivityBaggage");
When using Baggage instead of a Tag the custom property is added to all telemetry generated during the execution, like dependency calls etc.
See also this github thread. It also mentions there might be a bug introduced in a later version of AI that might force you to downgrade AI for this to work.
Thanks to this GitHub issue, this is finally working after downgrading System.Diagnostics.DiagnosticSource to version 4.6
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.6.0" />
After upgrade to .NET5 for Azure Function this signature throws the exception below.
I've implemented it according to the documentation here https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-event-grid-trigger?tabs=csharp%2Cbash
[Function(nameof(CustomerCreated))]
public async Task CustomerCreated([EventGridTrigger] EventGridEvent eventGridEvent, FunctionContext functionContext)
{
// My implementation
}
System.NotSupportedException: 'Deserialization of types without a
parameterless constructor, a singular parameterized constructor, or a
parameterized constructor annotated with 'JsonConstructorAttribute' is
not supported. Type 'Azure.Messaging.EventGrid.EventGridEvent'. Path:
$ | LineNumber: 0 | BytePositionInLine: 1.'
How can I receive the event from EventGrid?
The new way of doing this seems to be CloudEvent from the Azure.Messaging namespace.
(A side note is that the data properties are case-sensitive, I'm not sure if they were before.)
public async Task CustomerCreated([EventGridTrigger] CloudEvent eventGridEvent, FunctionContext functionContext)
{
// [...]
}
UPDATE:
This breaks when deploying to Azure and receiving events from a real event grid with an Azure Function as endpoints. But works fine when testing locally using ngrok and webhook. Back to square one.
After endless googling with outdated examples I found a note in this document, pointing to this example showing that you need to create a custom type (looking just like the EventGridEvent).
After testing I found that this actually works:
Pass a string instead of EventGridEvent and parse the actual event with the utility function from EventGridEvent.
[Function(nameof(CustomerCreated))]
public async Task CustomerCreated([EventGridTrigger] string data, FunctionContext functionContext)
{
var eventGridEvent = EventGridEvent.Parse(BinaryData.FromString(data));
// Rest of code
}
Another related caveat is that you can't create the function from the portal but need to run it from the command line like:
az eventgrid event-subscription create --name customer-created \
--source-resource-id <event-grid-topic-resource-id> \
--endpoint <azure-func-resource-id> --endpoint-type azurefunction
(The resource id:s can be found at http://resources.azure.com/)
Hello Microsoft;
Running Azure Functions on .NET5 doesn't feel very GA with this approach. I really hope to be able to pass typed objects like EventGridEvent from other Azure services with official libraries.
I really think that the EventGridEvent on .NET5/dotnet-isolated should be compatible with Azure Functions at the same level as on previous .NET versions and as in the public examples.
I am using Azure Queue Trigger for my Function. But the Infrastructure (e.g., Queue, Blob storage) for that Function is not in place. So, the Azure storage connection string will also be empty. But while running the Function App, it is expecting the connection string and throwing an exception at runtime. Even though I disabled the Function using the [Disable("MY_TIMER_DISABLED")] attribute.
Exception
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
The reason I found is that while running the Function App, the Startup is invoking all the Functions, and then it is reading the properties associated with those Functions. So, at the initial invoke, it is expecting the Queue, Connection String, etc., even though the function is Disabled.
public class UserDataRetryFunction()
{
[FunctionName(UserDataRetryFunction)]
[Disable("AzureWebJobs.UserDataRetryFunction.Disabled")]
public async Task RetryData([QueueTrigger("%RetryQueueName%", Connection = "%ConnectionStrings:StorageConnectionString%")])
{
// Process the Queue Message
}
}
appsetings.json
{
"IsEncrypted": false,
"RetryQueueName" : "retry-response-queue",
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobs.UserDataRetryFunction.Disabled": "true"
},
"ConnectionStrings": {
"StorageConnectionString" : "",
}
}
I have tried many documents and sites, but could not able to find the solution.
Some of the links I’ve evaluated are stated below.
https://learn.microsoft.com/en-us/azure/azure-functions/disable-function?tabs=portal
https://forums.asp.net/t/2165324.aspx?Value+cannot+be+null+Parameter+connectionString+
Value cannot be null. Parameter name: connectionString appsettings.json in starter
The behaviour you're setting is expected. In Azure disabling a function only means disabling the trigger as you have done and as detailed in the link you referenced. This disables the trigger but doesn't stop the entire function.
If you wish to stop the entire function you can do so in the Azure Portal.
You can also use the AZ CLI as follows:
az functionapp stop --name MyFunctionApp --resource-group MyResourceGroup
With PowerShell you can stop a function with the following command:
Stop-AzFunctionApp -Name MyAppName -ResourceGroupName MyResourceGroupName
I have a simple C# HttpTrigger Azure function that retrieves data from CosmosDB:
namespace urda
{
public static class GetAccount
{
[FunctionName("GetAccount")]
public static IActionResult Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"get",
Route = "account/{id}")] HttpRequest req,
[CosmosDB(
"UrdaDemo",
"Accounts",
ConnectionStringSetting = "CosmosDBConnection",
SqlQuery = "select * from Accounts a where a.id = {id}")]
IEnumerable<Account> accounts,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (Account account in accounts)
{
log.LogInformation(account.id);
}
return new OkObjectResult(accounts);
}
}
}
The function worked fine until a few days ago (last checked on Nov. 22) and now it does not. It gives me the following error?
Function (Urda/GetAccount) Error: Microsoft.Azure.WebJobs.Host: Error indexing method 'GetAccount'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'accounts' to type IEnumerable`1. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
I have not changed anything nor redeployed the function and am not sure why I am getting this error? What is meant by "make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage()..."?
I recreated and redeployed the functions using Visual Studio and it worked fine. Upon comparison of the artifacts, the only difference between my Visual Studio Code project and Visual Studio project I found was in host.json:
{
"version": "2.0",
- "extensionBundle": {
- "id": "Microsoft.Azure.Functions.ExtensionBundle",
- "version": "[1.*, 2.0.0)"
- }
}
Lines marked with a "-" were no longer needed. That fixed the problem. BUt on previous deployments, these lines were there and all was good. Go figure.
I have a Azure Function like that
[FunctionName("Function1")]
public static void Run([ServiceBusTrigger("myqueue", AccessRights.Manage, Connection = "AzureWebJobsServiceBus")]string myQueueItem, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {myQueueItem}");
}
I want to dynamic bind myqueue and AzureWebJobServiceBus connection string in a startup or OnInit of app without as method's parameter above. I mean, I want to a method run first of all like Program.cs in WebJob to binding or start up global variables. Can I do that in Azure Function and how to do it?
Many thanks
The attributes here are compiled into a function.jsonfile before deployment that has the info on what the binding talks to. Often things like the connection string reference app settings. Neither of these can be modified within the code itself (so a Program.cs couldn’t modify the function.json binding).
Can you share any more on your scenario? If you have multiple queues you want to listen to could you deploy a function per queue? Given the serverless nature of Functions there isn’t a downside to having extra functions deployed. Let me know - happy to see if we can help with what you need.
Edit
The suggestion below doesn't work for a Trigger, only for a Binding.
We have to wait for the team to support Key Vault endpoints in Azure Functions, see this GitHub issue.
I think what you are looking for is something called Imperative Bindings.
I've discovered them myself just yesterday and had a question about them also. With these type of bindings you can just dynamically set up the bindings you want, so you can retrieve data from somewhere else (like a global variable, or some initialization code) and use it in the binding.
The thing I have used it for is retrieving some values from Azure Key Vault, but you can also retrieve data from somewhere else of course. Some sample code.
// Retrieving the secret from Azure Key Vault via a helper class
var connectionString = await secret.Get("CosmosConnectionStringSecret");
// Setting the AppSetting run-time with the secret value, because the Binder needs it
ConfigurationManager.AppSettings["CosmosConnectionString"] = connectionString;
// Creating an output binding
var output = await binder.BindAsync<IAsyncCollector<MinifiedUrl>>(new DocumentDBAttribute("TablesDB", "minified-urls")
{
CreateIfNotExists = true,
// Specify the AppSetting key which contains the actual connection string information
ConnectionStringSetting = "CosmosConnectionString",
});
// Create the MinifiedUrl object
var create = new CreateUrlHandler();
var minifiedUrl = create.Execute(data);
// Adding the newly created object to Cosmos DB
await output.AddAsync(minifiedUrl);
There are also some other attributes you can use with imperative binding, I'm sure you'll see this in the docs (first link).
Instead of using Imperative Bindings, you can also use your application settings.
As a best practice, secrets and connection strings should be managed using app settings, rather than configuration files. This limits access to these secrets and makes it safe to store function.json in a public source control repository.
App settings are also useful whenever you want to change configuration based on the environment. For example, in a test environment, you may want to monitor a different queue or blob storage container.
App settings are resolved whenever a value is enclosed in percent signs, such as %MyAppSetting%. Note that the connection property of triggers and bindings is a special case and automatically resolves values as app settings.
The following example is an Azure Queue Storage trigger that uses an app setting %input-queue-name% to define the queue to trigger on.
{
"bindings": [
{
"name": "order",
"type": "queueTrigger",
"direction": "in",
"queueName": "%input-queue-name%",
"connection": "MY_STORAGE_ACCT_APP_SETTING"
}
]
}