An idea that’s been floating around my head for a while is how to monitor those pesky Flows where something has not gone quite right. Where no matter how much error handling you put in, there’s always something you miss.
My main concern with Flows is that they never fail, so no matter the error they keep on running as best they can. At first I sent myself emails when a Flow had reached a non expected condition so at least I knew. This escalated to emailing the IT support so they knew.
Now, as the apps and Flows get more business critical, it’s time to do it (more) properly.
I’m starting with each environment having its Flow Entity, which is a custom DataVerse entity any Flow (or app) can write to to log Flow runs and any useful output.
The fields (to start with) in the entity.
Flow Name | Flow Run URL | Triggering User | Severity | Key Info | Last Action Run | Description |
The Flow name, Flow run URL, Triggering User, Last Action Run and Description will generally be auto populated from the Flow info. Severity will be the Flow writer’s choice, and Key Info I added as there will generally be something that has gone wrong, such as a User failed to be created or a record failed to be updated, so this field can provide a quick search facility.
All a work in progress …
The immediate thing that comes to mind, is there will be a Flow that fires on a log severity of ‘Critical’ to warn IT Support or similar there has been an error that needs fixing.
Building Blocks
- A Flow Log entity with some useful fields.
- A cut and paste DataVerse/SharePoint action template to write to the log
- An app to view the log files – each app can have their own view on the Flow log filtered by the app name.
Here is the Flow action to write to DataVerse and the form:


where:
Flow Name is workflow()?['tags']?['flowDisplayName']
Description and Last Action Run come from the error output post.
Flow Run URL is concat('https://unitedkingdom.flow.microsoft.com/manage/environments/',workflow()['tags']['environmentName'],'/flows/',workflow()['name'],'/runs/',workflow()['run']['name'])
(Change region to match!)
The triggering user variable depends on the type of Flow, but in DataVerse it will generally be “triggerBody()[‘RunAsSystemUserId’]
“
Or alternatively if you can’t use DataVerse, use a SharePoint List with the same fields. Triggering User Claims is a bit different, passing in a user name will work.


To Solution-ise this (DataVerse):
Create a Flow Log table and a model driven app to view the logs.
The basic solution of the table and the model driven app is available (unmanaged) on my GitHub.
Then in the Flow where you want to log something, you will need two Scope actions, one named Try and one named Catch. The Try scope will include the actions that may fail, and the Catch is the logging to Flow. The Catch scope has to be configured to run on failure of the Try scope.
These can be pasted into the Flow editor.
Try:
{"id":"4d53b6b6-0c97-4e9b-87ec-4169-9f2ceea2","brandColor":"#8C3900","connectorDisplayName":"Control","icon":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=","isTrigger":false,"operationName":"Try","operationDefinition":{"type":"Scope","actions":{},"runAfter":{}}}
and Catch:
{"id":"f0af6e92-20c9-42c3-9228-c258-a58e06c8","brandColor":"#8C3900","connectorDisplayName":"Control","icon":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=","isTrigger":false,"operationName":"Catch","operationDefinition":{"type":"Scope","actions":{"Add_a_new_row_to_Flow_Logs":{"type":"OpenApiConnection","inputs":{"host":{"connectionName":"shared_commondataserviceforapps","operationId":"CreateRecord","apiId":"/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"},"parameters":{"entityName":"mjb_flowlogs","item/mjb_flowname":"@workflow()?['tags']?['flowDisplayName']","item/mjb_description":"@result('Try')[0].outputs.body.error.message","item/mjb_flowrunurl":"@concat('https://unitedkingdom.flow.microsoft.com/manage/environments/', workflow()['tags']['environmentName'], '/flows/', workflow()['name'], '/runs/', workflow()['run']['name'])","item/mjb_lastactionrun":"@result('Try')[0].name"},"authentication":{"type":"Raw","value":"@json(decodeBase64(triggerOutputs().headers['X-MS-APIM-Tokens']))['$ConnectionKey']"}},"runAfter":{}}},"runAfter":{"Try":["Failed","TimedOut"]}}}
And the Add row to Logs as a standalone (again, you will need to add a connection if it gives you a red error – if there is already a DataVerse connection in the Flow it will just work):
{"id":"70160417-f324-48ee-ad25-312f-f92f3a3d","brandColor":"#088142","connectorDisplayName":"Microsoft Dataverse","icon":"https://connectoricons-prod.azureedge.net/releases/v1.0.1473/1.0.1473.2431/commondataserviceforapps/icon.png","isTrigger":false,"operationName":"Add_a_new_basic_row_to_Flow_Logs","operationDefinition":{"type":"OpenApiConnection","inputs":{"host":{"connectionName":"shared_commondataserviceforapps","operationId":"CreateRecord","apiId":"/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"},"parameters":{"entityName":"mjb_flowlogs","item/mjb_flowname":"@workflow()?['tags']?['flowDisplayName']","item/mjb_description":"A Description to be entered","item/mjb_flowrunurl":"@concat('https://unitedkingdom.flow.microsoft.com/manage/environments/', workflow()['tags']['environmentName'], '/flows/', workflow()['name'], '/runs/', workflow()['run']['name'])","item/mjb_keyinfo":"This Record Failed","item/mjb_lastactionrun":"Action XYZ","item/mjb_severity":100000002},"authentication":"@parameters('$authentication')"},"runAfter":{}}}
These cut and pastes have connections removed, so they will need to be reconnected after pasting to your Flow.
Example: In a Flow where you are working, do a + New Step, go to the My Clipboard tab, and just Control V in the Try code snippet above.

This will then change to the Try Scope in the clipboard which you can then select. It is in this Try scope your other actions will be dragged/entered. Add another new step and paste in the Catch Scope in the same way.
If you already have a DataVerse connector in the Flow it will automatically use that one, otherwise select one from the ellipsis and Connection references.
Your Flow should look like this:

Add in an action that will fail in the Try scope, example on a badly formatted user name:

On the Catch scope, click on Configure run after:

and then select run after : has failed (and others if required).

Then test. And hey presto, on deleting a row in the Flow Log table, another row appears!
