Everything you need to know to write, debug, deploy and monitor Azure Functions

Step by step guide using a light weight approach

1. Introduction

public void Configure(...) {
//...
Task.Factory.StartNew(() => {
while (true) {
//Capture some data
//...

//Now waits for 15 minutes or so
Thread.Sleep(new TimeSpan(someInterval));
}
});
}

2. Set up NodeJS and npm packages

$ npm install -g azure-functions-core-tools@latest

3. Install .NET Core and Visual Studio Code

Image for post
Image for post
<TargetFramework>netcoreapp2.1</TargetFramework>
Image for post
Image for post
Image for post
Image for post
Image for post
Image for post
Image for post
Image for post

4. Restructure the folder hierarchy

Image for post
Image for post
Image for post
Image for post
{
"bindings": [{
"name": "FunctionApp1or2",
"type": "timerTrigger",
"direction": "in",
"runOnStartup": true,
"schedule": "*/1 * * * * *"
}]
}

5. AzureWebJobStorage

{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}

Some Troubleshooting tips

Image for post
Image for post
Image for post
Image for post

6. Logging

public static void Run([TimerTrigger("0 */2 * * * *")]TimerInfo myTimer, ILogger log) {
log.LogInformation("...");
}
{ 
"version": "2.0",
"logging": {
"logLevel": {
"default": "Error"
}
}
}

7. Logging in other classes’ methods

8. Dependency Injection

$ dotnet add package AzureFunctions.Autofac --version 3.0.5
using System;
using Microsoft.Azure.WebJobs.Host.Config;
using Microsoft.Extensions.DependencyInjection;
using Autofac;
using AzureFunctions.Autofac.Configuration;
using Microsoft.Extensions.Logging;
namespace ExampleAzFuncs {
public class AutofacConfig {
public AutofacConfig(string functionName) {
DependencyInjection.Initialize(builder => {
builder.Register(ctx => new ServiceCollection()
.AddLogging()
.BuildServiceProvider()
.GetService<ILoggerFactory>())
.As<ILoggerFactory>();
}, functionName);
}
}
}
//IServiceHelper.cs
namespace ExampleAzFuncs {
public interface IServiceHelper {
string Greet(string message);
}
}
//ServiceHelper.cs
namespace ExampleAzFuncs {
public class ServiceHelper : IServiceHelper {
public string Greet(string message) {
//We'll add logging later
return "Hello "+ message;
}
}
}
public AutofacConfig(string functionName) {
DependencyInjection.Initialize(builder => {
builder.RegisterType<ServiceHelper>().As<IServiceHelper>();
builder.Register(ctx => new ServiceCollection()
.AddLogging()
.BuildServiceProvider()
.GetService<ILoggerFactory>())
.As<ILoggerFactory>();
}, functionName);
}
$ dotnet add package Microsoft.Extensions.Logging.Console --version 2.1.1
//ServiceHelper.cs
using AzureFunctions.Autofac;
using AzureFunctions.Autofac.Configuration;
using Microsoft.Extensions.Logging;

namespace ExampleAzFuncs {
[DependencyInjectionConfig(typeof(AutofacConfig))]
public class ServiceHelper : IServiceHelper {
private ILogger _logger;
public ServiceHelper([Inject] ILoggerFactory logFactory){
_logger = logFactory.AddConsole(LogLevel.Information)
.CreateLogger<ServiceHelper>();
}

public string Greet(string message) {
_logger.LogInformation($"[{System.DateTime.Now}] Message is {message}");
return "Hello "+ message;
}
}
}
$ dotnet add package Microsoft.Extensions.Logging.AzureAppServices — version 2.1.1
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using AzureFunctions.Autofac;
using AzureFunctions.Autofac.Configuration;
namespace ExampleAzFuncs {
[DependencyInjectionConfig(typeof(AutofacConfig))]
public static class FunctionApp1 {
[FunctionName("FunctionApp1")]
public static void Run(
[TimerTrigger("0 */1 * * * *")]TimerInfo myTimer,
ILogger log,
[Inject] IServiceHelper serviceHelper) {

serviceHelper.Greet("Azure Function");
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
}
}
Image for post
Image for post

9. Debug locally

10. Deploy to Azure

Image for post
Image for post
"AzureWebJobsStorage": "UseDevelopmentStorage=true",

11. Logging in Production

Image for post
Image for post

12. Conclusion

Written by

Driven by passion and patience. Read my shorter posts https://dev.to/codeprototype (possibly duplicated from here but not always)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store