How do I post a message to a Azure Service Bus from my Azure function? - azure

I am playing around with Azure functions and trying to setup an intricate construct of pipes and filters (the pattern). I am using Azure functions for this.
My starting point is a HTTP triggered Azure function. That collects some JSON from the body of the request and should pass this message to a Azure Service Bus.
I must be missing something here (I have done this before in RabbitMQ with console apps) but how do I post a message to a service bus from a HTTP triggered Azure function.
I found several references talking about configuring my function.json (what ever that is - im building in Visual Studio).
How does this input/output (trigger/binding) thing work - im guessing that is the problem here...or??
I have my first Azure function in place and is receiving the data from the HTTP - so far so good. But how to proceed?
** Update **
Still cant get it to Work. Got this code and it fails with an http500. (it also says i need to see the og - where is that log?)
public static class EI_WooCommerce_Hub
{
[FunctionName("EI_WooCommerce_Hub")]
[return: ServiceBus("eilogging", Connection = "EIIntegrationServiceBusConnection")]
public async static Task<string> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "EIWooCommerceHub/name/")]HttpRequestMessage req, TraceWriter log)
{
log.Info("Webhook triggered from: ");
return "Hello World to queue";
}
}
** Update 2 **
This seems to be a config problem. In the application settings on the function app I kept getting an authorization error for the servicebus. I added the default "AzureWebJobsServiceBus" setting with the connectionstring, then it worked. It could not pick up my own connection string for some reason.

You should use Service Bus output binding. Since you mentioned Visual Studio, I assume C#. The simplest ever example looks like this:
[FunctionName("ServiceBusOutput")]
[return: ServiceBus("myqueue", Connection = "ServiceBusConnection")]
public static string ServiceBusOutput([HttpTrigger] dynamic input)
{
return input.Text;
}
Then add an application setting called ServiceBusConnection with the connection string to a namespace with queue myqueue (or rename in attribute constructor).
You can find more in Azure Service Bus bindings for Azure Functions - Output.

When you build in Visual Studio, then the function.json is created automatically. All you have to do is to define your triggers and output as attributes of the function parameters (see here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus#output)
A minimalistic example:
[FunctionName("HttpTriggerCSharp")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestMessage req,
[ServiceBus("myqueue")] out string sbMessage,
TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
sbMessage = name;
}

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."

Can Azure function GridTrigger be used along with CosmosDB input binding?

I am a newbie to Azure functions. I am having problem with the below code where CosmosDB binding is not working. If I remove CosmosDB, it works find; I am able to get messages thru eventGridEvent. But as soon as I add CosmosDB, this piece of code fails. I had tried different Collectors (IAsyncCollectory, IReadOnlyCollection, IReadOnlyList, IEnumerable, etc.) some of them compiles fine but when deployed to Azure portal it does nothing (msg: function not found).
I need to retrieve data from CosmosDb and save it to a Queue by using the message coming thru eventGridEvent. I can hardcoded but that is not allowed for my project. Any help will be appreciated team!
[FunctionName("TopicGridTrigger")]
public static void Run([EventGridTrigger()] EventGridEvent eventGridEvent,
[Queue("myqueuetest")] out string queueMessage,
[CosmosDB("MyCarStore", "cars", ConnectionStringSetting = "CosmosDBConnectionString")] IAsyncCollector<MyCar> Items,
ILogger log
)
{
//SOME CODE HERE
}

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.");
}

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?

Function logging not showing details in Kudu - Log param always appears null

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>).

Resources