Power BI アクティビティ ログへのアクセス

この記事は、Power BI アクティビティ ログから供給されるデータにアクセスして分析する必要がある Power BI 管理者を対象としています。 Power BI Management モジュールから Get-PowerBIActivityEvent コマンドレットを使って、Power BI アクティビティをプログラムで取得することに重点を置いています。 最大 30 日分の履歴を利用できます。 このコマンドレットでは、管理 API である Get Activity Events Power BI REST API 操作を使用します。 PowerShell コマンドレットにより、基になる API の上に抽象化のレイヤーが追加されます。 そのため、PowerShell コマンドレットを使うと Power BI アクティビティ ログへのアクセスを簡素化できます。

Power BI アクティビティを取得するには、他にも手動の方法やプログラムによる方法があります。 詳しくは、「ユーザー アクティビティ データにアクセスする」を参照してください。

Power BI アクティビティ ログの分析は、ガバナンス、コンプライアンス、導入作業の追跡にとって不可欠です。 Power BI アクティビティ ログについて詳しくは、「Power BI でユーザー アクティビティを追跡する」を参照してください。

ヒント

テナントレベルの監査に関する記事全体を確認することをお勧めします。 この記事では、エンドツーエンドの監査ソリューションを構築する際に考慮すべき計画、主要な決定事項、前提条件、主要なソリューション開発アクティビティについて説明しています。

利用できる例

この記事の目的は、作業の開始に役立つ例を提供することです。 これらの例には、Power BI Management PowerShell モジュールを使ってアクティビティ ログからデータを取得するスクリプトが含まれています。

警告

これらのスクリプトは教育用の使用のみを意図したものであるため、運用には適していません。 ただし、このスクリプトにログ、エラー処理、アラート、コードの再利用とモジュール化のためのリファクタリングのロジックを追加すれば、運用目的のために適合させることができます。

これらの例は学習用のものであるため、簡略化されていますが、実際の例です。 すべての例を確認し、わずかに異なる手法がどのように適用されているかを理解することをお勧めします。 必要なアクティビティ データの種類を特定したら、それらの手法を組み合わせて、ご自分の要件に最も適したスクリプトを作成できます。

この記事には、次の例が含まれています。

名前の例 アクティビティ データの種類
Power BI サービスで認証する N/A
ユーザーの 1 日のアクティビティをすべて表示する すべて
N 日間のアクティビティを表示する レポートの共有 (リンクまたは直接アクセス)
N 日間の 3 つのアクティビティを表示する アプリの作成、アプリの更新、アプリのインストール
ワークスペースの 1 日のアクティビティをすべて表示する すべて
過去 N 日間のすべてのアクティビティをエクスポートする すべて

わかりやすくするために、ほとんどの例では結果が画面に出力されます。 たとえば、Visual Studio Code では、データはターミナル パネルに出力されます。そこではデータのバッファー セットがメモリに保持されます。

ほとんどの例では、生の JSON データを取得します。 生の JSON データを扱うことには、多くの利点があります。

  • 各アクティビティ イベントについて取得可能なすべての情報が返されます。 これは、どのデータを取得できるか学習するのに役立ちます。 API 応答の内容は、実際のアクティビティ イベントによって異なる点に注意してください。 たとえば、CreateApp イベントについて取得できるデータは、ViewReport イベントとは異なります。
  • アクティビティ ログで利用できるデータは、Power BI が時間と共に進化するにつれて変化するため、API の応答も変化すると想定できます。 それによって、導入された新しいデータを見逃さずに済みます。 また、お客様のプロセスは変化に対する回復性が高くなり、失敗する可能性が低くなります。
  • API 応答の詳細は、Power BI の商用クラウドと国/地域内クラウドで異なる場合があります。
  • このプロセスに関与する異なるチームのメンバー (データ エンジニアなど) がいる場合は、データを抽出する最初のプロセスを簡素化すると、複数のチームが共同作業しやすくなります。

ヒント

データを抽出するスクリプトは、できるだけシンプルにしておくことをお勧めします。 そのため、アクティビティ ログのデータを抽出する際に解析、フィルター処理、書式設定を行わないようにしてください。 このアプローチでは、データの抽出、読み込み、変換の手順を分離させる、ELT の方法を使います。 この記事では、データの抽出に関する最初の手順のみに焦点を当てています。

必要条件

スクリプトの例を使用するには、次の要件を満たす必要があります。

  • PowerShell クライアント ツール: PowerShell コマンドを実行するために好みのツールを使用します。 例はすべて、PowerShell 7 で Visual Studio Code 用 PowerShell 拡張機能を使ってテストされています。 クライアント ツールと PowerShell バージョンについて詳しくは、テナントレベルの監査に関する記事を参照してください。
  • Power BI Management モジュール: すべての Power BI PowerShell モジュールをインストールします。 以前にインストールしている場合は、モジュールを更新して、確実に最新の公開バージョンを使うようにすることをお勧めします。
  • Fabric 管理者ロール: スクリプトの例は、対話型認証フローを使用するように設計されています。 そのため、PowerShell サンプル スクリプトを実行するユーザーは、Power BI REST API を使うためにサインインする必要があります。 アクティビティ ログのデータを取得するには、認証するユーザーが Power BI 管理者ロールに属している必要があります (アクティビティ イベントの取得は管理者 API を使って行われるため)。 サービス プリンシパル認証は、これらの学習例の範囲外です。

この記事の残りの部分には、アクティビティ ログのデータを取得するさまざまな方法を示すサンプル スクリプトが含まれています。

例 1: Power BI サービスで認証する

すべての Power BI REST API 操作では、サインインする必要があります。 "認証" (誰が要求しているか) と "認可" (ユーザーは何をするためのアクセス許可を持っているか) は、Microsoft ID プラットフォームによって管理されます。 次の例では、Power BI Management モジュールConnect-PowerBIServiceAccount コマンドレットを使います。 このコマンドレットでは、サインインするためのシンプルな方法がサポートされています。

要求のサンプル 1

最初のスクリプトでは、サインイン プロセスを完了するためにユーザーをブラウザーにリダイレクトします。 多要素認証 (MFA) が有効になっているユーザー アカウントは、この対話型認証フローを使ってサインインできます。

Connect-PowerBIServiceAccount

重要

Power BI 管理者特権を持たないユーザーは、この記事のこれ以降のサンプル スクリプトを実行できません。 Power BI 管理者は、Power BI サービスを管理したり、テナント全体のメタデータ (アクティビティ ログのデータなど) を取得したりするためのアクセス許可を持ちます。 これらの例ではサービス プリンシパル認証の使用は範囲外ですが、スケジュールに従って実行される運用対応の無人スクリプトの場合は、サービス プリンシパルを設定することを強くお勧めします。

以下のいずれかのスクリプトを実行する前には、必ずサインインしてください。

例 2: ユーザーの 1 日のアクティビティをすべて表示する

特定のユーザーが特定の 1 日に実行したすべてのアクティビティをチェックする必要がある場合があります。

ヒント

PowerShell コマンドレットを使ってアクティビティ ログからデータを抽出する場合、各要求では 1 日分 (最大 24 時間) のデータを抽出できます。 したがって、この例の目的は、まずは単純に 1 人のユーザーの 1 日をチェックすることです。 この記事では後ほど、ループを使って複数の日のデータをエクスポートする方法を示す他の例を紹介します。

要求のサンプル 2

このスクリプトでは、スクリプトを再利用しやすくするために、次の 2 つの PowerShell 変数を宣言します。

  • $UserEmailAddr: 関心のあるユーザーのメール アドレス。
  • $ActivityDate: 関心のある日付。 YYYY-MM-DD という形式です (ISO 8601 形式)。 現在の日付から 30 日以上前の日付を要求することはできません。
#Input values before running the script:
$UserEmailAddr = 'jordan@contoso.com'
$ActivityDate = '2023-03-15'
#----------------------------------------------------------------------
#View activity events:
Get-PowerBIActivityEvent `
    -StartDateTime ($ActivityDate + 'T00:00:00.000') `
    -EndDateTime ($ActivityDate + 'T23:59:59.999') `
    -User $UserEmailAddr

注意

お気付きかもしれませんが、この PowerShell スクリプトの一部の行の末尾にはバックティック (`) 文字があります。 PowerShell でバックティック文字を使う方法の 1 つは、行連結文字として使うことです。 この記事ではこれを使って、スクリプトを読みやすくしています。

ヒント

このスクリプトでは、各 PowerShell 変数が、Get-PowerBIActivityEvent コマンドレットの必須または省略可能なパラメーター値に関連付けられています。 たとえば、$UserEmailAddr 変数に代入する値は -User パラメーターに渡されます。 このように PowerShell 変数を宣言することは、変更される可能性のある値をスクリプトにハードコーディングするのを回避するための簡単なアプローチです。 この習慣を取り入れることをお勧めします。スクリプトがより複雑になるにつれて役に立ちます。 PowerShell パラメーターは変数よりも堅牢ですが、この記事では範囲外です。

応答のサンプル 2

JSON 応答のサンプルを次に示します。 これには、ユーザーが実行した 2 つのアクティビティが含まれています。

  • 1 つ目のアクティビティは、ユーザーがレポートを表示したことを示しています。
  • 2 つ目のアクティビティは、管理者が Power BI アクティビティ ログからデータをエクスポートしたことを示しています。
[
  {
    "Id": "10af656b-b5a2-444c-bf67-509699896daf",
    "RecordType": 20,
    "CreationTime": "2023-03-15T15:18:30Z",
    "Operation": "ViewReport",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "100FFF92C7717B",
    "Workload": "PowerBI",
    "UserId": "jordan@contoso.com",
    "ClientIP": "192.168.1.1",
    "Activity": "ViewReport",
    "ItemName": "Gross Margin Analysis",
    "WorkSpaceName": "Sales Analytics",
    "DatasetName": "Sales Data",
    "ReportName": "Gross Margin Analysis",
    "WorkspaceId": "e380d1d0-1fa6-460b-9a90-1a5c6b02414c",
    "ObjectId": "Gross Margin Analysis",
    "DatasetId": "cfafbeb1-8037-4d0c-896e-a46fb27ff229",
    "ReportId": "94e57e92-Cee2-486d-8cc8-218c97200579",
    "ArtifactId": "94e57e92-Cee2-486d-8cc8-218c97200579",
    "ArtifactName": "Gross Margin Analysis",
    "IsSuccess": true,
    "ReportType": "PowerBIReport",
    "RequestId": "53451b83-932b-f0b0-5328-197133f46fa4",
    "ActivityId": "beb41a5d-45d4-99ee-0e1c-b99c451e9953",
    "DistributionMethod": "Workspace",
    "ConsumptionMethod": "Power BI Web",
    "SensitivityLabelId": "e3dd4e72-5a5d-4a95-b8b0-a0b52b827793",
    "ArtifactKind": "Report"
  },
  {
    "Id": "5c913f29-502b-4a1a-a089-232edaf176f7",
    "RecordType": 20,
    "CreationTime": "2023-03-15T17:22:00Z",
    "Operation": "ExportActivityEvents",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 2,
    "UserKey": "100FFF92C7717B",
    "Workload": "PowerBI",
    "UserId": "jordan@contoso.com",
    "ClientIP": "192.168.1.1",
    "UserAgent": "MicrosoftPowerBIMgmt/1.2.1111.0",
    "Activity": "ExportActivityEvents",
    "IsSuccess": true,
    "RequestId": "2af6a22d-6f24-4dc4-a26a-5c234ab3afad",
    "ActivityId": "00000000-0000-0000-0000-000000000000",
    "ExportEventStartDateTimeParameter": "2023-03-17T00:00:00Z",
    "ExportEventEndDateTimeParameter": "2023-03-17T23:59:59.999Z"
  }
]

ヒント

上記の応答が示すように、Power BI アクティビティ ログ データの抽出もログされる操作です。 ユーザー アクティビティを分析する場合は、管理者のアクティビティを省略するか、個別に分析することをお勧めします。

例 3: N 日間のアクティビティを表示する

1 つの特定の種類のアクティビティを数日間にわたって調査したい場合があります。 この例では、項目ごとのレポート共有アクティビティを取得する方法を示します。 ループを使って、過去 7 日間のアクティビティを取得します。

要求のサンプル 3

このスクリプトでは、次の 2 つの変数を宣言します。

  • $ActivityType: 調査するアクティビティの操作名
  • $NbrOfDaysToCheck: 確認したい日数。 現在の日付からさかのぼって処理するループを実行します。 使用できる最大値は 30 日です (取得できる最も前の日付は現在の日付の 30 日前であるため)。
#Input values before running the script:
$ActivityType = 'ShareReport' 
$NbrOfDaysToCheck = 7 
#-----------------------------------------------------------------------

#Use today to start counting back the number of days to check:
$DayUTC = (([datetime]::Today.ToUniversalTime()).Date)

#Iteratively loop through each of the last N days to view events:
For($LoopNbr=0; $LoopNbr -le $NbrOfDaysToCheck; $LoopNbr++)
{
    $PeriodStart=$DayUTC.AddDays(-$LoopNbr)
    $ActivityDate=$PeriodStart.ToString("yyyy-MM-dd")
    Write-Verbose "Checking $ActivityDate" -Verbose 

    #Check activity events once per loop (once per day):
    Get-PowerBIActivityEvent `
        -StartDateTime ($ActivityDate + 'T00:00:00.000') `
        -EndDateTime ($ActivityDate + 'T23:59:59.999') `
        -ActivityType $ActivityType 
}

ヒント

このループ手法を使って、アクティビティ ログに記録されている任意の操作をチェックできます。

応答のサンプル 3

JSON 応答のサンプルを次に示します。 これには、ユーザーが実行した 2 つのアクティビティが含まれています。

  • 1 つ目のアクティビティは、ユーザーの共有リンクが作成されたことを示しています。 SharingAction の値は、ユーザーがリンクを作成したか、リンクを編集したか、またはリンクを削除したかによって異なることに注意してください。 簡潔にするために、この応答には 1 種類の共有リンク アクティビティのみが表示されています。
  • 2 つ目のアクティビティは、グループの直接アクセス共有が作成されたことを示しています。 SharingInformation の値は、実行されたアクションによって異なることに注意してください。 簡潔にするために、この応答には 1 種類の直接アクセス共有アクティビティのみが表示されています。
[
  {
    "Id": "be7506e1-2bde-4a4a-a210-bc9b156142c0",
    "RecordType": 20,
    "CreationTime": "2023-03-15T19:52:42Z",
    "Operation": "ShareReport",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "900GGG12D2242A",
    "Workload": "PowerBI",
    "UserId": "morgan@contoso.com",
    "ClientIP": "192.168.1.1",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0",
    "Activity": "ShareReport",
    "ItemName": "Call Center Stats",
    "WorkSpaceName": "Sales Analytics",
    "SharingInformation": [
      {
        "RecipientEmail": "ellis@contoso.com",
        "RecipientName": "Turner",
        "ObjectId": "fc9bbc6c-e39b-44cb-9c8a-d37d5665ec57",
        "ResharePermission": "ReadReshare",
        "UserPrincipalName": "ellis@contoso.com"
      }
    ],
    "WorkspaceId": "e380d1d0-1fa6-460b-9a90-1a5c6b02414c",
    "ObjectId": "Call Center Stats",
    "Datasets": [
      {
        "DatasetId": "fgagrwa3-9044-3e1e-228f-k24bf72gg995",
        "DatasetName": "Call Center Data"
      }
    ],
    "ArtifactId": "81g22w11-vyy3-281h-1mn3-822a99921541",
    "ArtifactName": "Call Center Stats",
    "IsSuccess": true,
    "RequestId": "7d55cdd3-ca3d-a911-5e2e-465ac84f7aa7",
    "ActivityId": "4b8b53f1-b1f1-4e08-acdf-65f7d3c1f240",
    "SharingAction": "CreateShareLink",
    "ShareLinkId": "J_5UZg-36m",
    "ArtifactKind": "Report",
    "SharingScope": "Specific People"
  },
  {
    "Id": "b4d567ac-7ec7-40e4-a048-25c98d9bc304",
    "RecordType": 20,
    "CreationTime": "2023-03-15T11:57:26Z",
    "Operation": "ShareReport",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "900GGG12D2242A",
    "Workload": "PowerBI",
    "UserId": "morgan@contoso.com",
    "ClientIP": "69.132.26.0",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0",
    "Activity": "ShareReport",
    "ItemName": "Gross Margin Analysis",
    "WorkSpaceName": "Sales Analytics",
    "SharingInformation": [
      {
        "RecipientName": "SalesAndMarketingGroup-NorthAmerica",
        "ObjectId": "ba21f28b-6226-4296-d341-f059257a06a7",
        "ResharePermission": "Read"
      }
    ],
    "CapacityId": "1DB44EEW-6505-4A45-B215-101HBDAE6A3F",
    "CapacityName": "Shared On Premium - Reserved",
    "WorkspaceId": "e380d1d0-1fa6-460b-9a90-1a5c6b02414c",
    "ObjectId": "Gross Margin Analysis",
    "Datasets": [
      {
        "DatasetId": "cfafbeb1-8037-4d0c-896e-a46fb27ff229",
        "DatasetName": "Sales Data"
      }
    ],
    "ArtifactId": "94e57e92-Cee2-486d-8cc8-218c97200579",
    "ArtifactName": "Gross Margin Analysis",
    "IsSuccess": true,
    "RequestId": "82219e60-6af0-0fa9-8599-c77ed44fff9c",
    "ActivityId": "1d21535a-257e-47b2-b9b2-4f875b19855e",
    "SensitivityLabelId": "16c065f5-ba91-425e-8693-261e40ccdbef",
    "SharingAction": "Direct",
    "ArtifactKind": "Report",
    "SharingScope": "Specific People"
  }
]

注意

この JSON 応答は、イベントの種類によってデータ構造が異なることを示しています。 同じ種類のイベントであっても、特性に違いがあり、若干異なる出力が生成されることがあります。 この記事で前述したように、生データの取得に慣れることをお勧めします。

例 4: N 日間の 3 つのアクティビティを表示する

場合によっては、いくつかの関連するアクティビティを調査する必要があります。 この例では、過去 7 日間にわたって特定の 3 つのアクティビティを取得する方法を示します。 アプリの作成、アプリの更新、アプリのインストールなど、Power BI アプリに関連するアクティビティに焦点を当てています。

要求のサンプル 4

このスクリプトでは、次の変数を宣言します。

  • $NbrOfDaysToCheck: 確認したい日数。 現在の日付からさかのぼって処理するループを実行します。 使用できる最大値は 30 日です (取得できる最も前の日付は現在の日付の 30 日前であるため)。
  • $Activity1: 調査する 1 つ目のアクティビティの操作名。 この例では、Power BI アプリの作成アクティビティを検索します。
  • $Activity2: 2 つ目の操作名。 この例では、Power BI アプリの更新アクティビティを検索します。
  • $Activity3: 3 つ目の操作名。 この例では、Power BI アプリのインストール アクティビティを検索します。

一度に取得できるのは、1 つのアクティビティのアクティビティ イベントだけです。 そのため、スクリプトでは各操作を個別に検索します。 各検索結果を $FullResults という名前の変数にまとめて、画面に出力します。

注意事項

多くのループを何度も実行すると、API "スロットリング" の可能性が大幅に上がります。 スロットリングは、特定の期間内で許可されている要求の数を超えた場合に発生する可能性があります。 Get Activity Events 操作は、1 時間あたり 200 件の要求に制限されています。 スクリプトを設計するときは、元のデータを必要な回数以上取得しないように注意してください。 一般に、1 日に 1 回すべての生データを抽出してから、そのデータを個別にクエリ、変換、フィルター処理、または書式設定することをお勧めします。

このスクリプトでは、現在の日付の結果が表示されます。

注意

前日の結果のみを取得する (半端な日の結果を回避する) 場合は、「過去 N 日間のすべてのアクティビティをエクスポートする」の例を参照してください。)

#Input values before running the script:
$NbrOfDaysToCheck = 7
$Activity1 = 'CreateApp'
$Activity2 = 'UpdateApp'
$Activity3 = 'InstallApp'
#-----------------------------------------------------------------------
#Initialize array which will contain the full resultset:
$FullResults = @() 

#Use today to start counting back the number of days to check:
$DayUTC = (([datetime]::Today.ToUniversalTime()).Date)

#Iteratively loop through each day (<Initilize> ; <Condition> ; <Repeat>)
#Append each type of activity to an array:
For($LoopNbr=0; $LoopNbr -le $NbrOfDaysToCheck; $LoopNbr++)
{
    $PeriodStart=$DayUTC.AddDays(-$LoopNbr)
    $ActivityDate=$PeriodStart.ToString("yyyy-MM-dd")
    Write-Verbose "Checking $ActivityDate" -Verbose 

    #Get activity 1 and append its results into the full resultset:
    $Activity1Results = @()
    $Activity1Results += Get-PowerBIActivityEvent `
        -StartDateTime ($ActivityDate+'T00:00:00.000') `
        -EndDateTime ($ActivityDate+'T23:59:59.999') `
        -ActivityType $Activity1 | ConvertFrom-Json
    If ($null -ne $Activity1Results) {$FullResults += $Activity1Results}
    
    #Get activity 2 and append its results into the full resultset:
    $Activity2Results = @()
    $Activity2Results += Get-PowerBIActivityEvent `
        -StartDateTime ($ActivityDate+'T00:00:00.000') `
        -EndDateTime ($ActivityDate+'T23:59:59.999') `
        -ActivityType $Activity2 | 
    ConvertFrom-Json
    If ($null -ne $Activity2Results) {$FullResults += $Activity2Results}  

    #Get activity 3 and append its results into the full resultset:
    $Activity3Results = @()
    $Activity3Results += Get-PowerBIActivityEvent `
        -StartDateTime ($ActivityDate+'T00:00:00.000') `
        -EndDateTime ($ActivityDate+'T23:59:59.999') `
        -ActivityType $Activity3 | 
    ConvertFrom-Json
    If ($null -ne $Activity3Results) {$FullResults += $Activity3Results}
    
}  
#Convert all of the results back to a well-formed JSON object:
$FullResults = $FullResults | ConvertTo-Json

#Display results on the screen:
$FullResults

応答のサンプル 4

JSON 応答のサンプルを次に示します。 これには、ユーザーが実行した 3 つのアクティビティが含まれています。

  • 1 つ目のアクティビティは、Power BI アプリが作成されたことを示しています。
  • 2 つ目のアクティビティは、Power BI アプリが更新されたことを示しています。
  • 3 つ目のアクティビティは、Power BI アプリがユーザーによってインストールされたことを示しています。

警告

応答には、変更されたユーザーのアクセス許可のみが含まれています。 たとえば、CreateApp イベントで 3 人の対象ユーザーが作成された可能性があります。 UpdateApp イベントでは、1 人の対象ユーザーのみが変更された場合、OrgAppPermission のデータには 1 人の対象ユーザーのみが表示されます。 そのため、UpdateApp イベントに依存してすべてのアプリのアクセス許可を追跡することは不完全です。アクティビティ ログには変更された内容のみが表示されるためです。

すべての Power BI アプリのアクセス許可のスナップショット用には、代わりに Get App Users as Admin API 操作を使います。

[
  {
    "Id": "65a26480-981a-4905-b3aa-cbb3df11c7c2",
    "RecordType": 20,
    "CreationTime": "2023-03-15T18:42:13Z",
    "Operation": "CreateApp",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "100FFF92C7717B",
    "Workload": "PowerBI",
    "UserId": "jordan@contoso.com",
    "ClientIP": "192.168.1.1",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0",
    "Activity": "CreateApp",
    "ItemName": "Sales Reconciliations App",
    "WorkSpaceName": "Sales Reconciliations",
    "OrgAppPermission": {
      "recipients": "Sales Reconciliations App(Entire Organization)",
      "permissions": "Sales Reconciliations App(Read,CopyOnWrite)"
    },
    "WorkspaceId": "9325a31d-067e-4748-a592-626d832c8001",
    "ObjectId": "Sales Reconciliations App",
    "IsSuccess": true,
    "RequestId": "ab97a4f1-9f5e-4a6f-5d50-92c837635814",
    "ActivityId": "9bb54a9d-b688-4028-958e-4d7d21ca903a",
    "AppId": "42d60f97-0f69-470c-815f-60198956a7e2"
  },
  {
    "Id": "a1dc6d26-b006-4727-bac6-69c765b7978f",
    "RecordType": 20,
    "CreationTime": "2023-03-16T18:39:58Z",
    "Operation": "UpdateApp",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "100GGG12F9921B",
    "Workload": "PowerBI",
    "UserId": "morgan@contoso.com",
    "ClientIP": "192.168.1.1",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0",
    "Activity": "UpdateApp",
    "ItemName": "Sales Analytics",
    "WorkSpaceName": "Sales Analytics",
    "OrgAppPermission": {
      "recipients": "Sales Reps Audience(SalesAndMarketingGroup-NorthAmerica,SalesAndMarketingGroup-Europe)",
      "permissions": "Sales Reps Audience(Read,CopyOnWrite)"
    },
    "WorkspaceId": "c7bffcd8-8156-466a-a88f-0785de2c8b13",
    "ObjectId": "Sales Analytics",
    "IsSuccess": true,
    "RequestId": "e886d122-2c09-4189-e12a-ef998268b864",
    "ActivityId": "9bb54a9d-b688-4028-958e-4d7d21ca903a",
    "AppId": "c03530c0-db34-4b66-97c7-34dd2bd590af"
  },
  {
    "Id": "aa002302-313d-4786-900e-e68a6064df1a",
    "RecordType": 20,
    "CreationTime": "2023-03-17T18:35:22Z",
    "Operation": "InstallApp",
    "OrganizationId": "927c6607-8060-4f4a-a5f8-34964ac78d70",
    "UserType": 0,
    "UserKey": "100HHH12F4412A",
    "Workload": "PowerBI",
    "UserId": "ellis@contoso.com",
    "ClientIP": "192.168.1.1",
    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0",
    "Activity": "InstallApp",
    "ItemName": "Sales Reconciliations App",
    "ObjectId": "Sales Reconciliations App",
    "IsSuccess": true,
    "RequestId": "7b3cc968-883f-7e13-081d-88b13f6cfbd8",
    "ActivityId": "9bb54a9d-b688-4028-958e-4d7d21ca903a"
  }
]

例 5: ワークスペースの 1 日のアクティビティをすべて表示する

特定のワークスペースに関連するアクティビティを調査したい場合があります。 この例では、1 日分のすべてのユーザーのすべてのアクティビティを取得します。 次に、その結果をフィルター処理して、1 つのワークスペースのアクティビティの分析に集中できるようにします。

要求のサンプル 5

このスクリプトでは、次の 2 つの変数を宣言します。

  • $ActivityDate: 関心のある日付。 YYYY-MM-DD という形式です。 現在の日付から 30 日以上前の日付を要求することはできません。
  • $WorkspaceName: 関心のあるワークスペースの名前。

このスクリプトでは結果を $Results 変数に格納します。 次に、JSON データをオブジェクトに変換して、結果を解析できるようにします。 次に、その結果をフィルター処理して、5 つの特定の列を取得します。 CreationTime のデータは ActivityDateTime という名前に変更されます。 その結果をワークスペース名でフィルター処理して、画面に出力します。

Get-PowerBIActivityEvent コマンドレットには、アクティビティ ログを確認するときにワークスペースを指定できるパラメーターはありません (この記事の前の例では、PowerShell パラメーターを使って特定のユーザー、日付、またはアクティビティ名を設定しました)。 この例では、スクリプトですべてのデータを取得した後、JSON 応答を解析して、特定のワークスペースに結果をフィルター処理します。

注意事項

1 日に数百または数千のアクティビティがある大規模な組織の場合は、結果を取得してからフィルター処理すると非常に効率が悪いことがあります。 Get Activity Events 操作は、1 時間あたり 200 件の要求に制限されていることに注意してください。

(特定の期間内で許可されている要求数を超えた場合の) API のスロットリングを回避するために、必要以上に元のデータを取得しないでください。 スクリプトを実行してもう一度結果を取得することなく、フィルター処理された結果を使って作業を継続できます。 継続的に必要な場合は、1 日に 1 回すべてのデータを抽出し、それに対して何度もクエリを実行することをお勧めします。

#Input values before running the script:
$ActivityDate = '2023-03-22'
$WorkspaceName = 'Sales Analytics'
#----------------------------------------------------------------------
#Run cmdlet to check activity events and store intermediate results:
$Events = Get-PowerBIActivityEvent `
    -StartDateTime ($ActivityDate+'T00:00:00.000') `
    -EndDateTime ($ActivityDate+'T23:59:59.999')
    
#Convert from JSON so we can parse the data:
$ConvertedResults = $Events | ConvertFrom-Json

#Obtain specific attributes and save to a PowerShell object:
$FilteredResults = $ConvertedResults `
    | 
    Select-Object `
    @{Name="ActivityDateTime";Expression={$PSItem.CreationTime}}, ` #alias name
    Activity, `
    UserId, `
    ArtifactName, `
    WorkspaceName `
    | 
    #Filter the results:
    Where-Object {($PSItem.WorkspaceName -eq $WorkspaceName)}

#View the filtered results:
$FilteredResults 

#Optional - Save back to JSON format:
#$FilteredResults = $FilteredResults | ConvertTo-Json -Depth 10
#$FilteredResults

応答のサンプル 5

プロパティの小さなサブセットを含む、フィルター処理された結果を次に示します。 一時的な分析のために、読みやすい形式になっています。 ただし、結果を保存する予定の場合は、JSON 形式に変換し直すことをお勧めします。

注意

JSON の結果を PowerShell オブジェクトに変換すると、時刻の値はローカル時刻に変換されます。 元の監査データは常に協定世界時 (UTC) の時刻で記録されるため、UTC 時刻のみを使うように慣れることをお勧めします。

ActivityDateTime : 4/25/2023 3:18:30 PM
Activity         : ViewReport
UserId           : jordan@contoso.com
ArtifactName     : Gross Margin Analysis
WorkSpaceName    : Sales Analytics

CreationTime     : 4/25/2023 5:32:10 PM
Activity         : ShareReport
UserId           : ellis@contoso.com
ArtifactName     : Call Center Stats
WorkSpaceName    : Sales Analytics

CreationTime     : 4/25/2023 9:03:05 PM
Activity         : ViewReport
UserId           : morgan@contoso.com
ArtifactName     : Call Center Stats
WorkSpaceName    : Sales Analytics

ヒント

この手法を使うと、結果内の任意のプロパティで結果をフィルター処理できます。 たとえば、特定のイベント RequestId を使って、1 つの特定のイベントだけを分析できます。

例 6: 過去 N 日間のすべてのアクティビティをエクスポートする

すべてのアクティビティ データをファイルにエクスポートして、PowerShell の外部でそのデータを操作できるようにしたい場合があります。 この例では、最大 30 日分のすべてのユーザーのすべてのアクティビティを取得します。 1 日あたり 1 つの JSON ファイルにデータをエクスポートします。

重要

アクティビティ ログのデータは、最大 30 日間使用できます。 履歴の分析を実行できるように、データをエクスポートして保持しておくことが重要です。 現在アクティビティ ログのデータをエクスポートして格納していない場合は、優先的にそうすることを強くお勧めします。

要求のサンプル 6

スクリプトでは、数日間のすべてのアクティビティを取得します。 次の 3 つの変数を宣言します。

  • $NbrDaysDaysToExtract: エクスポートしたい日数。 前日の日付からさかのぼって処理するループを実行します。 使用できる最大値は 30 日です (取得できる最も前の日付は現在の日付の 30 日前であるため)。
  • $ExportFileLocation: ファイルを保存するフォルダー パス。 フォルダーは、スクリプトを実行する前に存在している必要があります。 フォルダー パスの末尾にバックスラッシュ (\) を含めないでください (実行時に自動的に追加されるため)。 生データ ファイルを格納するには、個別のフォルダーを使うことをお勧めします。
  • $ExportFileName: 各ファイル名のプレフィックス。 1 日に 1 つのファイルが保存されるため、スクリプトによって、ファイルに含まれるデータと、データが取得された日時を示すサフィックスが追加されます。 たとえば、2023 年 4 月 25 日の午前 9 時 (UTC) にスクリプトを実行して、2023 年 4 月 23 日のアクティビティ データを抽出した場合、ファイル名は PBIActivityEvents-20230423-202304250900 になります。 保存先のフォルダー構造も役に立ちますが、各ファイル名はそれだけで完全に判別できるものにする必要があります。

現在の日付よりも少なくとも 1 日前のデータを抽出することをお勧めします。 そうすることで、半端な日のイベントを取得しないようにして、各エクスポート ファイルに 24 時間分の完全なデータが含まれていることを確信できます。

スクリプトでは、前日までの最大 30 日分のデータを収集します。 監査されたイベントのタイムスタンプは常に UTC です。 監査プロセスはすべて、ローカル時刻ではなく UTC 時刻に基づいて構築することをお勧めします。

このスクリプトでは、1 日に 1 つの JSON ファイルが生成されます。 ファイル名のサフィックスには、抽出されたデータのタイムスタンプ (UTC 形式) が含まれます。 同じ日付のデータを複数回抽出した場合は、ファイル名のサフィックスが新しいファイルを識別するのに役立ちます。

#Input values before running the script:
$NbrDaysDaysToExtract = 7
$ExportFileLocation = 'C:\Power-BI-Raw-Data\Activity-Log'
$ExportFileName = 'PBIActivityEvents'
#--------------------------------------------

#Start with yesterday for counting back to ensure full day results are obtained:
[datetime]$DayUTC = (([datetime]::Today.ToUniversalTime()).Date).AddDays(-1) 

#Suffix for file name so we know when it was written:
[string]$DateTimeFileWrittenUTCLabel = ([datetime]::Now.ToUniversalTime()).ToString("yyyyMMddHHmm")

#Loop through each of the days to be extracted (<Initilize> ; <Condition> ; <Repeat>)
For($LoopNbr=0 ; $LoopNbr -lt $NbrDaysDaysToExtract ; $LoopNbr++)
{
    [datetime]$DateToExtractUTC=$DayUTC.AddDays(-$LoopNbr).ToString("yyyy-MM-dd")

    [string]$DateToExtractLabel=$DateToExtractUTC.ToString("yyyy-MM-dd")
    
    #Create full file name:
    [string]$FullExportFileName = $ExportFileName `
    + '-' + ($DateToExtractLabel -replace '-', '') `
    + '-' + $DateTimeFileWrittenUTCLabel `
    + '.json' 

    #Obtain activity events and store intermediary results:
    [psobject]$Events=Get-PowerBIActivityEvent `
        -StartDateTime ($DateToExtractLabel+'T00:00:00.000') `
        -EndDateTime ($DateToExtractLabel+'T23:59:59.999')

    #Write one file per day:
    $Events | Out-File "$ExportFileLocation\$FullExportFileName"

    Write-Verbose "File written: $FullExportFileName" -Verbose 
}
Write-Verbose "Extract of Power BI activity events is complete." -Verbose

Get Activity Events REST API 操作ではなく Get-PowerBIActivityEvent PowerShell コマンドレットを使用する利点がいくつかあります。

  • このコマンドレットでは、コマンドレットを使って呼び出しを行うたびに 1 日のアクティビティを要求できます。 一方、API と直接通信する場合は、API 要求ごとに 1 時間しか要求できません。
  • このコマンドレットでは、後続トークンが自動的に処理されます。 API を直接使う場合は、後続トークンをチェックして、さらに結果が存在するかどうかを判断する必要があります。 一部の API では、大量のデータが返される場合のパフォーマンス上の理由から、改ページ位置の自動修正と後続トークンを使う必要があります。 レコードの最初のセットが返された後、後続トークンを使って後続の API 呼び出しを行い、次のレコード セットを取得できます。 後続トークンが返されなくなるまで、API を呼び出し続けます。 後続トークンを使うことは、複数の API 要求を統合して結果の論理セットを統合できるようにする方法の 1 つです。 後続トークンの使用例については、アクティビティ イベント REST API に関する記事をご覧ください。
  • このコマンドレットは、Microsoft Entra ID (旧称: Azure Active Directory) アクセス トークンの有効期限を処理します。 認証した後、アクセス トークンは 1 時間後に期限切れになります (既定)。 この場合、コマンドレットによって自動的に更新トークンが要求されます。 API と直接通信する場合は、自分で更新トークンを要求する必要があります。

詳しくは、「API または PowerShell コマンドレットを選択する」を参照してください。

注意

応答のサンプルは省略します。前の各例で示した応答と同様の出力であるためです。

この記事に関する詳細については、次のリソースを参照してください。