- Print
- Comment
- DarkLight
- PDF
BAM when you have an existing logic app you cant change
If you like the BAM videos I have been doing and want to use BAM but your existing Logic Apps are already in production and you can not change them, fear not you can still use BAM. If you accept a couple of constraints as to how you can use BAM then its possible to subscribe to the diagnostics events that Logic Apps pushes to an event hub and then filter/map the events and forward them to the Serverless360 BAM API. This would allow you to be able to get the value from a BAM view of your processes to simplify the operations of them and to allow some self service for your users but without the need to change your existing logic apps. The main constraints for this pattern are as follows:
- You need to aim for 1 BAM transaction per Logic App you want to use BAM with
- You need to map and filter the events from diagnostics to get rid of the noise
- You would use the CheckPoint with correlation approach discussed in a previous video and correlate events based on the LogicApp run ID.
The below video will walk you through how to do this.
The article I talk about in the video is on this link:
https://docs.serverless360.com/docs/implicit-bam-vs-explicit-bam
Sample Mappings
Below is the example mapping data which I used to filter and map the diagnostics events for BAM.
[
{
"workflowId": "/SUBSCRIPTIONS/[My Sub]/RESOURCEGROUPS/BAM_BUSINESSPROCESS_13_NOINSTRUMENTATION/PROVIDERS/MICROSOFT.LOGIC/WORKFLOWS/BP13",
"bam_businessProcessName": "Business Process 13 - No Instrumentation",
"bam_transactionName": "BP13",
"bam_startStageName": "Message Received",
"bam_endStageName": "Complete",
"stageMappings": [
{
"logicAppStepName": "Compose_-_Do_some_work_1",
"bam_StageName": "Compose - Do some work 1"
},
{
"logicAppStepName": "Compose_-_Do_some_work_2",
"bam_StageName": "Compose - Do some work 2"
},
{
"logicAppStepName": "Completed",
"bam_StageName": "Completed"
}
]
},
{
"workflowId": "/SUBSCRIPTIONS/[My Sub]/RESOURCEGROUPS/BAM_BUSINESSPROCESS_13_NOINSTRUMENTATION/PROVIDERS/MICROSOFT.LOGIC/WORKFLOWS/BP_13_DEMO",
"bam_businessProcessName": "Business Process 13 - No Instrumentation",
"bam_transactionName": "BP13-Demo",
"bam_startStageName": "Received Order",
"bam_endStageName": "Logic App Complete",
"stageMappings": [
{
"logicAppStepName": "Compose_-_Check_Order",
"bam_StageName": "Checking Order"
},
{
"logicAppStepName": "Compose_-_Order_Approved",
"bam_StageName": "Order Approved"
},
{
"logicAppStepName": "Compose_-_Order_Declined",
"bam_StageName": "Order Exceeds Limit"
},
{
"logicAppStepName": "Compose_-_Process_Order",
"bam_StageName": "Process Order"
},
{
"logicAppStepName": "Compose_-_Customer_Number",
"bam_StageName": "Create Customer"
},
{
"logicAppStepName": "Compose_-_Order_Number",
"bam_StageName": "Create Order"
}
]
}
]
Sample Logic App Definition
Below is the json for the sample logic app i used to be able to process logic app diagnostics events and to push them to BAM.
{
//Note: If you want to try this make sure to check the connections at the bottom to make sure they would point to your A Logic App connectors
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"Compose": {
"inputs": "@triggerBody()?['ContentData']",
"runAfter": {
"Parse_JSON_-_Mappings": [
"Succeeded"
]
},
"type": "Compose"
},
"Compose_-_BAM_Mappings": {
"inputs": [
{
"bam_businessProcessName": "Business Process 13 - No Instrumentation",
"bam_endStageName": "Complete",
"bam_startStageName": "Message Received",
"bam_transactionName": "BP13",
"stageMappings": [
{
"bam_StageName": "Compose - Do some work 1",
"logicAppStepName": "Compose_-_Do_some_work_1"
},
{
"bam_StageName": "Compose - Do some work 2",
"logicAppStepName": "Compose_-_Do_some_work_2"
},
{
"bam_StageName": "Completed",
"logicAppStepName": "Completed"
}
],
"workflowId": "/SUBSCRIPTIONS/[My Sub ID]/RESOURCEGROUPS/BAM_BUSINESSPROCESS_13_NOINSTRUMENTATION/PROVIDERS/MICROSOFT.LOGIC/WORKFLOWS/BP13"
},
{
"bam_businessProcessName": "Business Process 13 - No Instrumentation",
"bam_endStageName": "Logic App Complete",
"bam_startStageName": "Received Order",
"bam_transactionName": "BP13-Demo",
"stageMappings": [
{
"bam_StageName": "Checking Order",
"logicAppStepName": "Compose_-_Check_Order"
},
{
"bam_StageName": "Order Approved",
"logicAppStepName": "Compose_-_Order_Approved"
},
{
"bam_StageName": "Order Exceeds Limit",
"logicAppStepName": "Compose_-_Order_Declined"
},
{
"bam_StageName": "Process Order",
"logicAppStepName": "Compose_-_Process_Order"
},
{
"bam_StageName": "Create Customer",
"logicAppStepName": "Compose_-_Customer_Number"
},
{
"bam_StageName": "Create Order",
"logicAppStepName": "Compose_-_Order_Number"
}
],
"workflowId": "/SUBSCRIPTIONS/[My Sub ID]/RESOURCEGROUPS/BAM_BUSINESSPROCESS_13_NOINSTRUMENTATION/PROVIDERS/MICROSOFT.LOGIC/WORKFLOWS/BP_13_DEMO"
}
],
"runAfter": {},
"type": "Compose"
},
"For_each_-_Event_Hub_Record": {
"actions": {
"Compose_-_Event_Hub_Message": {
"inputs": "@items('For_each_-_Event_Hub_Record')",
"runAfter": {},
"type": "Compose"
},
"For_each_-_BAM_Mapping": {
"actions": {
"Condition_-_Logic_App_Workflow_ID_Matches": {
"actions": {
"Switch": {
"cases": {
"Case_-_Workflow_Started": {
"actions": {
"Parse_JSON_-_Logic_App_Started": {
"inputs": {
"content": "@items('For_each_-_Event_Hub_Record')",
"schema": {
"properties": {
"category": {
"type": "string"
},
"level": {
"type": "string"
},
"operationName": {
"type": "string"
},
"properties": {
"properties": {
"$schema": {
"type": "string"
},
"correlation": {
"properties": {
"clientTrackingId": {
"type": "string"
}
},
"type": "object"
},
"resource": {
"properties": {
"location": {
"type": "string"
},
"originRunId": {
"type": "string"
},
"resourceGroupName": {
"type": "string"
},
"runId": {
"type": "string"
},
"subscriptionId": {
"type": "string"
},
"workflowId": {
"type": "string"
},
"workflowName": {
"type": "string"
}
},
"type": "object"
},
"startTime": {
"type": "string"
},
"status": {
"type": "string"
},
"tags": {
"properties": {},
"type": "object"
}
},
"type": "object"
},
"resourceId": {
"type": "string"
},
"time": {
"type": "string"
},
"workflowId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
},
"Start_Transaction_-_Logic_App_Started": {
"inputs": {
"body": {
"MessageBody": "@body('Parse_JSON_-_Logic_App_Started')",
"MessageHeader": {
"LogicAppID": "@{body('Parse_JSON_-_Logic_App_Started')?['properties']?['resource']?['runId']}"
}
},
"headers": {
"SL360-ArchiveMessage": "True",
"SL360-BusinessProcess": "@items('For_each_-_BAM_Mapping')['bam_businessProcessName']",
"SL360-IsTransactionComplete": "False",
"SL360-Stage": "@items('For_each_-_BAM_Mapping')['bam_startStageName']",
"SL360-StageStatus": "Success",
"SL360-Transaction": "@items('For_each_-_BAM_Mapping')['bam_transactionName']"
},
"host": {
"connection": {
"name": "@parameters('$connections')['SL360-BAM']['connectionId']"
}
},
"method": "post",
"path": "/api/StartTransaction"
},
"runAfter": {
"Parse_JSON_-_Logic_App_Started": [
"Succeeded"
]
},
"type": "ApiConnection"
}
},
"case": "Microsoft.Logic/workflows/workflowRunStarted"
},
"Case_-_workflowActionCompleted": {
"actions": {
"Condition_-_Send_Event_to_BAM": {
"actions": {
"For_each_-_Stage_Mapping": {
"actions": {
"Condition_-_Stage_Mapping_Name": {
"actions": {
"Checkpoint_With_Correlation_-_Action_Complete": {
"inputs": {
"body": {
"MessageBody": "@body('Parse_JSON_-_Action_Complete')",
"Property": [
{
"Name": "LogicAppID",
"Value": "@body('Parse_JSON_-_Action_Complete')?['properties']?['resource']?['runId']"
}
]
},
"headers": {
"SL360-ArchiveMessage": "True",
"SL360-BusinessProcess": "@items('For_each_-_BAM_Mapping')['bam_businessProcessName']",
"SL360-IgnoreNotFound": "True",
"SL360-Stage": "@items('For_each_-_Stage_Mapping')['bam_StageName']",
"SL360-StageStatus": "@{outputs('Compose_-_Stage_Result')}",
"SL360-Transaction": "@items('For_each_-_BAM_Mapping')['bam_transactionName']"
},
"host": {
"connection": {
"name": "@parameters('$connections')['SL360-BAM']['connectionId']"
}
},
"method": "post",
"path": "/api/CheckpointWithCorrelation"
},
"runAfter": {
"Compose_-_Stage_Result": [
"Succeeded"
]
},
"type": "ApiConnection"
},
"Compose_-_Stage_Result": {
"inputs": "@if(equals(body('Parse_JSON_-_Action_Complete')?['properties']?['status'], 'Succeeded'), 'Success', 'Failure')",
"runAfter": {},
"type": "Compose"
}
},
"expression": {
"and": [
{
"equals": [
"@body('Parse_JSON_-_Action_Complete')?['properties']?['resource']?['actionName']",
"@items('For_each_-_Stage_Mapping')['logicAppStepName']"
]
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "@items('For_each_-_BAM_Mapping')['stageMappings']",
"runAfter": {},
"type": "Foreach"
}
},
"expression": {
"and": [
{
"not": {
"equals": [
"@body('Parse_JSON_-_Action_Complete')?['properties']?['status']",
"Skipped"
]
}
}
]
},
"runAfter": {
"Parse_JSON_-_Action_Complete": [
"Succeeded"
]
},
"type": "If"
},
"Parse_JSON_-_Action_Complete": {
"inputs": {
"content": "@items('For_each_-_Event_Hub_Record')",
"schema": {
"properties": {
"category": {
"type": "string"
},
"level": {
"type": "string"
},
"operationName": {
"type": "string"
},
"properties": {
"properties": {
"$schema": {
"type": "string"
},
"correlation": {
"properties": {
"actionTrackingId": {
"type": "string"
},
"clientTrackingId": {
"type": "string"
}
},
"type": "object"
},
"resource": {
"properties": {
"actionName": {
"type": "string"
},
"location": {
"type": "string"
},
"resourceGroupName": {
"type": "string"
},
"runId": {
"type": "string"
},
"subscriptionId": {
"type": "string"
},
"workflowId": {
"type": "string"
},
"workflowName": {
"type": "string"
}
},
"type": "object"
},
"startTime": {
"type": "string"
},
"status": {
"type": "string"
},
"tags": {
"properties": {},
"type": "object"
}
},
"type": "object"
},
"resourceId": {
"type": "string"
},
"time": {
"type": "string"
},
"workflowId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
}
},
"case": "Microsoft.Logic/workflows/workflowActionCompleted"
},
"Case_-_workflowRunCompleted": {
"actions": {
"Checkpoint_With_Correlation_-_Logic_App_Finished": {
"inputs": {
"body": {
"MessageBody": "@body('Parse_JSON_-_Logic_App_Complete')",
"Property": [
{
"Name": "LogicAppID",
"Value": "@body('Parse_JSON_-_Logic_App_Complete')?['properties']?['resource']?['runId']"
}
]
},
"headers": {
"SL360-ArchiveMessage": "True",
"SL360-BusinessProcess": "@items('For_each_-_BAM_Mapping')['bam_businessProcessName']",
"SL360-IgnoreNotFound": "True",
"SL360-IsTransactionComplete": "True",
"SL360-Stage": "@items('For_each_-_BAM_Mapping')['bam_endStageName']",
"SL360-StageStatus": "@{outputs('Compose_-_Complete_Stage_Status')}",
"SL360-Transaction": "@items('For_each_-_BAM_Mapping')['bam_transactionName']"
},
"host": {
"connection": {
"name": "@parameters('$connections')['SL360-BAM']['connectionId']"
}
},
"method": "post",
"path": "/api/CheckpointWithCorrelation"
},
"runAfter": {
"Compose_-_Complete_Stage_Status": [
"Succeeded"
]
},
"type": "ApiConnection"
},
"Compose_-_Complete_Stage_Status": {
"inputs": "@if(equals(body('Parse_JSON_-_Logic_App_Complete')?['properties']?['status'], 'Failed'), 'Failure', 'Success')",
"runAfter": {
"Parse_JSON_-_Logic_App_Complete": [
"Succeeded"
]
},
"type": "Compose"
},
"Parse_JSON_-_Logic_App_Complete": {
"inputs": {
"content": "@items('For_each_-_Event_Hub_Record')",
"schema": {
"properties": {
"category": {
"type": "string"
},
"level": {
"type": "string"
},
"operationName": {
"type": "string"
},
"properties": {
"properties": {
"$schema": {
"type": "string"
},
"correlation": {
"properties": {
"clientTrackingId": {
"type": "string"
}
},
"type": "object"
},
"endTime": {
"type": "string"
},
"resource": {
"properties": {
"location": {
"type": "string"
},
"originRunId": {
"type": "string"
},
"resourceGroupName": {
"type": "string"
},
"runId": {
"type": "string"
},
"subscriptionId": {
"type": "string"
},
"workflowId": {
"type": "string"
},
"workflowName": {
"type": "string"
}
},
"type": "object"
},
"startTime": {
"type": "string"
},
"status": {
"type": "string"
},
"tags": {
"properties": {},
"type": "object"
}
},
"type": "object"
},
"resourceId": {
"type": "string"
},
"time": {
"type": "string"
},
"workflowId": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
}
},
"case": "Microsoft.Logic/workflows/workflowRunCompleted"
}
},
"default": {
"actions": {
"Compose_-_Log_Default": {
"inputs": "Currently we will skip this\n\n@{body('Parse_JSON_-_Logic_App_Events')}",
"runAfter": {},
"type": "Compose"
}
}
},
"expression": "@items('For_each_-_Event_Hub_Record')?['operationName']",
"runAfter": {},
"type": "Switch"
}
},
"description": "Does the logic app id match the id of the workflow in the mappings",
"expression": {
"and": [
{
"equals": [
"@items('For_each_-_Event_Hub_Record')?['workflowId']",
"@items('For_each_-_BAM_Mapping')['workflowId']"
]
}
]
},
"runAfter": {},
"type": "If"
}
},
"foreach": "@body('Parse_JSON_-_Mappings')",
"runAfter": {
"Compose_-_Event_Hub_Message": [
"Succeeded"
]
},
"type": "Foreach"
}
},
"foreach": "@body('Parse_JSON_-_Logic_App_Events')?['records']",
"runAfter": {
"Parse_JSON_-_Logic_App_Events": [
"Succeeded"
]
},
"type": "Foreach"
},
"Parse_JSON_-_Logic_App_Events": {
"inputs": {
"content": "@triggerBody()?['ContentData']",
"schema": {
"properties": {
"records": {
"items": {
"properties": {
"category": {
"type": "string"
},
"level": {
"type": "string"
},
"operationName": {
"type": "string"
},
"resourceId": {
"type": "string"
},
"time": {
"type": "string"
},
"workflowId": {
"type": "string"
}
},
"required": [
"time",
"workflowId",
"resourceId",
"category",
"level",
"operationName"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
"runAfter": {
"Compose": [
"Succeeded"
]
},
"type": "ParseJson"
},
"Parse_JSON_-_Mappings": {
"inputs": {
"content": "@outputs('Compose_-_BAM_Mappings')",
"schema": {
"items": {
"properties": {
"bam_businessProcessName": {
"type": "string"
},
"bam_endStageName": {
"type": "string"
},
"bam_startStageName": {
"type": "string"
},
"bam_transactionName": {
"type": "string"
},
"stageMappings": {
"items": {
"properties": {
"bam_StageName": {
"type": "string"
},
"logicAppStepName": {
"type": "string"
}
},
"required": [
"logicAppStepName",
"bam_StageName"
],
"type": "object"
},
"type": "array"
},
"workflowId": {
"type": "string"
}
},
"required": [
"workflowId",
"bam_businessProcessName",
"bam_transactionName",
"bam_startStageName",
"bam_endStageName",
"stageMappings"
],
"type": "object"
},
"type": "array"
}
},
"runAfter": {
"Compose_-_BAM_Mappings": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"When_events_are_available_in_Event_Hub": {
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['eventhubs']['connectionId']"
}
},
"method": "get",
"path": "/@{encodeURIComponent('logicapptelemetry')}/events/batch/head",
"queries": {
"consumerGroupName": "$Default",
"contentType": "application/json",
"maximumEventsCount": 50
}
},
"recurrence": {
"frequency": "Second",
"interval": 30
},
"splitOn": "@triggerBody()",
"type": "ApiConnection"
}
}
},
"parameters": {
"$connections": {
"value": {
"SL360-BAM": {
"connectionId": "/subscriptions/[Add Subscription]/resourceGroups/BAM_BusinessProcess_13_NoInstrumentation/providers/Microsoft.Web/connections/SL360-BAM",
"connectionName": "SL360-BAM",
"id": "/subscriptions/[Add Subscription]/resourceGroups/BAM_BusinessProcess1_SimpleDemo/providers/Microsoft.Web/customApis/SL360-BAM"
},
"eventhubs": {
"connectionId": "/subscriptions/[Add Subscription]/resourceGroups/BAM_BusinessProcess_13_NoInstrumentation/providers/Microsoft.Web/connections/eventhubs",
"connectionName": "eventhubs",
"id": "/subscriptions/[Add Subscription]/providers/Microsoft.Web/locations/northeurope/managedApis/eventhubs"
}
}
}
}
}