title: Intermittent error messages when running an Azure Functions app
body: <p>I have a Powershell program which runs on a schedule in an Azure Functions app. It connects to Office 365 to download audit logs, make some changes and then export a CSV to an Azure Data Lake Storage account. To avoid hard-coded credentials, an Azure Key Vault stores the secrets. I created a managed identity in the Azure Function along with the required application settings and URL to point to Azure Key Vault. The code references the application secrets (APPSETTING) and all seemed to be running well, until I noticed today that since yesterday afternoon the exported CSV files were empty.</p>
  <p>So I opened up the Function app, hit Run manually and I could see a CSV file exported with data. When I took a look at the execution log however, I spotted these error messages which despite not affecting the execution this time, makes me wonder whether this is what caused the problem with the empty CSV files. The program is now running on a schedule as normal and the error messages appear to be intermittent.</p>
  <p><a href="https://i.stack.imgur.com/L43k8.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/L43k8.png" alt="enter image description here" /></a></p>
  <p>Not sure why it's complaining about the username and password, when it is clearly able to access the data source (Office audit logs), export the CSV and transfer it to the file destination (Azure Data Lake Storage) successfully.</p>
  <p>Any idea what is going on? Any tips or suggestions welcome! Code provided below. Many thanks!</p>
  <pre><code>  # Input bindings are passed in via param block.
      param($Timer)
  
      # Get the current universal time in the default string format.
      $currentUTCtime = (Get-Date).ToUniversalTime()
  
      # The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
      if ($Timer.IsPastDue) {
          Write-Host &quot;PowerShell timer is running late!&quot;
      }
  
      # Write an information log with the current time.
      Write-Host &quot;PowerShell timer trigger function ran! TIME: $currentUTCtime&quot;
  
      &lt;# 
      Title: Power BI Audit Logging 
      Client: 
  
      Description: Connects to Azure audit logs using admin credentials (secrets via Azure Key Vault). Opens a session to iterate through the Audit Log ($currentrResults) and aggregate 
      the logs into a single object ($aggregateResults). A for-each loop then iterates through the $aggregateResults and assigns each data piece (datum)
      to a PowerShell object to which properties are added to hold the audit data. A CSV file is created and exported, and then transferred to a Data Lake storage account (using SAS secret via Azure Key Vault). 
  
      Last Revision: 06/09/2020 #&gt;
  
      Set-ExecutionPolicy RemoteSigned
      Set-Item ENV:\SuppressAzurePowerShellBreakingChangeWarnings &quot;true&quot;
  
      # Better for scheduled jobs
      $uSecret = $ENV:APPSETTING_SecretUsername
      $pSecret = $ENV:APPSETTING_SecretPassword 
      $sasSecret = $ENV:APPSETTING_SecretSAS
  
      $securePassword = ConvertTo-SecureString -String $pSecret -AsPlainText -Force
  
      $UserCredential = New-Object -TypeName &quot;System.Management.Automation.PSCredential&quot; -ArgumentList $uSecret, $securePassword
  
      # This will prompt the user for credential (optional)
      # $UserCredential = Get-Credential
  
      $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
      Import-PSSession $session
  
      $startDate=(get-date).AddDays(-10)
      $endDate=(get-date)
      $scriptStart=(get-date)
  
      $sessionName = (get-date -Format 'u')+'pbiauditlog'
      # Reset user audit accumulator
      $aggregateResults = @()
      $i = 0 # Loop counter
      Do { 
          $currentResults = Search-UnifiedAuditLog -StartDate $startDate -EndDate $enddate -SessionId $sessionName -SessionCommand ReturnLargeSet -ResultSize 1000 -RecordType PowerBIAudit
          if ($currentResults.Count -gt 0) {
              Write-Host (&quot;Finished {3} search #{1}, {2} records: {0} min&quot; -f [math]::Round((New-TimeSpan -Start $scriptStart).TotalMinutes,4), $i, $currentResults.Count, $user.UserPrincipalName )
              # Accumulate the data.
              $aggregateResults += $currentResults
              # No need to do another query if the # records returned &lt;1000 - should save around 5-10 seconds per user.
              if ($currentResults.Count -lt 1000) {
                  $currentResults = @()
              } else {
                  $i++
              }
          }
      } Until ($currentResults.Count -eq 0) # End of Session Search Loop.
  
      $data=@()
  
      foreach ($auditlogitem in $aggregateResults) {
          $datum = New-Object -TypeName PSObject  
          $d = ConvertFrom-json $auditlogitem.AuditData
          $datum | Add-Member -MemberType NoteProperty -Name Id -Value $d.Id
          $datum | Add-Member -MemberType NoteProperty -Name CreationTDateTime -Value $d.CreationDate
          $datum | Add-Member -MemberType NoteProperty -Name CreationTime -Value $d.CreationTime
          $datum | Add-Member -MemberType NoteProperty -Name RecordType -Value $d.RecordType
          $datum | Add-Member -MemberType NoteProperty -Name Operation -Value $d.Operation
          $datum | Add-Member -MemberType NoteProperty -Name OrganizationId -Value $d.OrganizationId
          $datum | Add-Member -MemberType NoteProperty -Name UserType -Value $d.UserType
          $datum | Add-Member -MemberType NoteProperty -Name UserKey -Value $d.UserKey
          $datum | Add-Member -MemberType NoteProperty -Name Workload -Value $d.Workload
          $datum | Add-Member -MemberType NoteProperty -Name UserId -Value $d.UserId
          $datum | Add-Member -MemberType NoteProperty -Name ClientIPAddress -Value $d.ClientIPAddress
          $datum | Add-Member -MemberType NoteProperty -Name UserAgent -Value $d.UserAgent
          $datum | Add-Member -MemberType NoteProperty -Name Activity -Value $d.Activity
          $datum | Add-Member -MemberType NoteProperty -Name ItemName -Value $d.ItemName
          $datum | Add-Member -MemberType NoteProperty -Name WorkSpaceName -Value $d.WorkSpaceName
          $datum | Add-Member -MemberType NoteProperty -Name DashboardName -Value $d.DashboardName
          $datum | Add-Member -MemberType NoteProperty -Name DatasetName -Value $d.DatasetName
          $datum | Add-Member -MemberType NoteProperty -Name ReportName -Value $d.ReportName
          $datum | Add-Member -MemberType NoteProperty -Name WorkspaceId -Value $d.WorkspaceId
          $datum | Add-Member -MemberType NoteProperty -Name ObjectId -Value $d.ObjectId
          $datum | Add-Member -MemberType NoteProperty -Name DashboardId -Value $d.DashboardId
          $datum | Add-Member -MemberType NoteProperty -Name DatasetId -Value $d.DatasetId
          $datum | Add-Member -MemberType NoteProperty -Name ReportId -Value $d.ReportId
          $datum | Add-Member -MemberType NoteProperty -Name OrgAppPermission -Value $d.OrgAppPermission
              
          # Option to include the below JSON column however for large amounts of data it may be difficult for PBI to parse
          $datum | Add-Member -MemberType NoteProperty -Name Datasets -Value (ConvertTo-Json $d.Datasets)
          
          # Below is a simple PowerShell statement to grab one of the entries and place in the DatasetName if any exist
          foreach ($dataset in $d.datasets) {
              $datum.DatasetName = $dataset.DatasetName
              $datum.DatasetId = $dataset.DatasetId
          }
          $data+=$datum
      }
  
      $dateTimestring = $startDate.ToString(&quot;yyyyMMdd&quot;) + &quot;_&quot; + (Get-Date -Format &quot;yyyyMMdd&quot;) + &quot;_&quot; + (Get-Date -Format &quot;HHmm&quot;)
      $fileName = ($dateTimestring + &quot;.csv&quot;)
      Write-Host (&quot;Writing to file {0}&quot; -f $fileName) 
      $filePath = &quot;$Env:temp/&quot; + $fileName
      $data | Export-csv -Path $filePath
  
      # File transfer to Azure storage account 
      Get-AzContext #Connect-AzAccount -Credential $UserCredential
      Get-AzVM -ResourceGroupName &quot;Audit&quot; -status
      $Context = New-AzStorageContext -StorageAccountName &quot;auditingstorage&quot; -StorageAccountKey $sasSecret
      Set-AzStorageBlobContent -Force -Context $Context -Container &quot;auditlogs&quot; -File $filePath -Blob $filename 
  
      # Close PowerShell session
      Remove-PSSession -Id $Session.Id
  </code></pre>