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.");
}
Related
I'm using Azure Functions with Automatic Dependency Tracking disabled and manually tracking my dependencies.
I also use the SDK provided ILogger for traces and metrics, and also heavily use the ILogger.BeginScope(...) to track details about operations.
Is it possible to get the current scope properties so I can add them to my dependency tracking?
Example would be
using(var scope = log.BeginScope("{document}{user}", documentId, userId)){
// do HTTP Call using HttpClient
}
HTTP Client Config
.AddHttpMessageHandler(serviceProvider => new
DependencyLoggingMessageHandler(serviceProvider.GetRequiredService<TelemetryClient>()))
And the Message Handler
public class DependencyLoggingMessageHandler : DelegatingHandler
{
private readonly TelemetryClient client;
public DependencyLoggingMessageHandler(TelemetryClient client)
{
this.client = client;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
try
{
response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
return response;
}
finally
{
client.TrackDependency(new DependencyTelemetry(..){
Data = ...,
Properties = /*how to get scope props? */
});
}
}
}
In the AppInsights dependency created for this, I would like to have document and user as properties like the traces and metrics created by the SDK.
Update:
Currently I have 2 (questionable) solutions
If you want a no frills, easy implementation, use LogMetric("HTTP_REQUEST", duration, properties) which will have the scope properties as usual and add your things to its properties.
Sure it won't show up in app insights dependencies, but you can have the duration of the HTTP request as its value, have the url, host .etc. as custom properties and get most things done. My main requirement is to track duration and urls, which works in this solution so I have settled for this solution for now.
Maintain the scope properties yourself
I think this can be done with essentially duplicating what the Functions Runtime does. i.e Using a custom version of it in a AsyncLocal and iterating from current scope to the root scope and adding them to your telemetry like the runtime does. Looks like a lot more work than its worth to me.
If you have a better/different solution please put your answer below.
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>).
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;
}
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.