In part 1 of this series, we looked at how you could use Azure Functions to host a static website. The function basically served up static files it read off the file system and delivered them as HTTP responses. Websites though are not complete without logging! Logging is already supported in functions when one calls the context.log method, however if you want custom logging that is more easily parseable, you can implement a table output binding and easily write custom logs out to the binding.

If you have not already done so, setup a website according to the instructions in the first post, then you’ll be ready to add a custom log to the post.

  1. To add a log, open the GetPage function you created in the editor in Azure Portal, then select select Integrate, then click on New Output, then select Azure Table Storage. Finally, click on Select.
  2. Change Table name to log and the Storage account connection to AzureWebJobStorage, then click on Save. This is the default storage account that is created whenever you create the Function App. Finally click Save.
  3. Now, open the code editor for GetPage, and replace the code with the following code. This code builds on the last code you used in the Function App. Notice the context.bindings.outputTable. This is where the logging happens. The required fields for table storage are the partitionKey and rowKey. The partition key can be more or less static, but the row key needs to be unique. This implementation uses a UUID. The rest of the fields however are optional. We’re logging the HTTP method, the request file, the users agent (browser info), and the referrer who sent the user to the site. Later in the code, the HTTP status us set, either to 200 for OK or 404 for not found. After pasting the code, click Save.
      var fs = require("fs")
      var mime = require('mime-types')
      function uuidv4() {
       return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
         var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
         return v.toString(16);
      module.exports = function (context, req) {
          var file="index.html"
          if (req.query.file) {
          file = file.replace(/\//g, "\\");
          fs.readFile(__dirname + "\\content\\" +  file, function(err, data) {
             context.log('GET ' + __dirname + "\\content\\" +  file);
             context.bindings.outputTable = {
                 "partitionKey": "log",
                 "method": req.method,
                 "file": file,
                 "from": req.headers["x-forwarded-for"],
                 "useragent": req.headers["user-agent"],
                 "referer": req.headers["referer"]
              if (!err){
                  var contentType = mime.lookup(file) 
                  context.bindings.outputTable.status = 200
                  context.res = {
                      status: 200, 
                      body: data,
                      isRaw: true,
                      headers: {
                          'Content-Type': contentType
                  context.log("Error: " + err)
                  context.bindings.outputTable.status = 404
                  context.res = {
                      status: 404, 
                      body: "Not Found.",
                      headers: {
  4. Now, load the site at the same URL from Part 1. Everything looks exactly the same in the browser. The only difference now though is there are logs going to Azure table storage. To view the logs, you can use Azure Storage Explorer. This utility lets you see all the blobs, files, tables, and queues in your storage accounts. Click on the User icon, then click Add an account. Depending on how you connect to the storage account depends on how you will complete the wizard. Most likely, you can choose Add an Azure account and complete the wizard that way.
  5. Once Storage Explorer is connected, you can drill down into the storage account for your Function App and find the table called log and view the logs.


As you’re beginning to see, you can do all sorts of things with function apps. A static website with custom logging is one of many different ways to use it. Next time, we’ll look at how to add a feedback form to the a site using an Azure function with a CAPTCHA.

Stay tuned for part 3