各サイトのログをOCI loggingに集約

# 概要
システムを稼働する際にアプリケーションやOSでログがとられており、これらログは以下の観点で重要です。
- 問題が発生した場合の調査
- 法規制やガイドラインに遵守するため保管

ログは通常ローカルシステムに吐き出されますがディスクの可用性や容量により保管要件に制約を受ける場合があります。
また各サイトに散らばったログを管理するのも大変です。
そこで、各サイトにあるシステムのログを[Oracle Cloud Infrastructure（OCI）](https://www.oracle.com/jp/cloud/)に集約してまとめて管理できる方法を考えてみました。

# 何がいいの?
- 集約されたログを期間指定やキーワード検索することによって問題調査に有効です
- 集約されたログを法規制やガイドラインに遵守した保管期間でログ保管できるため効率的な管理が可能です

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/44e65ec8-283f-eda8-282d-274f8efe1244.png">

# Linux/Windowsログ
オンプレやクラウド上にあるLinux/Windowsのログを収集します
## 構成
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/dbf429c1-b980-46af-b2df-c949963b6153.png">


## 準備
### OCI資格情報取得
Linux/WindowsからOCIに接続するための資格情報を取得します
- User OCID
    - OCIコンソールナビゲーションメニューから右上の人マーク<img width="25" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/385538f4-b4cc-6919-c320-3594f4ff6b8b.png">をクリックしてユーザー設定を選択
    - ユーザー情報のOCIDをコピー
- Tenancy OCID
    - OCIコンソールナビゲーションメニューから右上の人マーク<img width="25" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/385538f4-b4cc-6919-c320-3594f4ff6b8b.png">をクリックしてテナンシを選択
    - テナンシ情報のOCIDをコピー
- region
    - 東京はap-tokyo-1 大阪はap-osaka-1

- APIキーおよびフィンガープリント
    - OCIコンソールナビゲーションメニューから右上の人マーク<img width="25" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/385538f4-b4cc-6919-c320-3594f4ff6b8b.png">をクリックしてユーザー設定を選択
    - 左のリソースメニューからAPIキーを選択し「APIキーの追加」を押下
    - 秘密キーおよび公開キーをダウンロードして「追加」を押下
    - フィンガープリントが表示されるのでコピー

### OCI Logging設定
受信したログを保存する場所をOCIに設定します
- OCIコンソールナビゲーションメニューから監視および管理>>ロギング>>ログを選択
- ロググループ未作成の場合はログ・グループの作成を実施
- 「カスタム・ログの作成」を押下
- カスタム・ログ名およびログ・グループを指定して「カスタム・ログの作成」を押下
- エージェントは「後で構成を追加」を選択して「エージェント構成の作成」を押下
- 作成したログを選択し、ログ情報のOCIDをコピー

### Policy設定
ログを送信できるよう対象ユーザーを含む動的グループに対して許可を設定します
```
Allow dynamic-group 【動的グループ】 to log-content in tenancy
```

### Pythonインストール
対象システムにPythonをインストールしてpipコマンドでociおよびdatetimeをインストールします

### OCI資格情報設定
OCIで認証するための設定を行います
- config (Linuxは~/.oci/config, Windowsは/User/(ユーザー)/.oci/config
```
user=【User OCID】
fingerprint=【フィンガープリント】
tenancy=【Tenancy OCID】
region=ap-tokyoy-1 または ap-osaka-1
key_file=【ダウンロードした秘密キーファイル】
```
- ダウンロードした秘密キーファイルをkey_fileで設定した場所に移動

## ログ送信用python作成
ログ送信用pythonプログラムを作成してOCI loggingに保管されることを確認します
- パラメータ
    - log_id:OCI Logging設定で取得したログのOCID
    - data:ログメッセージ
    - id:今回は使用しないので"-"を指定
    - time:日付
    - source:システムの名前
    - type:OCI上のログ種類
    - defaultlogentrytime:日付
    - subject:ログの名前　例:/var/log/message  
- ログ送信用pythonプログラム (Linux/Windows共通)
```ocilogingestion.py
import sys
import oci,datetime
from pytz import timezone

# using default configuration file (~/.oci/config)
from oci.config import from_file
config = from_file()

# initialize service client with default config file
loggingingestion_client = oci.loggingingestion.LoggingClient(config,service_endpoint="https://ingestion.logging.ap-tokyo-1.oci.oraclecloud.com")

# command line arguments
args = sys.argv

# time stamp
times_stamp = datetime.datetime.now(timezone('UTC'))

# open logfile
with open(args[2]) as f:
    l_strip = [s.strip() for s in f.readlines()]
    logmsgs = (l_strip)

# log ingestion to OCI
for logmsg in logmsgs:
    put_logs_response = loggingingestion_client.put_logs(
       log_id="ocid1.log.oc1.ap-tokyo-1....",
        put_logs_details=oci.loggingingestion.models.PutLogsDetails(
            specversion="1.0",
            log_entry_batches=[
                oci.loggingingestion.models.LogEntryBatch(
                    # log contents
                    entries=[
                        oci.loggingingestion.models.LogEntry(
                            # log message
                            data=logmsg,
                            id="-",
                            time=times_stamp)],
                    # log source
                    source=args[1],
                    # log kind
                    type="Customlog.Data",
                    defaultlogentrytime=times_stamp,
                    # log name ex:/var/log/message
                    subject="Customlog")]))  

# Get the data from response
print(put_logs_response.headers)
```
- Python実行および結果
引数としてクライアント名および送信するログを指定して実行

【Linux実行結果】
```
[user@linux]$ python3 ocilogingestion.py client01 /path/to/testmsgfromlinux.txt
{'Content-Type': 'application/json', 'Date': 'Fri, 2 Aug 2024 07:55:41 GMT', 
'opc-request-id': '.....', 'connection': 'keep-alive', 
'content-encoding': 'gzip', 'transfer-encoding': 'chunked'}
```
【OCIコンソールでの確認】
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/36f6d86c-6a67-0a88-3b29-ba84241bc1e1.png">

【Windows実行結果】
```
C:\path\to>python ocilogingestion.py client02 /path/to/testmsgfromwin.txt
{'Content-Type': 'application/json', 'Date': 'Fri, 2 Aug 2024 08:07:25 GMT', 
'opc-request-id': '.....', 'connection': 'keep-alive', 
'content-encoding': 'gzip', 'transfer-encoding': 'chunked'}
```
【OCIコンソールでの確認】
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/c855f7e0-f050-15a4-5204-b772543a6513.png">

## ログ定期送付
ここでは例としてlinuxの/var/log/messagesを定期的にOCI Loggingに送信します

- ログ差分取得およびOCIへの送信Shell
```logingestion.sh
#!/bin/bash

# ログを一時ファイルにコピー
sudo cp /var/log/messages /path/to/logdata.txt
# 一時ファイルと前回のログを比較し差分をファイルに書き出し
sudo diff --old-line-format='' --new-line-format='%L' --unchanged-line-format='' /path/to/logdataprev.txt /path/to/logdata.txt > /path/to/logdiff.txt
# 一時ファイルを前回ログとしてコピーして次回に利用
sudo mv /path/to/logdata.txt /path/to/logdataprev.txt

#差分がある場合は差分のログをOCIに送信
if [ ! -s /path/to/logdiff.txt ]; then
  echo "Skip ingestion"
else
  echo "ingestion"
  python3 /path/to/ocilogingestion.py client01 /path/to/logdiff.txt
  rm /path/to/logdiff.txt
fi
```
- cronで1分ごとに実行
```crontab.
*/1 * * * * /bin/bash /path/to/logingestion.sh
```
## 実行結果
Linuxのlogの内容がOCI loggingに表示できました
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/f977349a-8f16-15a2-f87e-dad6d489ccec.png">

# AWS CloudWatch log
AWS CloudWatch logをOCIに収集します
## 構成
OCI内のVMから定期的にCloudWatch logのログを取得します
次にVM内統合モニタリングエージェントを使ってOCI Loggingにログを送信します。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/4950478a-cd6d-ba7e-94ea-69f58b43f927.png">

## 準備
### AWS資格情報取得
OCI VMからAWS Cloud Watch Logにアクセスしてログを取得するたAWSユーザー情報を取得します
- ユーザー作成時または作成したユーザーに許可ポリシー CloudWatchLogReadOnlyAccessをアタッチ
- セキュリティ認証情報からアクセスキーを作成

### OCI VM環境準備
OCI VMからAWS Cloud Watch Logにアクセスしてログを取得するための準備を行います。
- OCIコンソールを使用してLinux VM作成
- VMにAWS CLIをインストールしてconfig設定
- ~/.aws/下にconfigおよびcredentialsが作成されることを確認

### AWS CloudWatch Log取得
AWS CLIでCloudWatch Logからログ取得できることを確認します
今回は10分毎に取得したログを/var/log/aws/ec2varlog.logに書き出します

```AWSCloudWatchLog2OCI.sh
#! /bin/bash
starttime=$(expr `date -d "10 minutes ago" +"%s"` \* 1000)
endtime=$(expr `date +"%s"` \* 1000)
/usr/local/bin/aws logs get-log-events \
  --log-group-name messages \
  --log-stream-name 【AWS CloudWatch logの取得対象ログストリーム名】 \
  --start-time ${starttime} \
  --end-time ${endtime} \
  --query "events[].[message]" \
  --output text >> /var/log/aws/ec2varlog.log
```
```
crontab -l
*/10 * * * * /bin/sh /path/to/AWSCloudWatchLog2OCI.sh
```

### OCI VM環境準備
以下のリンクを参考にVMの/var/log/aws/ec2varlog.logに保存したログをOCI loggingに収集します
リンク内のログ入力の構成のファイル・パスは/var/log/aws/ec2varlog.logを指定します
[ロギング・サービスを使って3つのログを収集する - カスタム・ログの作成](https://oracle-japan.github.io/ocitutorials/intermediates/using-logging/#anchor3)

### 実行結果
CloudWatch logの内容がOCI loggingに表示できました
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/c074d0f1-738e-38b8-034a-1998c751781d.png">


# ログの長期保管
- OCI Loggingは保管日数を1ヶ月から6ヶ月まで設定可能です
- ログ保管日数よりも長い期間保管する場合オブジェクトストレージに保管することにより長期保管が可能です
[オブジェクト・ストレージへのログのアーカイブ](https://docs.public.oneportal.content.oci.oraclecloud.com/ja-jp/iaas/Content/connector-hub/archivelogs.htm)
- オブジェクトストレージのアーカイブ層に保管することにより標準層に比べかなり安く保管が可能です
耐監査性のような長期間保管必要かつアクセス頻度が低く取り出し時間に時間がかかってもよい場合はアーカイブ層への保管をおすすめします
    - アーカイブ層への保管は以下の方法が選択可能です
        -  アーカイブ層に設定されたバケットへ保管
        -  標準層のバケットにライフサイクル・ポリシー・ルールを設定して、設定した日数を経過すると標準層からアーカイブ層に変更