Introduction

Recently in the forums, some Logic App users were asking how to query the state of their Logic Apps.  The scenario were not uncommon in that the expected Logic App process time could not be determined and for legitimate reasons can take longer than timeouts or users would accept.

There is no easy way to do this with existing services to the level of a specific Logic App instance, but it is very easy to do using other Azure services, specifically Azure Functions and Redis Cache.

For clarity, this post is not about security or performance or cache design.  All things you should consider separately and apply patterns necessary to meet requirements or goals.

Note: These Portal steps are current as of February 2018.

Redis Cache Instance

The first thing to create is an instance of Azure Redis Cache.  That takes only three steps in the Portal.

1. Create your instance of Azure Redis Cache.  This one is MyCompanyLogicAppStatus.

2. Next, you will need a connection string from the Access Keys section of the newly created cache instance.

And that’s all we need to do when creating a basic Redis Cache instance.

Azure Function

Next, we create an Azure Function that will be the interface to our Azure Redis Cache.

1. Click Create a resource

2. Then click Serverless Function App

3. Complete the details for your Function.  Be sure to correctly set the Resource Group and Storage.

4. Select Application Settings and add the connection string for your Redis Cache to the Connection strings list.

5. Modify or create project.json to include the reference to StackExchange.Redis.

{
   "frameworks": {
     "net46":{
       "dependencies": {
         "StackExchange.Redis": "1.2.1"
       }
     }
    }
}

6. Modify function.json to support the PUT and GET methods.  Basically, change POST to PUT.

{
   "bindings": [
     {
       "authLevel": "function",
       "name": "req",
       "type": "httpTrigger",
       "direction": "in",
       "methods": [
         "get",
         "put"
       ]
     },
     {
       "name": "$return",
       "type": "http",
       "direction": "out"
     }
   ],
   "disabled": false
}

For simplicity, the function will use either PUT or GET with 3 or 2 parameters.  This is merely a sample so feel free to use fewer or more parameters in any composition you need.

The PUT code will be called by the Logic App to set it’s current state.  In this case, we’re going to use a combination key of [LogicApp Name] + [OrderNumber], ProcessOrder+12345 for example, as the cache key with any text as the value.

The GET code will be called by any client interested in the state of it’s process using the key as it’s parameter.

using System.Net;
using StackExchange.Redis;
 
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
     log.Info("C# HTTP trigger function processed a request.");
 
    string cstring = System.Configuration.ConfigurationManager.ConnectionStrings["SampleLogicAppState"].ConnectionString;
     ConnectionMultiplexer LogicAppStatusConnection = ConnectionMultiplexer.Connect(cstring);
     
     System.Net.Http.Headers.HttpRequestHeaders reqHeaders = req.Headers;
     string LogicApp = reqHeaders.Contains("LogicApp") ? reqHeaders.GetValues("LogicApp").First() : null;
     string ID = reqHeaders.Contains("ID") ? reqHeaders.GetValues("ID").First() : null;
     string Status = reqHeaders.Contains("Status") ? reqHeaders.GetValues("Status").First() : null;
 
    string cacheKey = LogicApp + "+" + ID;
     IDatabase LogicAppStatusCache = LogicAppStatusConnection.GetDatabase();
 
    if(req.Method == HttpMethod.Put)
     {
         LogicAppStatusCache.StringSet(cacheKey, Status);
         return req.CreateResponse(HttpStatusCode.OK, cacheKey);
     }
     else if(req.Method == HttpMethod.Get)
     {
         string cacheStatus = (string)LogicAppStatusCache.StringGet(cacheKey) ?? "Unknown";
         return req.CreateResponse(HttpStatusCode.OK, cacheStatus);
     }
     else
     {
         return req.CreateResponse(HttpStatusCode.MethodNotAllowed);
     }
}

Logic App

Finally, we need a Logic App to to write some state to our status interface.  In this case, all we need is a fake order process which sets our status.

The Logic App here consists most of calls to our Function to set the status, and a delay.

In more detail, we can see that Azure Function Action calls our status function with the details necessary to cache the current status.  The Delay Action is merely to allow us to see the changing status over time.  Note, once you select the Function when adding the Action, the function name is no longer displayed.

Testing

The process is very easy to test with Postman.

First, we submit an Order we need to track the status of during processing.

{
     "OrderNumber" : "34567",
     "OrderDate" : "20180211",
     "OrderItem" : "Send me a fun LogicApp Demo!"
}

Next, we can use the GET method with the LogicAppName and ID to get the current status of our running LogicApp.

Final Thoughts

Here are some things you should consider when knowing the state of a process is important: