イベントモニタリングのログデータを出力する

## イベントモニタリングとは

ユーザアクティビティを追跡するログ機能です。
Salesforceのセキュリティアドオンである[Salesforce Shield](https://www.salesforce.com/jp/products/platform/products/shield/)の製品の一つです。
取得できるイベントは「ログイン」「レポートのエクスポート」など49種(v48.0)あります。
取得できるイベントの詳細は[公式ドキュメント](https://developer.salesforce.com/docs/atlas.ja-jp.api.meta/api/sforce_api_objects_eventlogfile_supportedeventtypes.htm)を参照ください。
ユーザのアクティビティログをSalesforce組織内で1年間取得・保持します（Spring'24より前は30日間でした）。
期間を超えて保持するためにはログデータの出力が必要です。

## EventLogFileオブジェクトについて

イベントモニタリングのログはEventLogFileオブジェクトに格納されます。
イベント種別、対象日ごとに1件のレコードが作成され、ログCSVがBase64に符号化されてLogFile列に格納されています。
ログが1件もないイベント種別ではEventLogFileレコード自体作成されません。
このオブジェクトには下記の項目があります。

|項目|説明|
|:--|:--|
|EventType|API、ログイン、レポート、URI などのイベントタイプ。各自の組織に生成されたファイルを判別するために使用します。|
|Interval|Daily または Hourly。|
|LogDate|ログファイル作成日時。|
|LogFile|★Logの本体。CSV形式のデータがBase64で符号化された値が格納されています。|
|LogFileFieldNames|LogFileのCSVデータのヘッダー。|
|LogFileFieldTypes|LogFileの各列のデータ型。|
|LogFileLength|LogFileのデータサイズ。|
|Sequence|Hourlyのログファイルのイベントログファイルデータの部分の番号。|
|CreatedDate|EventLogFileレコードの作成時刻|

「1 時間ごとのイベントログファイルの場合、(LogDateではなく)CreatedDate を使用して、EventLogFile オブジェクトが作成された日時を照会することをお勧めします。」([SOAP API 開発者ガイド](https://developer.salesforce.com/docs/atlas.ja-jp.api.meta/api/sforce_api_objects_eventlogfile.htm))とのこと。

## ログデータのダウンロード

Salesforceには30日間しかログが保持されないので、過去のログを使用するためにはダウンロードして別途保管する必要があります。
ログを保存する方法は、外部システムからREST APIを使用してダウンロードする方法とブラウザからダウンロードする方法があります。

<!-- 
Apexはガバナ制限でヒープの合計サイズが指定されていて、6MB(同期処理)または12MB(非同期処理)が上限に設定されています。
EventLogFileのLogFileはデータ量が大きくなりがちで、12MBを超える組織が多いと思います。
そのため、Apexではなく、APIを使用してログを取得ことになります。
また、33を使用してUIからログをダウンロードすることもできます。
-->

## ① ブラウザからイベントログをダウンロードする

Spring'24から[Setup (設定)] の [Event Log File Browser (イベントログファイルブラウザー)] からイベントログを簡単にダウンロードできるようになりました。

手順の詳細は[こちら](https://trailhead.salesforce.com/ja/content/learn/modules/event_monitoring/event_monitoring_download)を参照。

<!--
![ELF001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/707d8b2c-3885-06b6-7b16-744ca0cac37e.png)

1. シークレットウインドウで[Salesforce Event Log File Browser](https://salesforce-elf.herokuapp.com/)にアクセスする。
1. [Production Login]をクリックします。
1. ユーザ名とパスワードを入力してログインします。
1. 検索する日付範囲を入力します。
1. 検索するイベントタイプを入力します。
1. 間隔 (毎日または毎時) を入力します。
1. [Apply] をクリックします。

### 留意点
* ログインの際、「アクセスを許可しますか?」と表示された場合は[許可]をクリックします。
* IP制限をかけている場合、ログインエラーになることがあります。その場合は下記の手順でIP制限を緩和します。

#### IP制限をかけているユーザでEvent Log File Browserを使用する
1. [設定]-[アプリケーション]-[接続アプリケーション]-[接続アプリケーションの OAuth の利用状況]をクリックします。
1. 接続アプリケーション「elfbrowser」の[インストール]をクリックします。
![ELF004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/831759f9-0619-ef9e-55b8-509f6029a073.png)
1. 「接続アプリケーションをインストールしますか?」と問われるので、アプリケーション名を確認して[インストール]をクリックします。
1. 接続アプリケーションの詳細画面が開かれます。
![ELF003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/f8382dde-654e-7f03-728f-abbb04a643ab.png)
1. [ポリシーを編集]をクリックしてIP制限の緩和に「IP制限の緩和」を設定します。
1. Salesforce Event Log File Browser でログインを試みます。
-->

## ② データローダを使用してイベントログをダウンロードする

この方法では、ログデータがbase64にエンコードされて出力されるため、そのまま使用することができません。
③のElfPyを使用する方法がおすすめです。

1. データローダを実行します。
1. [Export]をクリックします。
1. Step2で[Show all Salesforce objects]にチェックを入れ、[Event Log File(EventLogFile)]を選択します。
![ELF005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/fe6f21f3-a5f2-f8a4-4d09-225702dc8c40.png)
1. Step3でクエリを記述して[Finish]をクリックします。ファイルサイズが大きいため、LogDateでフィルターを掛けることをおすすめします。
1. ログが出力されます。ログは「LogFile」の列にBase64に符号化されています。
![ELF006_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125621/6f228355-a150-12e0-5f2b-82f6de82b00e.png)

## ③ ElfPyを使用してイベントログをダウンロードする

ElfPyは[Adam Torman](https://admin.salesforce.com/blog/author/atorman)がGitHubで公開しているEventLogFileのダウンロードするためのPythonでかかれたスクリプトです。
データローダではLogFileはBase64に符号化されてCSVの1つの列に格納されていましたが、ElfPyを使用すると、LogFile自体をCSVで出力することが可能です。
<https://github.com/atorman/elfPy>

### 事前準備

1. [Python3.x.x](https://www.python.org/downloads/)をインストールします。
1. Salesforce組織で接続アプリケーションを作成し、コンシューマ鍵とコンシューマの秘密を取得します(接続アプリケーションの作成方法は[こちら](https://qiita.com/TaaaZyyy/items/7feb7d03cb1f5248d2e9#2-%E6%8E%A5%E7%B6%9A%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8Boauth%E3%81%AB%E3%82%88%E3%82%8B%E8%AA%8D%E8%A8%BC)にまとめました)。
1. [ElfPy](https://github.com/atorman/elfPy)をダウンロードします。
1. ダウンロードした elf.py をエディタで開き、`FILL_ME_IN`を書き換えます。`CLIENT_ID`にはコンシューマ鍵を、`CLIENT_SECRET`にはコンシューマの秘密を入力します。なお、elf2.pyはPython2.x.x用です。

```py:elf.py
##########################################################################################
# Connected App information: fill it in by creating a connected app
# https://help.salesforce.com/articleView?id=connected_app_create.htm&language=en_US&type=0
CLIENT_ID = 'FILL_ME_IN'
CLIENT_SECRET = 'FILL_ME_IN'
##########################################################################################
```

1. sandboxのイベントログを取得したい場合は、ログインURLを`https://login.salesforce.com/services/oauth2/token`から`https://test.salesforce.com/services/oauth2/token`に書き換える必要があります。

```py:elf.py
# create a new salesforce REST API OAuth request
url = 'https://login.salesforce.com/services/oauth2/token'
data = { 'grant_type': 'password', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'username': username, 'password': password}
headers = {'X-PrettyPrint' : '1'}
```

### 使用方法

コンソールまたはコマンドプロンプトを開き、elf.pyのあるディレクトリに移動します。
[こちら](https://github.com/atorman/elfPy)からダウンロードできます。
下記コマンドからelf.pyを実行します。

```console
python elf.py
```

```console
Username:
Password:
```

Salesforceのユーザ名とパスワードが求められるので入力します。
なお、会社の信頼できる IP 範囲外の IP アドレスから Salesforce にアクセスするときはセキュリティトークンが必要になります。セキュリティトークンについては[こちら](https://qiita.com/TaaaZyyy/items/7feb7d03cb1f5248d2e9#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97)。Passwordの入力の際にパスワードとセキュリティトークンを続けて入力して下さい。

```console
Date range (e.g. Last_n_Days:2, Today, Tomorrow):
```

Date range はイベントログの対象日を指定します。日時形式または日付リテラルで入力し、エンターを押します。
日付を指定する場合はGMTで0時0分を指定します。例:`2020-05-19T00:00:00Z`
何も入力されない場合は`Last_n_Days:2`が使用されます。

```console
Output directory:
```

出力したログファイルを格納するディレクトリを指定します。
何も入力しない場合、`elf`フォルダが作成されます。

```console
Use compression (y/n)
```

最後に、レスポンスボディを圧縮するかどうか聞かれます。
通常、`y`で問題ありません。何も入力しない場合、圧縮が行われます。
詳細は[公式ドキュメント](https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/intro_rest_compression.htm#intro_rest_compression)を参照してください。

```console
********************************
Downloading: 2020-05-19-Report.csv to C:\Users\username\Desktop\elfPy-master/elf

Total download time: 0.172285 seconds

Using gzip compression
```

ダウンロードが実行されます。
データローダを使用したときとは異なり、LogFileがCSV形式で直接出力できます。

<!--
★★★★★★★★★★★★★★★★★★★★★★★★★★★★

ユーザ名とパスワードが聞かれるので入力します。
この時エラーになる場合は下記を確認してください。

- コンシューマ鍵、コンシューマの秘密が正しいか。
- IP制限をかけていない場合、セキュリティトークンを設定しているか。
    - セキュリティトークンの取得は[こちら](https://qiita.com/TaaaZyyy/items/7feb7d03cb1f5248d2e9#%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97)を参照してください。
    - Passwordの入力の際にパスワードとセキュリティトークンを続けて入力して下さい。
- IP制限の範囲内から実行しているか(接続アプリケーションのポリシーに「IP制限を適用」を設定している場合)
- ユーザに適切なプロファイル・権限セットが付与されているか(接続アプリケーションのポリシーに「管理者が承認したユーザは事前承認済み」が設定されている場合)
-->

## ④ その他

### ElfBashを使用してイベントログをダウンロードする

ElfPyと同じ作者がBash Shell Script版を公開しています。
こちらを使用することでもイベントログを出力できます。
<https://github.com/atorman/elfBash>

### 任意の言語でダウンロードツールを作成する

SalesforceのREST APIを使用して、ElfPyと同様のものを任意の言語[^2]で作成することが可能です。
EventLogFileの出力には2つのRESTリソースを使用します。
外部システムからSalesforceのREST APIを使用する方法については[こちらの記事](https://qiita.com/TaaaZyyy/items/7feb7d03cb1f5248d2e9)で取り扱いました。参考にしてください。

1. 「[Query](https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/resources_query.htm)」を使用してEventLogFileレコードを取得する
    - `/services/data/{APIversion}/query?q=SELECT+Id,+EventType,+Logdate+FROM+EventLogFile`

1. 「[sObject Blob Retrieve](https://developer.salesforce.com/docs/atlas.ja-jp.api_rest.meta/api_rest/resources_sobject_blob_retrieve.htm#resources_sobject_blob_retrieve)」を使用してblob項目を取得する
    - `/services/data/{APIversion}/sobjects/EventLogFile/{eventlogfileのsfid}/LogFile`

## 参照

- [EventLogFile | Developers](https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_eventlogfile.htm)
- [イベントモニタリング | Trailhead](https://trailhead.salesforce.com/ja/content/learn/modules/event_monitoring)
- [ElfPy - a Tasty Little Script for Downloading Event Log Files on Multiple Platforms](https://www.salesforcehacker.com/2015/03/elfpy-tasty-little-script-for.html)
- [elfPy | GitHub](https://github.com/atorman/elfPy)

<!-- 注釈 -->
[^2]: ただし、Apexはヒープサイズの上限が12MB(非同期処理時)のため、現実的ではありません。