Why is the Azure App Configuration feature flag not found? - azure-app-configuration

Azure Functions app, runtime v3.
The application has a FunctionsStartup class that first enables Azure App Configuration in its ConfigureAppConfiguration method:
builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
{
options
.Connect(appConfigurationConnectionString)
.UseFeatureFlags();
});
And in its Configure method it enables feature management, and it adds the Azure App Configuration services (so we can refresh settings at runtime):
builder.Services
.AddAzureAppConfiguration()
.AddFeatureManagement()
.AddFeatureFilter<ContextualTargetingFilter>();
On the Azure Portal there is a feature flag, which is enabled, called CardExpirationNotice. The code uses IFeatureManagerSnapshot to check if the feature is enabled:
feature = nameof(Features.CardExpirationNotice);
var isEnabled = await _featureManagerSnapshot.IsEnabledAsync(feature);
isEnabled is false, and this log message is output:
The feature declaration for the feature 'CardExpirationNotice' was not found.
I tried configuring a flag locally in local.settings.json:
"FeatureManagement__CardExpirationNotice": true
Then isEnabled is true, so I can narrow the problem to Azure App Configuration, and exclude the feature management implementation.

As it turns out, when you add a feature flag in Azure App Configuration, you can set a label. But if you do that, then you need to specify that label in your code as well:
builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
{
options
.Connect(appConfigurationConnectionString)
.UseFeatureFlags(options => options.Label = "payments");
});

Related

Elsa workflow designer client side API

I have to persist / save workflow using custom javascript code, not by using built-in designer publish button. So is there any client side API like
const elsaStudioRoot = document.querySelector('elsa-studio-root');
that is using for registering custom plugins.
The elsa-studio-root element does not expose any methods or services that you can leverage, but it would make sense for it to do. You could create an issue and/or submit a PR.
Alternatively, or as a temporary workaround, you could write a plugin that captures the ElsaStudio service, which provides access to the elsaClientFactory factory method.
This factory method produces an instance of ElsaClient, which offers direct API access to the workflow server, which exposes an endpoint to update workflow definitions.
For example (untested code):
// Declare a variable you can access from wherever you want.
let elsaClientFactory = null;
// Declare an Elsa plugin.
function CaptureElsaClientFactoryPlugin(elsaStudio) {
// Capture the elsa client factory method.
elsaClientFactory = elsaStudio.elsaClientFactory;
}
// Register the plugin.
elsaStudioRoot.addEventListener('initializing', e => {
const elsa = e.detail;
elsa.pluginManager.registerPlugin(CaptureElsaClientFactoryPlugin);
});
// Retrieve an elsa client service.
var elsaClient = elsaClientFactory();
// Save some workflow definition
await elsaClient.workflowDefinitionsApi.save({
workflowDefinitionId: 'some workflow definition ID',
name: 'optional',
displayName: 'optional',
description: 'optional',
publish: true, // or false if you don't want to publish but save as draft.
activities: [],
connections: []
// etc. See https://github.com/elsa-workflows/elsa-core/blob/master/src/designer/elsa-workflows-studio/src/services/elsa-client.ts#L377 for a full list of fields you can specify.
});

Migration to Minimal API - Test Settings Json not overriding Program

Thanks to this answer: Integration test and hosting ASP.NET Core 6.0 without Startup class
I have been able to perform integration tests with API.
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
});
});
HttpClient? client = app.CreateClient();
This has worked using the appsettings.json from the API project. Am now trying to use integrationtestsettings.json instead using:
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(ProjectDirectoryLocator.GetProjectDirectory())
.AddJsonFile("integrationtestsettings.json")
.Build();
WebApplicationFactory<Program>? app = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
builder.ConfigureServices(services =>
{
});
});
_httpClient = app.CreateClient();
I have inspected the configuration variable and can see the properties loaded from my integrartiontestsettings.json file. However, the host is still running using the appsettings.json from the server project.
Previously, in .Net5, I was using WebHostBuilder and the settings were overridden by test settings.
WebHostBuilder webHostBuilder = new();
webHostBuilder.UseStartup<Startup>();
webHostBuilder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(_configuration));
But cannot get the test settings to apply using the WebApplicationFactory.
It seems the method has changed.
Changing:
builder.ConfigureAppConfiguration(cfg => cfg.AddConfiguration(configuration));
To:
builder.UseConfiguraton(configuration);
has done the trick.
builder.ConfigureAppConfiguration, now it's configuring the app (after your WebApplicationBuilder.Build() is called) and your WebApplication is created.
You need to "inject" your configurations before the .Build() is done. This is why you need to call UseConfiguraton instead of ConfigureAppConfiguration.

Tracking hangfire background jobs with app insights

I have set up app insights in Asp.net core application. All my web api requests are tracked on app insights and if I have any failures I can simply find them in Failures section.
However, I have also Hangfire background jobs running and if they are failing I can't find them on app insights. Also I have alert rule Whenever the total http server errors is greater than or equal to 1 count and I am not sure if hangfire 5xx errors will go under this condition.
So is there any way to track Hangfire jobs failures and get notified about them?
Hangfire handles most exceptions under the hood, so App Insights is not going to pick them up by default. There is also a bunch of configuration you have to do with App Insights as well.
I wrote a JobFilter for Hangfire which allows you to connect with App Insights, this should be enough to get you going:
https://github.com/maitlandmarshall/MIFCore/blob/master/MIFCore.Hangfire/Analytics/AppInsightsEventsFilter.cs
And for the App Insights configuration:
https://github.com/maitlandmarshall/MIFCore/blob/master/MIFCore.Hangfire/Analytics/TelemetryConfigurationFactory.cs
To put everything together from the above links:
var appInsights = this.rootScope.ResolveOptional<AppInsightsConfig>();
var childScope = ServiceScope = this.rootScope.BeginLifetimeScope("HangfireServiceScope");
var activator = new AutofacLifecycleJobActivator(childScope);
var options = new BackgroundJobServerOptions()
{
Activator = activator,
Queues = new[] { JobQueue.Alpha, JobQueue.Beta, JobQueue.Default, JobQueue.Low }
};
this.globalConfig
.UseFilter(new BackgroundJobContext());
if (!string.IsNullOrEmpty(appInsights?.InstrumentationKey))
{
var telemetryClient = new TelemetryClient(TelemetryConfigurationFactory.Create(appInsights));
this.globalConfig.UseFilter(new AppInsightsEventsFilter(telemetryClient));
}
using (var server = new BackgroundJobServer(options))
{
await server.WaitForShutdownAsync(stoppingToken);
}
There was a nice nuget package created Hangfire.Extensions.ApplicationInsights.
So, install the package:
Install-Package Hangfire.Extensions.ApplicationInsights
and add the line to ConfigureService method:
services.AddHangfireApplicationInsights();
If your solution requires some custom details you can adjust the code from github repository.

Enable/Disable logging in Worklight application

We are developing a WL application using WL enterprise 6.2.0.1. We have four environments (Dev/QA/UAT and PROD).
Our application is logging the user credentials on the Server (file:SystemOut.log) which is ok for Dev environment. However, when we need to move the build to QA and UAT we need to disable the logging since it is a security point of view and we can't proceed to PROD.
What we did is we added the following code to the initOptions.js:
var bEnableConsoleLog = false; // Enable Disable the logging
var wlInitOptions = {
...
...
...
logger : {
enabled : bEnableConsoleLog},};
var disableLogging = function() {
WL.Logger.info("##### LOG ENABLED ?? => " + bEnableConsoleLog);
if (bEnableConsoleLog == false)
{
WL.Logger.config({
enabled : false,
level : 'info'
});
console.log = function() {
}.bind(console.log);
console.error = function() {
}.bind(console.error);
}
};
if (window.addEventListener) {
window.addEventListener('load', function() {
WL.Client.init(wlInitOptions);
disableLogging();
}, false);
} else if (window.attachEvent) {
window.attachEvent('onload', function() {
WL.Client.init(wlInitOptions);
disableLogging();
});
}
disableLogging();
WL.Logger
.info("######################## WL.Logger.info ENABLED ############################");
console
.log("######################## console.log ENABLED ############################");
console
.error("######################## console.error ENABLED ############################");
By Setting the value var bEnableConsoleLog = (true/false); we thought we can enable or disable the logging, but it seems still logging the credentials.
Is there a way to resolve this?
I don't think there is an 'enabled' option on WL.Logger.config based on the WL.Logger API reference. There is a 'capture' option which you can set to false, which will disable saving the client logs and sending them to the server.
If your client is logging the user credentials in a log statement then that information should only be sent based on 'capture' being true (the default) and the log statement you use being at the 'level' value or above. Given your WL.Logger.config() above, that means WL.Logger.info() would be sent to the server and WL.Logger.debug() would not. For more information see Configuring the Worklight Logger.
Note that all of this pertains only to WL.Logger calls made by the client. If you are logging the user credentials in your server-side code (for example using Java logger) then what is logged will be based on the log levels configured on the server; the client log configuration will have no effect.

Worklight Direct Update and run offline

I want to achieve such a functionality.
That is:
1) in case of connecting to worklight server successfully, Direct Update is available.
2) in case of failing to connect to worklight server, the app can run offline.
Below is my configuration in "initOptions.js".
// # Should application automatically attempt to connect to Worklight Server on application start up
// # The default value is true, we are overriding it to false here.
connectOnStartup : true,
// # The callback function to invoke in case application fails to connect to Worklight Server
onConnectionFailure: function (){
alert("onConnectionFailure");
doDojoReady();
},
// # Worklight server connection timeout
timeout: 10 * 1000,
// # How often heartbeat request will be sent to Worklight Server
heartBeatIntervalInSecs: 20 * 60,
// # Should application produce logs
// # Default value is true
//enableLogger: false,
// # The options of busy indicator used during application start up
busyOptions: {text: "Loading..."
But it doesn't work.
Any idea?
Direct Update happens only when a connection to the server is available. From the way you phrased your question, your problem is that when the app cannot connect to the server it doesn't work "offline". So your question has got nothing to do with Direct Update (if it does, re-phrase your question appropriately).
What you should do, is read the training material for working offline in Worklight.
You are not specifying what "doesn't work". Do you get the alert you've placed in onConnectionFailure? How does your doDojoReady function look like?
I too am using Dojo in Worklight.
My practice is have worklight configured not to connect on startup
var wlInitOptions = {
connectOnStartup : false
in my wl init I then initialise my dojo app,
function wlCommonInit(){
loadDojoLayers();
};
requiring whatever layers I'm using, and then do the actual dojo parsing
require([ "dojo/parser",
"myApp/appController",
"dojo/domReady!"
],
function(parser, appController) {
parser.parse().then (function(){
appController.init();
});
});
Finally, now WL, Dojo, and myApp are all ready I attempt the WL connection, calling this method from my appController.init()
connectWLServer: function() {
// possibly WL.Client.login(realm) here
var options = {
onSuccess: lang.hitch(this, "connectedWLServer"),
onFailure: lang.hitch(this, "connectWLServerFailed"),
};
WL.Client.connect(options);
}
Any Direct Update activities happen at this point. Note that the app as whole keeps going whether or not the connection works, but clearly we can run appropriate code in success and fail cases. Depending upon exactly what authentication is needed an explicit login call may be needed - adapter-based authentication can't happen automatically from inside the connect().