What Are Logic Apps?
Logic Apps are a piece of integration workflow hosted on Azure which is used to create scale-able integrations between various systems. These are very easy to design and provide connectivity between various disparate systems using many out of the box connectors as well as with the facility to design custom connectors for specific purposes. This makes integration easier than ever as the design aspect of the earlier complex integrations is made easy with minimum steps required to get a workflow in place and get it running.
Problem Scenario
Whenever Logic Apps are Hosted onto the Microsoft Azure Platform for integrating various business flows, it becomes imperative that the Logic App run is monitored on a daily basis to check if there were any errors and resubmit the execution of the Logic Apps. There will be scenarios where Azure Administrators should be able to re-submit all the failed runs of the logic App. The problem with the Azure Powershell Get-AzureRmLogicAppRunHistory is that it returns only the latest 30 items.
The following Azure Powersehll command ony returns latest 30 runs
Get-AzureRmLogicAppRunHistory -ResourceGroupName $grpName -Name $logicApp.NameTo enumerate for all the Logic App Runs, REST API should be used to get all the runs using the paging mechanism. The REST can be called from PowerShell using
Invoke-RestMethod
REST APIs allow users to interact with various services over HTTP/HTTPS and follow a common methodology of using methods to read and manipulate information. REST return information in a standard way, typically through JavaScript Object Notation (JSON). The Invoke-RestMethod cmdlet is built with REST in mind. It allows the user to invoke various methods for web service APIs and easily parse the output.
The Invoke-RestMethod
cmdlet sends HTTP and HTTPS requests to Representational State Transfer (REST) web services that return richly structured data. PowerShell formats the response based on the data type. For JavaScript Object Notation (JSON) or XML, PowerShell converts (or deserializes) the content into objects.
Get Logic App Runs using REST
Azure exposes REST API to list the workflow runs.
https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Logic/workflows/{workflowName}/runs/{runName}?api-version=2016-06-01
The API endpoints are protected using oAuth2.0. The endpoints can be accessed using the Bearer token (Access Token). The Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer(access) tokens. The client must send the access token in the Authorization header when making requests to protected resources:Authorization: Bearer <token>
The access Token from the interactive login can be accessed using PowerShell as described below. The Access Token can also be retrieved using a registered appliaction credentials in Azure AD.
Connect-AzureRmAccount Get-AzureRmContext $subscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName $context = $subscription | Set-AzureRmContext $tokens = $context.TokenCache.ReadItems() | Where-Object { $_.TenantId -eq $context.Subscription.TenantId } | Sort-Object -Property ExpiresOn -Descending $token = $tokens[0].AccessToken
The Authentication header for Invoke-RestMethod can be passed as described below.
$headers = @{ 'Authorization' = 'Bearer ' + $token } Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers
The following code describes the method to get all the Logic App Runs and re-submit the failed one. The Response contains the nextLink property to get the link for the next Paging items.
function Get-LogicAppHistory { param ( [Parameter(Mandatory = $true)] $Token, [Parameter(Mandatory = $true)] $subscriptionId, [Parameter(Mandatory = $true)] $resourceGroupName, [Parameter(Mandatory = $true)] $logicAppName, [Parameter(Mandatory = $false)] $status, [Parameter(Mandatory = $true)] $startDateTime, [Parameter(Mandatory = $false)] $endDateTime ) $headers = @{ 'Authorization' = 'Bearer ' + $token } $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/runs?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName $method = (Invoke-RestMethod -Uri $uri -Headers $headers -Method Get) $output = $method.value foreach ($item in $output) { if ((($item.properties.status -eq $status) -and ($item.properties.startTime -ge $startDateTime)) -and ($item.properties.startTime -le $endDateTime )) { $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/triggers/{3}/histories/{4}/resubmit?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName,$item.properties.Trigger.Name,$item.Name Write-Host "Submitting" $uri Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers } } while ($method.nextLink) { $nextLink = $method.nextLink; Write-Host $nextLink $method = (Invoke-RestMethod -Uri $nextLink -Headers $headers -Method Get) $output = $method.value foreach ($item in $output) { if (($item.properties.status -eq $status) -and ([DateTime]$item.properties.startTime -ge $startDateTime) -and ([DateTime]$item.properties.startTime -le $endDateTime)) { $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/triggers/{3}/histories/{4}/resubmit?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName,$item.properties.Trigger.Name,$item.Name Write-Host "Submitting" $uri Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers } } } }
The complete Code
The complete code is below.
function Get-LogicAppHistory { param ( [Parameter(Mandatory = $true)] $Token, [Parameter(Mandatory = $true)] $subscriptionId, [Parameter(Mandatory = $true)] $resourceGroupName, [Parameter(Mandatory = $true)] $logicAppName, [Parameter(Mandatory = $false)] $status, [Parameter(Mandatory = $true)] $startDateTime, [Parameter(Mandatory = $false)] $endDateTime ) $headers = @{ 'Authorization' = 'Bearer ' + $token } $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/runs?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName $method = (Invoke-RestMethod -Uri $uri -Headers $headers -Method Get) $output = $method.value foreach ($item in $output) { if ((($item.properties.status -eq $status) -and ($item.properties.startTime -ge $startDateTime)) -and ($item.properties.startTime -le $endDateTime )) { $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/triggers/{3}/histories/{4}/resubmit?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName,$item.properties.Trigger.Name,$item.Name Write-Host "Submitting" $uri Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers } } while ($method.nextLink) { $nextLink = $method.nextLink; Write-Host $nextLink $method = (Invoke-RestMethod -Uri $nextLink -Headers $headers -Method Get) $output = $method.value foreach ($item in $output) { if (($item.properties.status -eq $status) -and ([DateTime]$item.properties.startTime -ge $startDateTime) -and ([DateTime]$item.properties.startTime -le $endDateTime)) { $uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Logic/workflows/{2}/triggers/{3}/histories/{4}/resubmit?api-version=2016-06-01' -f $subscriptionId,$resourceGroupName,$logicAppName,$item.properties.Trigger.Name,$item.Name Write-Host "Submitting" $uri Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers } } } } function ResubmitFailedLogicApp { param( [Parameter(Mandatory = $true)] [string]$subscriptionName, [Parameter(Mandatory = $true)] [string]$resourceGroupName, [Parameter(Mandatory = $true)] [string]$logicAppName, [Parameter(Mandatory = $true)] [string]$status ) $currentAzureContext = Get-AzureRmContext if (!$currentAzureContext) { Connect-AzureRmAccount $currentAzureContext = Get-AzureRmContext } $startDateTime = Get-Date -Date '2019-10-14' $endDateTime = Get-Date -Date '2019-10-23' $subscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName $context = $subscription | Set-AzureRmContext $tokens = $context.TokenCache.ReadItems() | Where-Object { $_.TenantId -eq $context.Subscription.TenantId } | Sort-Object -Property ExpiresOn -Descending $token = $tokens[0].AccessToken $subscriptionId = $subscription.Id; Write-Host $subscriptionId Get-LogicAppHistory -Token $token -SubscriptionId $subscriptionId -resourceGroupName $resourceGroupName -logicAppName $logicAppName -Status $status -startDateTime $startDateTime -endDateTime $endDateTime } Write-Host "####### Example #######" Write-Host "ResubmitFailedLogicApp -subscriptionName 'New ENT Subscription' -resourceGroupName 'resourceName' -logicAppName 'LogicAppName' -status 'Failed'" Write-Host "####### Example #######" ResubmitFailedLogicApp
- D365 FO introduces New user-based service protection API limits
- D365 FO: Priority based throttling for integrations
- Monitoring and alerting for Azure Key Vault
- D365 FO: Set financial dimension value using oData
- Azure Integration using Managed Identity
- D365 Finance and Operations integration using BYOD