Search code examples
azureazure-functionsazure-cosmosdbazure-eventhubazure-triggers

azure function - triggered when new event in eventhub, writing it to cosmos db - not working, why?


I hope you can help me.

I'm new to Azure and having lots of trouble understanding it. I'm trying to write an azure function, who is triggered with EventHubTrigger (when a new event is sent to eventHub), and will store the event in my table in cosmos db. (cosmos db as an output).

I'm writing in C# so that function.json is created automatically and I can't edit it. I can't seem to make it work, to set the trigger and output binding correctly.

this is my function code:

[FunctionName("InsertEvent")]
public static void Run(
    [EventHubTrigger("WaterlyNamespace", 
    Connection = "connectionStr")] string eventHubString,
    [CosmosDB(
    databaseName: "waterly_db",
    collectionName: "water_table", 
    Id = "device_id",
    ConnectionStringSetting = "conStr" )] out dynamic dbItem,
    ILogger log)

{
    log.LogInformation("C# trigger function processed an event from eventhub");

    EventItem dataJson = JsonConvert.DeserializeObject<EventItem>(eventHubString);

    //adding timestamp to event json
    dataJson.timestamp = DateTime.Now;

    dbItem = dataJson;
}

This is the function.json generated:

{
  "generatedBy": "Microsoft.NET.Sdk.Functions-3.0.3",
  "configurationSource": "attributes",
  "bindings": [
    {
      "type": "eventHubTrigger",
      "connection": "ConnectionStr",
      "eventHubName": "WaterlyNamespace",
      "name": "eventHubString"
    }
  ],
  "disabled": false,
  "scriptFile": "../bin/Waterly-iot-functions.dll",
  "entryPoint": "Waterly_iot_functions.InsertEvent.Run"
}

This is the host.json:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingExcludedTypes": "Request",
      "samplingSettings": {
        "isEnabled": true
      }
    }
  },
  "extensions": {
    "cosmosDB": {
      "connectionMode": "Gateway",
      "protocol": "Https",
      "leaseOptions": {
        "leasePrefix": "prefix1"
      }
    }
  }
}

and this is what I see in the Azure portal after publishing this code: See Image

Any ideas why the trigger is in the output area in the Azure portal, and what am I missing?

Any help would be very appreciated. Thanks,


Solution

  • I think you have a problem with the usage of the connection string in the attribute.

    Follow my steps, it can works fine:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.Azure.EventHubs;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp54
    {
        public static class Function1
        {
            [FunctionName("Function1")]
            public static void Run([EventHubTrigger("test", Connection = "str")] EventData[] events,
                [CosmosDB(
                    databaseName: "testbowman",
                    collectionName: "testbowman",
                    ConnectionStringSetting = "CosmosDBConnection",
                    PartitionKey = "111")]out dynamic item, 
                ILogger log)
            {
                item = new { id = Guid.NewGuid() , custom = "11111111111111111111"};
            }
        }
    }
    

    This is my local.settings.json:(On local, env vars are setted in local.settings.json)

    {
        "IsEncrypted": false,
      "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet",
        "str": "Endpoint=sb://testbowman.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxxxx",
        "CosmosDBConnection": "AccountEndpoint=https://testbowman.documents.azure.com:443/;AccountKey=xxxxxx;"
      }
    }
    

    You should get the connection string from these places:

    enter image description here

    enter image description here

    And then I create a console app to send event to event hub.

    using System;
    using System.Text;
    using System.Threading.Tasks;
    using Azure.Messaging.EventHubs;
    using Azure.Messaging.EventHubs.Producer;
    
    namespace SendEventToEventHub
    {
        class Program
        {
            private const string connectionString = "Endpoint=sb://testbowman.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=pftXmTesAa894OWYGZyD5s8GynR9hXVJl7CdbMy45Nc=";
            private const string eventHubName = "test";
            static async Task Main(string[] args)
            {
                // Create a producer client that you can use to send events to an event hub
                await using (var producerClient = new EventHubProducerClient(connectionString, eventHubName))
                {
                    // Create a batch of events 
                    using EventDataBatch eventBatch = await producerClient.CreateBatchAsync();
    
                    // Add events to the batch. An event is a represented by a collection of bytes and metadata. 
                    eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("First event")));
                    eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Second event")));
                    eventBatch.TryAdd(new EventData(Encoding.UTF8.GetBytes("Third event")));
    
                    // Use the producer client to send the batch of events to the event hub
                    await producerClient.SendAsync(eventBatch);
                    Console.WriteLine("A batch of 3 events has been published.");
                }
            }
        }
    }
    

    After that, I start my function, and I can see the output in cosmosdb:

    enter image description here

    By the way, if you deploy to azure, the settings should be set in below instead of local.settings.json:

    enter image description here

    Please let me know if you can do it successfully after trying as above. Good luck.:)