Setting up a Debugging Environment for Azure Functions 2.x using VS Code

1,506 reads

@ joegatt Joe Gatt I build security programs and defend networks. Sometimes with Python or Azure Functions.

Overview

Debugging Azure Functions can be extremely easy if you add the appropriate logging and error handling to your code. However, there are going to be times where debugging with these techniques is simply not enough. As a result, we need a robust debugging environment to trace a transaction end to end. Before I get to the environment setup, I want to first outline the high-level transaction flow (as I understand it) for Azure Functions. Please refer to the diagram below, which was posted in March 2018 in the Azure Function Python Worker wiki here:

reactions

Overall, the Azure Functions Host is the host/runtime that powers Azure Functions apps. Starting at the top of the diagram, incoming HTTP transactions are first routed to the WebHost, which is a sub-component of Azure Functions Host. The WebHost processes the HTTP request and sends the transactions to the Azure Functions Python Worker aka the Python Worker. The Python Worker then routes the transaction to the appropriate function app.

reactions

It is apparent from this diagram to appropriately debug an Azure Function; you need to insert yourself into the Azure Functions Host, which is a dotnet core app written in C#. Please note that for the purposes of this tutorial, I am focused on debugging HTTP Trigger function apps. This tutorial assumes that you have a working understanding of Azure Functions and VS Code.

reactions

Software Pre-Requisites

There are two pre-requisites necessary to build and debug Azure Functions Host: dotnet core 2.x and Visual Studio (VS) Code.

reactions

dotnet core 2.2.x:

reactions

Download dotnetcore-sdk 2.x from here

Validate the checksum of the download by running openssl sha512 dotnet-sdk-2.2.207-osx-x64.pkg

VS Code:

reactions

Download VS Code from here

Install the C# and python extensions

Environment Setup

The following steps help create a stand-alone virtual environment where you can independently debug function apps separate from your other function app development environments. To begin, create a virtual environment and supporting folder structure:

reactions

python3 -m venv .afhvenv cd .afhvenv/ source bin/activate mkdir afdebugenv cd afdebugenv mkdir functions

As you will see later in the article, following the above folder structure will allow you to debug multiple versions of the Azure Functions Host at the same time.

reactions

Azure Functions Host Source Code

Download source code of Azure Functions Host’s latest production release. Please note: you can, of course, download any branch you want from GitHub; however, I want what’s running in production since non-production branches may not build successfully. From the root of the afdebugenv run the following commands:

reactions

wget https://github.com/Azure/azure-functions-host/archive/2.0.12888.zip unzip 2.0.12888.zip

When finished, you will build the debug version of the Azure

Function Host from source using the dotnet executable from the command line:

reactions

cd azure-functions-host-2.0.12888 dotnet build -c Debug WebJobs.Script.sln

This build will take a few minutes to complete and should build with no errors (even on my MacBook Pro).

reactions

Azure Functions Host Symbol files

Symbol files hold a variety of data that are not actually needed when running the binaries, but which could be very useful in the debugging process. Symbol files are specific for each version of the software, so we are going to create a symbol folder in our Azure Functions Host folder. From the root of the version of Azure Functions Host that you are debugging run the following commands:

reactions

mkdir symbols wget https://github.com/Azure/azure-functions-host/releases/download/2.0.12888/Functions.Symbols.2.0.12888.win-x64.zip unzip Functions.Symbols.2.0.12888.win-x64.zip

Azure Functions Python Worker

The Azure Functions Host ships with a python worker which we will use for debugging purposes. Please note: the below path is specific to my setup (OS X), the path to your worker.py will be some variation after “

../netcoreapp2.2/workers..

reactions

cd /azure-functions-host-2.0.12888/src/WebJobs.Script.WebHost/bin/Debug/netcoreapp2.2/workers/python/3.7/OSX/X64 wget https://gist.githubusercontent.com/gattjoe/2b2e77a14cd461a131eee9ebc1539f0d/raw/a1c52c3bfb5be87b21bcdfd1e09fbea787ae06ed/worker.config.json

”. From the worker directory, run the following commands:

After you download

worker.config.json

worker.config.json

worker.config.json

reactions

"Arguments" : [ "-m ptvsd --host 127.0.0.1 --port 9091" ]

VS Code Setup

to the worker directory, you have to configure the python worker to run in debug mode when it is called by VS Code. For some background on the proper format of thefile, refer to this document . To enable debugging on theprocess, add the following directive to

Launch.json and tasks.json need to be customized to properly build and debug the Azure Functions Host. I am providing example files that will allow you to get up and running much quicker, which is why I was so specific as to the naming of directories above. Once you are comfortable, feel free to customize the

launch.json

reactions

mkdir .vscode cd .vscode wget https://gist.githubusercontent.com/gattjoe/ce03f5d7ea8294246efabaf048eb1c39/raw/820109fcdbd72b407c49b2c6e7aa9d68db03318a/tasks.json wget https://gist.githubusercontent.com/gattjoe/47b9e54f25d1d21800f02dd518d86bbb/raw/177908cf773e27f2936458200ba14484d6a55d4e/launch.json

file to meet your needs. At the root of the afdebugenv folder, run the following commands:

When finished, open VS Code from the afdebugenv directory. You

may get a notice that says, “Required assets to build and debug are missing

from ‘afdebugenv’. Add them?”. Say yes.

reactions

Install Additional Python Packages

We are effectively running the entire Azure Function stack locally, so we need to install ptvsd and Azure functions. Run the following command:

reactions

pip install ptvsd azure-functions

Validating Your Environment

If you made it this far, kudos to you. I thought about automating this entire process, but I figured that given the rapid pace of change in this space, it would be obsolete within a few months. Assuming you have a plain vanilla HTTP Trigger function app in your functions directory, we are going to run a short test below to ensure your environment is ready to start debugging. From the root of your afdebugenv directory, open up VS Code and perform the following steps:

reactions

In the explorer screen, navigate to the following path: “ afdebugenv/azure-functions-host-2.0.12888/src/WebJobs.Script.WebHost/Middleware/FunctionInvocationMiddleware.cs " In the first third of the code, you will find the following function definition: “ public async Task Invoke(HttpContext context) ”. Set a breakpoint in the left-hand gutter, which will be marked by a red dot To invoke the debugger for Azure Functions Host, in the debug screen, under the “debug and run” heading, select “.NET Core Launch” from the drop-down and press F5 You will notice that the integrated terminal opened with similar startup messages as when you execute "func host start". The only main difference is that the Azure Function Host is listening on port TCP 5000. Please refer to the screenshot below: To invoke the debugger for the python worker, in the debug screen, under the “debug and run” heading, select “Attach to Python Functions” from the drop-down and press F5 Run a test transaction against your HTTPTrigger The debugger should hit the breakpoint that you set in step 2, and you can now inspect the data that was passed to the function. Please refer to the screenshot below: To continue processing the transaction, hit F5. On your terminal where you executed the command, you should see your output. Additionally, the integrated terminal should reflect that you processed the transaction successfully To exit the debugging process, press the red square in the debugging control panel

Please note: Stopping the VS Code debugger will NOT kill the worker.py process spawned by Azure Functions Host. As a result, you have to manually kill the process to free ports TCP 5000 back up. Please note x2: you have to stop the VS Code debugger FIRST, otherwise, the Azure Functions Host will continually spawn up worker.py processes every time you kill it.

reactions

In future articles, I will be covering advanced debugging topics that rely on this article as a foundation. If you have any feedback, please send me a note at gattjoseph at <hotmail>.

reactions

Share this story @ joegatt Joe Gatt Read my stories I build security programs and defend networks. Sometimes with Python or Azure Functions.

Tags