Access the Power BI activity log

This article targets Power BI administrators who need to access the Power BI activity log. Because there's no user interface to search the activity log yet, you'll need to use the Power BI REST API and management cmdlets.

Note

This article doesn't introduce or describe the Power BI activity log. For more information, see Track user activities in Power BI.

PowerShell sample

A PowerShell sample is available to help you learn how to filter and retrieve Power BI activity log events. All code fragments and scenarios are annotated with how-to instructions and common gaps or issues to watch out for. Two scenarios are covered:

  • Retrieve a list of users for specific app.
  • Retrieve a list of users for direct report sharing.

Note

You'll need to have some familiarity with the Power BI Admin API and Power BI PowerShell modules. PowerShell modules must be installed prior to executing these script blocks. For more information, see Track user activities in Power BI.

There can be a lag of up to 30 minutes to retrieve Power BI events.

To use the sample, you must meet the following requirements:

Important

Users without admin privileges won't be able to execute code fragments in the sample script.

# Written by Sergei Gundorov; v1 development started on 07/08/2020
#
# Intent: 1. Address common friction points and usage issues and questions related to the
#            events generated by Power BI Service that are stored in the activity log.
#         2. Provide boiler plate code for capturing all 30 days of available data.
#         3. Power BI admin privileges are required to use the Activity Log API.
#
# Use:    Sign in to the Power BI service with admin privileges and execute specific segment one at a time.

# IMPORTANT: Use Connect-PowerBIServiceAccount to connect to the service before running individual code segments.

# IMPORTANT: $day value may need to be adjusted depending on where you're located in the world relative to UTC.
#            The Power BI activity log records events using UTC time; so add or subtract days according to your global location.

# SCENARIO: Sample code fragment to retrieve a limited number of attributes for specific events for specific user report viewing activity.
# You need to get user's Azure Active Directory (AAD) object ID. You can use this Azure AD cmdlet: https://docs.microsoft.com/powershell/module/azuread/get-azureaduser?view=azureadps-2.0

# Dates need to be entered using ISO 8601 format; adjust dates to span no more than 24 hours.
$a=Get-PowerBIActivityEvent -StartDateTime '2020-06-23T19:00:00.000' -EndDateTime '2020-06-23T20:59:59.999' -ActivityType 'ViewReport' -User [USER AAD ObjectId GUID] | ConvertFrom-Json

# You can use any attribute value to filter results further. For example, a specific event request Id can be used to analyze just one specific event.
$a | Select RequestId, ReportName, WorkspaceName |where {($_.RequestId -eq '[RequestId GUID of the event]')}

# SCENARIO: Retrieve a list of users for specific app.
# The user list can be partially derived (based on last 30 days of available activity) by combining data for two events: CreateApp and UpdateApp.
# Both events will contain OrgAppPermission property that contains app user access list.
# Actual app installation can be tracked using InstallApp activity.
# Run each code segment separately for each event.

# Iterate through 30 days of activity CreateApp.
$day=Get-date

for($s=0; $s -le 30; $s++)
{
    $periodStart=$day.AddDays(-$s)
    $base=$periodStart.ToString("yyyy-MM-dd")

    write-host $base

    $a=Get-PowerBIActivityEvent -StartDateTime ($base+'T00:00:00.000') -EndDateTime ($base+'T23:59:59.999') -ActivityType 'CreateApp' -ResultType JsonString | ConvertFrom-Json
    $c=$a.Count

    for($i=0 ; $i -lt $c; $i++)
    {
        $r=$a[$i]
        Write-Host "App Name `t: $($r.ItemName)"
                 ` "WS Name `t: $($r.WorkSpaceName)"
                 ` "WS ID `t`t: $($r.WorkspaceId)"
                 ` "Created `t: $($r.CreationTime)"
                 ` "Users `t`t: $($r.OrgAppPermission) `n"
    }
}

# Iterate through 30 days of activity UpdateApp.
$day=Get-date

for($s=0; $s -le 30; $s++)
{
    $periodStart=$day.AddDays(-$s)
    $base=$periodStart.ToString("yyyy-MM-dd")

    write-host $base

    $a=Get-PowerBIActivityEvent -StartDateTime ($base+'T00:00:00.000') -EndDateTime ($base+'T23:59:59.999') -ActivityType 'UpdateApp' -ResultType JsonString | ConvertFrom-Json
    $c=$a.Count

    for($i=0 ; $i -lt $c; $i++)
    {
        $r=$a[$i]
        Write-Host "App Name `t: $($r.ItemName)"
                 ` "WS Name `t: $($r.WorkSpaceName)"
                 ` "WS ID `t`t: $($r.WorkspaceId)"
                 ` "Updated `t: $($r.CreationTime)"
                 ` "Users `t`t: $($r.OrgAppPermission) `n"
    }
}

# Iterate through 30 days of activity InstallApp.
$day=Get-date

for($s=0; $s -le 30; $s++)
{
    $periodStart=$day.AddDays(-$s)
    $base=$periodStart.ToString("yyyy-MM-dd")

    write-host $base

    $a=Get-PowerBIActivityEvent -StartDateTime ($base+'T00:00:00.000') -EndDateTime ($base+'T23:59:59.999') -ActivityType 'InstallApp' -ResultType  JsonString | ConvertFrom-Json
    $c=$a.Count

    for($i=0 ; $i -lt $c; $i++)
    {
        $r=$a[$i]
        Write-Host "App Name `t: $($r.ItemName)"
                 ` "Installed `t: $($r.CreationTime)"
                 ` "User `t`t: $($r.UserId) `n"
    }
}

# SCENARIO: Retrieve a list of users for direct report sharing.
# This logic and flow can be used for tracing direct dashboard sharing by substituting activity type.
# Default output is formatted to return the list of users as a string. There is commented out code block to get multi-line user list.
# IMPORTANT: Removal of a user or group from direct sharing access list event is not tracked. For this reason, the list may be not accurate.
# IMPORTANT: If the user list contains a GUID instead of a UPN the report was shared to a group.
#            Group name and email can be obtained using Azure AD cmdlets using captured ObjectId GUID.

# Iterate through 30 days of activity ShareReport.
$day=Get-date

for($s=0; $s -le 30; $s++)
{
    $periodStart=$day.AddDays(-$s)
    $base=$periodStart.ToString("yyyy-MM-dd")

    #write-host $base

    $a=Get-PowerBIActivityEvent -StartDateTime ($base+'T00:00:00.000') -EndDateTime ($base+'T23:59:59.999') -ActivityType 'ShareReport' -ResultType JsonString | ConvertFrom-Json
    $c=$a.Count

    for($i=0 ; $i -lt $c; $i++)
    {
        $r=$a[$i]

        Write-Host "Rpt Name `t: $($r.ItemName)"
                 ` "Rpt Id  `t: $($r.ArtifactId)"
                 ` "WS Name  `t: $($r.WorkSpaceName)"
                 ` "WS ID  `t`t: $($r.WorkspaceId)"
                 ` "Capacity  `t: $($r.CapacityId)"
                 ` "SharedOn  `t: $($r.CreationTime.Replace('T',' ').Replace('Z',''))"
                 ` "User `t`t: $($r.UserId)"
                 #  NOTE:  $_.RecipientEmail + $_.RecipientName or +$_.ObjectId is the case for group sharing
                 #         can never happen both at the same time in the same JSON record
                 ` "Shared with`t: $(($r.SharingInformation)| % {$_.RecipientEmail + $_.ObjectId +'[' + $_.ResharePermission +']'})"


       #OPTIONAL: Formatted output for SharingInformation attribute
       #$sc= $r.SharingInformation.Count
       #Write-Host "Shared with`t:"
       #for($j=0;$j -lt $sc;$j++)
       #{
       #     Write-Host "`t`t`t  $($r.SharingInformation[$j].RecipientEmail)" -NoNewline
       #     Write-Host $r.SharingInformation[$j].ObjectId -NoNewline
       #     Write-Host ('[' + $r.SharingInformation[$j].ResharePermission +']')
       #}

       Write-host ""
    }
}

Next steps

For more information related to this article, check out the following resources: