DownloadErrorScript.ps1
<#PSScriptInfo .VERSION 1.0 .GUID a026e502-a561-4270-85ec-ae66f02897f1 .AUTHOR Microsoft Corporation .COMPANYNAME Microsoft Corporation .COPYRIGHT (c) 2019 Microsoft. All rights reserved. .TAGS Microsoft Graph Search PowerShell .LICENSEURI https://learn.microsoft.com/en-us/legal/mdsa?redirectedfrom=MSDN .PROJECTURI https://learn.microsoft.com/en-us/microsoftsearch/connector-details-errors .ICONURI https://contoso.com/Icon .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> #Requires -Module MSAL.PS <# .Synopsis Script to download item errors for a connection .Description This script downloads the item errors in a Microsoft Graph Connection. An Msal token is generated using the tenant credentials in which the connection is present. That token is then used to first get all the distinct error codes with which the items failed and then for each error code all the item errors are fetched iteratively. Getting item errors for a particular error code is a batched API call with deafulat batch size as 500. .Parameter ConnectionId ConnectionId for which the item errors need to be downloaded. .parameter OutputFile OutputFile in which item errors should get appended #> param( [Parameter(Mandatory=$true)][string]$ConnectionId, [Parameter(Mandatory=$true)][string]$OutputFile ) function InitializeOutputFile { param ( $FileName ) "Time,Path,Error Code,Detailed Error Code,Message" | Set-Content -Path $FileName } function WriteErrorBatchToOutputFile { param ( $ErrorsBatch, $FileName ) Foreach ($Error in $ErrorsBatch.errors) { $OutputLine = Get-Date($Error.timeStamp) -UFormat "%m/%d/%Y %T" $OutputLine = $OutputLine +","+ $Error.displayText +","+ $ErrorsBatch.Code +","+ $Error.detailedCode +',"'+ $ErrorsBatch.message +'"' $OutputLine | Add-Content -Path $FileName } } function Invoke-RestMethodWithRetries { param ( [string]$ApiName, [string]$Uri, [hashtable]$Headers, [string]$Method, [int]$MaxRetries = 3 ) $retryCount = 0 do { try { Write-Host "Request made for $ApiName." return Invoke-WebRequest -Uri $Uri -Headers $Headers -Method $Method } catch { $retryCount++ Write-Warning "Request failed for $ApiName. Retrying (Attempt $retryCount)..." Start-Sleep -Seconds (2 * $retryCount) # Increase the wait time with each retry } } while ($retryCount -lt $MaxRetries) throw "Request failed for $ApiName. All the retries are exhausted" } function Get-TokenWithRetries { param ( [string]$ClientId, [string]$Authority, [string]$RedirectUri, [string]$Scopes, [bool]$IsRefresh = $false, [int]$MaxRetries = 3 ) $retryCount = 0 do { try { if($IsRefresh) { Write-Host "Requesting for Msal Refresh Access token." return Get-MsalToken -ClientId $ClientId -Authority $Authority -RedirectUri $RedirectUri -Scopes $Scopes -ForceRefresh } else { Write-Host "Requesting for Msal Access token." return Get-MsalToken -ClientId $ClientId -Authority $Authority -RedirectUri $RedirectUri -Scopes $Scopes } } catch { $retryCount++ Write-Warning "Request failed for Generating Msal Token. Retrying (Attempt $retryCount)..." Start-Sleep -Seconds (2 * $retryCount) # Increase the wait time with each retry } } while ($retryCount -lt $MaxRetries) throw "Request failed for Generating Msal Token. All the retries are exhausted" } try { # Install MSAL.ps using "Install-Module -Name MSAL.PS" InitializeOutputFile -FileName $OutputFile $clientId = "d3590ed6-52b3-4102-aeff-aad2292ab01c" $authority = "https://login.microsoftonline.com/common" $redirectUri = "yammer://wefwef" $scopes = 'https://gcs.office.com/.default' $token = Get-TokenWithRetries -ClientId $clientId -Authority $authority -RedirectUri $redirectUri -Scopes $scopes $headers = @{"authorization"="Bearer $($token.AccessToken)"; "Content-Type"="application/json"; "Accept" = "application/json;odata=fullmetadata"} # Get the list of Error Codes $ErrorCodesResponse = Invoke-RestMethodWithRetries -ApiName "GetAggregatedErrors" -Uri "https://gcs.office.com/v1.0/admin/datasets/$ConnectionId/errors" -Headers $headers -Method Get | ConvertFrom-Json # Get all the error items for each error code Foreach($ErrorCode in $ErrorCodesResponse.errorCodes) { $CurrentErrorCode = $ErrorCode.code $CurrentOffset = "0" while($CurrentOffset -ne "-1") { Write-Host "Curent Offset: $CurrentOffset" # Refresh the token if it has expired $currentTime = Get-Date $tokenExpiry = $token.ExpiresOn Write-Host "CurrentTime: $currentTime, TokenExpiresOn: $tokenExpiry" # Refresh the token if it's about to expire in the next 5 seconds if ($tokenExpiry -lt ($currentTime.AddSeconds(5))) { Write-Host "Access token is about to expire. Refreshing..." $token = Get-TokenWithRetries -ClientId $clientId -Authority $authority -RedirectUri $redirectUri -Scopes $scopes -IsRefresh $true } $ItemErrorsBatchResponse = Invoke-RestMethodWithRetries -ApiName "GetErrorsByErrorCode" -Uri "https://gcs.office.com/v1.0/admin/datasets/$ConnectionId/errors/${CurrentErrorCode}?offset=$CurrentOffset&limit=2000" -Headers $headers -Method Get | ConvertFrom-Json WriteErrorBatchToOutputFile -ErrorsBatch $ItemErrorsBatchResponse -FileName $OutputFile $CurrentOffset = $ItemErrorsBatchResponse.metaData.nextOffset } } } catch { Write-Error "Error in running GetErrorItems.ps1 Error message: $_"; } |