Azure Queue Trigger Function - Local Integration - azure

I am creating a simple queue triggered azure function using Visual Studio. I am connecting it with my storage account, but for some reason its not working. Any help is appreciated.
This is my code: (auto-generated by VS)
[FunctionName("QueueTest")]
public static void Run([QueueTrigger("my-queue", Connection = "")]string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
This is my local.settings.json
{
"IsEncrypted": false,
"Values":{
"AzureWebJobsStorage":"DefaultEndpointsProtocol=https;AccountName=accountname;AccountKey=accountkey"
}
}

Queue trigger by default use a AzureWebJobsStorage account. All you need to do is just remove Connection parameter from the attribute:
[FunctionName("QueueTest")]
public static void Run([QueueTrigger("my-queue")]string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
}
Ideally if you are a Windows user, use Azure Storage Emulator to connect to local queues. Afterwards change the connection string in your local.settings.json file:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true",
}
}
If you are not a Windows user, you must connect to queues hosted on the Azure platform. To do this, find the storage account linked to your functions and copy the connection string from his settings (Storage Account -> Access Keys -> Connection string)

So I figured out the issue. All the configurations were fine. The issue was, Azure Function Version of my function app was 1 but for some reason, probably because of latest SDK/WebJobs, version 1 was not working correctly. So I had to create another function app with AzureFunctionVersion 2 and all worked fine.

You need to add the connection string of your queue storage account to the local.settings.json and then supply the name of the connection string as the Connection parameter of the QueueTrigger, e.g. in local.settings.json
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=accountname;AccountKey=accountkey",
"MyStorage": "DefaultEndpointsProtocol=https;AccountName=accountname2;AccountKey=accountkey2;EndpointSuffix=core.windows.net"
}
and in your code
[QueueTrigger("my-queue", Connection = "MyStorage")]string myQueueItem

Related

Event Hub Trigger Azure Function Not Being Triggered When Using Non-Default Consumer Group

So I have a basic setup for listening on events coming in to Event Hub, using an Event Hub Trigger function, defined as follows:
[FunctionName("myfunction")]
public async Run([EventHubTrigger(myeventhub, Connection = "EventHubConnectionAppSetting", ConsumerGroup = %myconsumergroup%)], EventData eventHubMessage, ILogger logger)
Where the values for the connection and consumergroup parameters are in my local settings.
Running my function and sending events via Postman (properly authenticated), the function is not triggered.
The only way the function is every triggered is if I remove the ConsumerGroup from the parameters, which will cause it to point to the $Default consumer group for the event hub:
[FunctionName("myfunction")]
public async Run([EventHubTrigger(myeventhub, Connection = "EventHubConnectionAppSetting"], EventData eventHubMessage, ILogger logger)
My goal is to keep my custom consumer group and have the function trigger for events coming into that consumer group.
I will mention that I'm testing this out locally, and using local storage:
AzureWebJobsStorage="UseDevelopmentStorage=true"
But obviously the event hub in question is an actual created resource on Azure, with the relevant consumer group existing under it as well.
You can directly use the consumer group name in the function, like below:
[FunctionName("myfunction")]
public async Run([EventHubTrigger(myeventhub, Connection = "EventHubConnectionAppSetting", ConsumerGroup = "myconsumergroup_name")], EventData eventHubMessage, ILogger logger)
Or if you want to use this mode %myconsumergroup%, you can refer to this steps as below:
In local.settings.json(remember right click the file -> select properties -> set "Copy to Output Directory" as "copy if newer"), define the key-values like below:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EventHubConnectionAppSetting": "xxxx",
"EventHubConsumerGroup": "your_consumergroup_name"
}
}
then in the function method, define the function like below:
[FunctionName("Function1")]
public static async Task Run([EventHubTrigger("eventhub_name", Connection = "EventHubConnectionAppSetting",ConsumerGroup = "%EventHubConsumerGroup%")] EventData[] events, ILogger log)
Note: I use the latest packages for the function.

How do I pass in the storage account connection string for a CosmosDBTrigger?

I'm trying to figure out the proper way to pass in a storage account connection string to a CosmosDBTrigger. I have a function that runs when there is a change on a CosmosDB container. This function copies image blobs from one container to another. If you look at the code below, I have commented out the line where I am trying to fine the storage account that I want to connect to. This function runs when that is commented out. It does not run when I have that un-commented. Why?
public static class Function1
{
[FunctionName("ImageCopier")]
public static async Task Run([CosmosDBTrigger(
databaseName: "MyDatabase",
collectionName: "Orders",
ConnectionStringSetting = "databaseConnection",
CreateLeaseCollectionIfNotExists = true,
LeaseDatabaseName = "TriggerLeases",
LeaseCollectionName = "TriggerLeases",
LeaseCollectionPrefix = "ImageCopier")]IReadOnlyList<Document> input,
//[StorageAccount("MyStorageAccount")]string storageConnectionString,
ILogger log)
{
I have MyStorageAccount defined in my local.settings.json file and I also have it in my Azure Function Configuration settings. I copied the connection string directly from the storage account keys panel.
When you set up a CosmosDB trigger, the information that is supplied in that trigger is specific to the trigger. If you need a setting or configuration not related to the trigger in your code, you can use the Environment.GetEnvironmentVariable method.
In your local environment, you can set these variables by editing the local.settings.json file, specifically the Values array. For example:
{
"IsEncrypted": false,
"Values": {
"JobUri": "https://yourapiendpointurl.com",
"BlobStorageConnectionString" : "the connection string",
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
In your method, you may grab that value like so:
public static class Function1
{
[FunctionName("ImageCopier")]
public static async Task Run([CosmosDBTrigger(
databaseName: "MyDatabase",
...
ILogger log)
{
var connectionString =
Environment.GetEnvironmentVariable("BlobStorageConnectionString");
}
}
The local.settings.json file will not be used when it's running in Azure.
I am not sure that when you publish the function if your local.settings.json file will migrate the settings to your Azure Function app's configuration, so I would check to make sure that your settings are in there after publishing.
Side note: Be carful when committing code to repos .. you don't want "secrets" in your repositories in case someone gets in to your repo and discovers it.
While you can access raw configuration values using GetEnvironmentVariable, a more robust/idiomatic approach with .NET in particular is to leverage the built-in dependency injection of configuration.
Using this, you can accept an IConfiguration or strongly-typed IOptions through the function's constructor and use the values in your code. For example:
public class Function1
{
private readonly IConfiguration configuration;
public Function1(IConfiguration configuration)
{
this.configuration = configuration;
}
[FunctionName("ImageCopier")]
public async Task Run([CosmosDBTrigger(/* trigger params */)] IReadOnlyList<Document> input)
{
var connectionString = configuration["MyStorageAccount"];
// Use connection string
}
}
You can take this further to inject services like an "ImageBlobService" into your function that have already been configured in a common Startup Configure method just like ASP.NET Core. That way the individual functions don't need to know anything about configuration and just ask for the relevant service to use.

Cosmos DB - Change Feed Trigger: The Listener for 'my-function-name' was unable to start

I am getting below error while running my azure function app application:
[7/15/2020 8:26:08 AM] The listener for function
'NotificationChangeFeed' was unable to start. [7/15/2020 8:26:08 AM]
The listener for function 'NotificationChangeFeed' was unable to
start. Microsoft.Azure.DocumentDB.Core: Object reference not set to an
instance of an object.
Error Screen shot:
Here is my Change Feed Trigger Azure Function:
public static class NotificationChangeFeed
{
[FunctionName("NotificationChangeFeed")]
public static async Task Run([CosmosDBTrigger(
databaseName: "FleetHubNotifications",
collectionName: "Notification",
ConnectionStringSetting = "CosmosDBConnection",
LeaseCollectionName = "leases", CreateLeaseCollectionIfNotExists = true)]IReadOnlyList<Document> input,
[Inject] ILoggingService loggingService,
[Inject] IEmailProcessor emailProcessor)
{
var logger = new Logger(loggingService);
try
{
if (input != null && input.Count > 0)
{
foreach (Document document in input)
{
string requestBody = document.ToString();
var notification = requestBody.AsPoco<Notification>();
var result = await emailProcessor.HandleEmailAsync(notification, logger);
if (result)
{
logger.Info($"Email Notification sent successfully for file name: {document.Id}");
}
else
{
logger.Warning($"Unable to process document for Email Notification for file with name: {document.Id}");
}
}
}
}
catch (Exception ex)
{
logger.Error($"Unable to process Documents for Email Notification for Files: {input.Count}", ex,
nameof(NotificationChangeFeed));
}
}
}
local.settings.json:
{
"IsEncrypted": "false",
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"CosmosDbId": "FleetHubNotifications",
//Localhost
"CosmoDbAuthKey": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
"CosmoDbEndpoint": "https://localhost:8081/",
"CosmosDBConnection": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
}
}
Connecting String of local Storage Emulator is correct.
If your firewall restricts func from accessing the Storage Account, then this error may be reported. The firewall is one of the reasons that the listener cannot access the virtual Storage Emulator.
When running the function locally, all triggers except httptrigger need to use the Storage Emulator. If the firewall restricts the listener's access to virtual storage, problems can occur when performing functions.
Try disabling the firewall and see if that resolves the issue.
Of course, it is also possible that the Storage Emulator service is not open. Try typing
"%programfiles(x86)%\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" status
in cmd to check the status.
If it returns false, enter the following command to start the Storage Emulator:
"%programfiles(x86)%\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" init
"%programfiles(x86)%\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" start
To sum up:
This listener can not start is generally for three reasons.
1.Connection string error prevents connection,
2.firewall is set
3.some services are not turned on.

Azure Timer Function - Microsoft.WindowsAzure.Storage: Settings must be of the form "name=value"

I'm able to create http trigger functions and execute them no problem, but when I create a timer function, I get the following error:
The listener for function 'Functions.CheckForWinnersOnTimer' was unable to start. Microsoft.WindowsAzure.Storage: Settings must be of the form "name=value".
This is with no alteration of the template code when I create the function.
module.exports = async function (context, myTimer) {
var timeStamp = new Date().toISOString();
if (myTimer.IsPastDue)
{
context.log('JavaScript is running late!');
}
context.log('JavaScript timer trigger function ran!', timeStamp);
};
Why is that? I appreciate any help!
This error is what you faced know.
Given that there is nothing wrong with your code, I think the problem should be caused by local.settings.json. Note the format of the value of AzureWebJobsStorage.
If you are using a local virtual storage simulator, then you should fill in UseDevelopmentStorage=true. If you choose Storage Account on Azure, then you should go here to copy the values and fill in AzureWebJobsStorage:
An example of local.settings.json using a local storage emulator:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node"
}
}

The listener for function 'SignalR' was unable to start. Azure function binding with signalr

I'm developing an application where IOT devices are connected with the Azure IOT Hub. and its realtime data can be visible on the web view. However, I'm facing an error, I'm trying to bind the data Azure function with SignalR, but when I run the application I receive the following error message.
The listener for function 'SignalR' was unable to start. Microsoft.Azure.EventHubs.Processor: Encountered error while fetching the list of EventHub PartitionIds. System.Private.CoreLib: The link address '$management' did not match any of the expected formats.
Error Description Image
I've tried everything to fix it but failed every time. I'd really appreciate if someone would help me find the solution to this problem.
Here is the script I'm using from this link
Here is my SignalR.cs class
public static class SignalR
{
[FunctionName("SignalR")]
public static async Task Run(
[IoTHubTrigger("messages/events", Connection = "IoTHubTriggerConnection", ConsumerGroup = "$Default")]EventData message,
[SignalR(HubName = "broadcast")]IAsyncCollector<SignalRMessage> signalRMessages,
ILogger log)
{
var deviceData = JsonConvert.DeserializeObject<DeviceData>(Encoding.UTF8.GetString(message.Body.Array));
deviceData.DeviceId = Convert.ToString(message.SystemProperties["iothub-connection-device-id"]);
log.LogInformation($"C# IoT Hub trigger function processed a message: {JsonConvert.SerializeObject(deviceData)}");
await signalRMessages.AddAsync(new SignalRMessage()
{
Target = "notify",
Arguments = new[] { JsonConvert.SerializeObject(deviceData) }
});
}
}
Here is my SignalRConnection.cs class
public static class SignalRConnection
{
[FunctionName("SignalRConnection")]
public static SignalRConnectionInfo Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
[SignalRConnectionInfo(HubName = "broadcast")] SignalRConnectionInfo info,
ILogger log) => info;
}
Here is my local.settings.json file
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureSignalRConnectionString": "",
"MSDEPLOY_RENAME_LOCKED_FILES": 1,
"IoTHubTriggerConnection": ""
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*"
}
}
for IoTHubTriggerConnection, I'm using the connection string of iothubjohnsoncontrol (displayed in image below).
IOT Hub Keys Image
for AzureSignalRConnectionString, I'm using the connection string of signalrjohnsoncontrol (displayed in image below).
SignalR Keys Image
Could you please check if you have given EventHub Compatible name and EventHub compatible connections string from here
Please try replacing messages/events with EventHub-Compatible name and IoTHubTriggerConnection as EventHub compatible endpoint from portal.
Almost similar discussion here :
https://github.com/Azure/azure-event-hubs-dotnet/issues/103
I have a usecase like that to Push Iot data to Azure data explorer and this is what my Function looks like
Iot Hub Connection string which is EventHub compatibale
Hope this helps.

Resources