Using Azure Function with .net5.0 isolated worker, make it log to an SEQ server and deploy to Azure

Claudio Santos
8 min readMay 19, 2021

Uff… That´s a lot! So let´s start this travel step by step!

The use case that brought me to writing this text is:

  • I have a Service Bus configured in Azure, that has a Topic, and that topic ships messages to various subscribers! I want an Azure Function, written in Dotnet 5.0 that has a Service Bus Topic trigger, and all the processing on that Azure Function will be logged to a Datalust / SEQ server that I have created in a web app ( read about it on this link )

Let’s learn a little more about this “Azure Functions in .NET 5.0”. So on .NET5.0 you can develop azure functions that run out-of-process, and doing so, lets you decouple your function code from Azure Functions Runtime.

I truly recommend the reading of https://docs.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide so you can understand what is this.

In a very summarized way, A .NET isolated function project is basically a .NET console app project that targets .NET 5.0. The following are the basic files required in any .NET isolated project: host.json file, local.settings.json file, C# project file (.csproj) that defines the project and dependencies and Program.cs file that’s the entry point for the app

1. Creating the Azure Function

  1. 1 Required tools to make magic happen:

So we will need to have installed the following pieces of software/packages:

a) .NET 5.0 ( you can download and install it from this link )

b) (optional) Powershell ( you can download and install it from this link )

c) Azure Function Core Tools ( you can download and install it from this link, and pleaseeee select a version higher than 3.0.3388 )

d) Azure CLI ( you can download and install it from this link )

After you have all set up, and here I´ll assume that you have installed PowerShell, and after creating a new folder for your project, navigate to it in PowerShell and use the following command:

func new

It will then ask what kind of runtime you want in your new Azure Function, please select Dotnet (Isolated Process)

You will get these options! dotnet (Isolated Process) is your target!

Then it will “ask” what is the trigger for your Azure Function. My use case asks for ServiceBusTopicTrigger, but choose the one that suits you best

So here I select Service Bus Topic Trigger, but it's because of my use case =)

The last step is to give it a name, my case: “MediumTest” just for the fun =)

Note: Unfortunately, at the time I´m writing this, Visual Studio has still no support to create this “kind” of Azure Functions in an automated way… Sorry =/

They will update this… they´ve said!

If you check your folder, you´ll have now a .csproj file with the same name of the folder you are in, and a .cs file with the name of the Azure Function that you have inserted before.

MAGIC!!! Files and folders born out of nowhere!!

So, it´s time to check how are the files, open the csproj that will open up Visual Studio if you have it installed!

Right after opening in Visual Studio, my first thing is to update the nugget packages, and you will notice that the names of the nugget packages installed are slightly different from the ones you might be used to see in an Azure Function, so let's check, they have a “.worker.” part… So we are really coding workers!! NICE!!!!

So this is the “shape” of my updated .csproj

1.2 Extra part for Service Bus Topic Trigger

If you also select for a Service Bus trigger, we now have to configure a little bit more, so we have to go to the file of the function (in my case MediumTest.cs) and edit the Azure Function so we can set up: the topic name, the subscription name and the name of the setting that will hold the connection string to the service bus.

My parameters for this example are:

Topic Name = “clients-topics”; Subscription Name = “default”; Connection String property name = ”ClientsSBConnection”

This will be my SUPER AMAZING AZURE FUNCTION!

And we have to add the connection string. For this purpose, we will add it to the local.settings.json but when you go production, use another way of pushing the connection string… I am thinking of using the Key Vault to retrieve the connection string…

As you can see, we now have a property “Values:ClientsSBConnection”

So we are ready to see if this works…

If you have Visual Studio as your IDE, just start a debugging session ( if by any case it fails, it didn´t fail in my case, but there are records that it can fail the debugging if you do your usual F5 in Visual Studio, please check this guide that might help you

So, after putting the Azure Function running, I sent a message to the Topic in the service bus and voilá :

I got a message, you got a message, EVERYONE GETS A MESSAGE!!!

More Functions! More triggers!!! GIVE ME!!!!

If you want to add new functions, you can just go back into the PowerShell and type func new and you can have some help on how to manage the signature and decorators of your function in this link.

1.3 Dependency Injection in Isolated Process Azure Function

Inspecting the Program.cs ( yeah I know we´re all used to have Startup.cs, and you can do it, but out of the box, it´s here you´ll DI ) and we can see that we have a HostBuilder with a couple of extension methods, one of them called ConfigureFunctionsWorkerDefaults() that as its name says, it's crucial for the correct behavior of the Azure Function, but we can also add some DI here, and even manage properly some middleware!

OMG! Adding Middleware on the fly!!!

And we can also add services to be injected, as usual, using the ConfigureServices(), but for that, we need to add Microsoft.Azure.Functions.Extensions Package (V. 1.1.0 or higher )

Sample service ready to be injected!! YEAHHHH!!!

2 Adding Serilog and connect it to the SEQ server.

Ahhh so now this one is easy! Let’s first add the packages we need:

<PackageReference Include=”Serilog” Version=”2.10.0" />

<PackageReference Include=”Serilog.Extensions.Logging” Version=”3.0.1" />

<PackageReference Include=”Serilog.Sinks.Console” Version=”3.1.1" />

<PackageReference Include=”Serilog.Sinks.Seq” Version=”5.0.1" />

Again these versions are the ones I use at the time of this writing, if you have an update, go for it!!

After installing the packages, we will use the Dependency Injection capabilities to configure our Serilog to our solution. Also, note that the last package that I´ve installed is Serilog.Sinks.Seq, it´s one who makes the magic to send the data to a remote SEQ server =)

So I just deleted the URL of my SEQ server… don't want to receive random logs =)

So inside the ConfigureServices we´ll add the following:

var logger = new LoggerConfiguration()

.Enrich.WithProperty(“ApplicationContext”, “MY SUPER FUNCTION”)

.WriteTo.Console()

.WriteTo.Seq(serverUrl)

.CreateLogger();

s.AddLogging(lb => lb.AddSerilog(logger));

I just added the write to console also, because I like the console =)

IT WORKS! Just have to remove the URL and my favorites so you don't mock on me =)

So let's power-up, and check it, and It works… I even sent a message and the logging system caught it and shipped it to the SEQ server! Everything working as expected ufff!!!

Waitt a minute!! we still have to deploy it to Azure!

3 Deploy to Azure

So now it's time to use Azure CLI!

First, we open a PowerShell and login to Azure, for that just type:

az login

It will open a browser, please log in to that browser, and after it, return to the PowerShell and it will show your subscriptions. If you have more than one subscription, you might need to set a subscription where you will deploy the azure function, with the command. Ignore this step if you only have one subscription.

az account set --subscription "<ID OF SELECTED SUB>"

If you don´t have a resource group ready or you might want to create a new one, you can use this command

az group create --name AzureFunctionsQuickstart-rg --location westeurope

Where, of course, you change the name of the resource and location for whatever you desire!

All azure functions have to have a storage account, so let´s create one, or you can skip also this step if you have already provisioned a storage account.

az storage account create --name <STORAGE_NAME> --location westeurope --resource-group AzureFunctionsQuickstart-rg --sku Standard_LRS

After this, we have to create the azure function in Azure to be ready to receive our files, so use this

az functionapp create --resource-group AzureFunctionsQuickstart-rg --consumption-plan-location westeurope --runtime dotnet-isolated --functions-version 3 --name <AZURE FUNCTION NAME> --storage-account <STORAGE ACCOUNT NAME>

After this, if you check the resource group in Azure you should have all resources ready to receive your code

All set to receive my azure function!

So its time to send files up to Azure, so make sure that your PowerShell is now in the same folder that your new Azure Function csproj file, and type the following

func azure functionapp publish <Function App name>
YEAH!!! IT’s DONE! It´s all on AZUREEEEEEEEE!!!

EXTRA NOTE

As you can see I´ve used CLI commands, and you can make use of Azure CLI and Powershell in Azure DevOps tasks… and doing so, you can automate all this!

Hope you enjoyed it! Don´t forget that you still have to make a better solution for the connection strings that are in the local.hosts.json and those don't go to Azure! I might write something on … How to use an Azure KeyVault to store secrets and extract them, like… A connection string!

Links Library :

Dave Brock

Azure Functions Worker GitHub

Microsoft Documents

Tech Repository Blog

--

--

Claudio Santos

A tech-savvy, .net developer, regular crazy guy! C#, Xamarin, Unity, AR/VR/MR, Azure, Angular... But also concerned about the planet and people!