One of the things I love to add to my Azure Functions are environments specific app settings files. Anybody that has been working with ASP .NET Core will be familiar with them and in my opinion, they are great to store your non-secret environment-specific settings. Since Microsoft start supporting them easily in Azure Functions, I have been adding them basically to all my functions. See Microsoft’s documentation for implementing that.
But recently I had to configure an environment-specific variable that didn’t work as expected. However, the solution was quite easy. I’ll tell you what I did.
I have an Azure Service Bus queue from which I want to process messages. Since I don’t have to process tons of messages, I decided to go for a Consumption App Service Plan to host it.
For each environment (Test, Staging, and Production) I have a different queue I need to process the messages from. Nothing secret about the queue name, so I decided to configure it in the app settings files. I created a separate section for ServiceBus options, where I added queuename as a property. So my app settings file looked like this:
{
ServiceBus: {
QueueName: "TestQueue"
}
}
Then I configured the Service Bus Trigger to read this variable, which would look like this:
[FunctionName("ServiceBusQueueTriggerCSharp")]
public static void Run(
[ServiceBusTrigger("%ServiceBus:QueueName%", Connection = "ServiceBusConnection")]
There are a few things to note here. Since it is a subkey, I had to use the colon (:) to read the QueueName from the ServiceBus section. And more importantly, to read this value on run time, I had to put percentages (%) around it. If I wouldn’t do that, it would resolve the value at run time and try to read from the queue, called: ServiceBus:QueueName in stead of TestQueue.
To test that this worked, I ran the function locally. Which worked perfectly. However, when I deployed the function to the Consumption Plan based App Service, it didn’t work.
In the Azure Portal I got the following error message:
Microsoft.Azure.WebJobs.Script: The Functions scale controller may not scale the following functions correctly because some configuration values were modified in an external startup class.
After lots of digging, I found out the reason was quite simple. Since I was using the consumption plan, the function will only run when a message is available. However to know if a message is available, it needs to monitor the queue. Since the queuename was only available at runtime, the scaling host could not figure out which queue it needs to monitor. Since I am not working with such a scaling host locally, I didn’t experience that issue.
The fix is quite simple. Set the queuename in the app settings on the app service itself. So if you use the Azure Portal, when you navigate to the app service and go to Configuration. In the App Settings tab, your queuename should be listed there. These values can be read by the scaling host. So in my case I added the following app setting:
Name: ServiceBus:QueueName
Value: TestQueue
Since I am was using Arm templates to deploy my infrastructure, I could easily configure the queuename as a parameter in the infra deployment.
In case you are running on a premium plan, you won’t experience this issue. Since the app service is then running 24/7.
Good luck building your Azure Functions and I hope this article helped!