[JAWS-UG CLI] CloudWatch Logs:#3 メトリックフィルタの作成

AWS CLIを利用して、CloudWatch Logsのメトリックフィルタを作成してみます。


前提条件
========


CloudWatchへの権限
------------------

* CloudWatchに対してフル権限があること。(LogsだけではなくCloudWatchの権限が必要。)


AWS CLIのバージョン
-------------------

* 以下のバージョンで動作確認済

  * AWS CLI 1.7.24

```bash:コマンド:
aws --version
```

```text:結果(例):
      aws-cli/1.7.24 Python/2.7.5 Darwin/13.4.0
```


0. 準備
=======


0.1. リージョンの決定
---------------------

メトリックフィルタを作成するロググループの存在するリージョンを指定します。

(カレントユーザが利用するカレントリージョンも切り変わります。)

```bash:コマンド(東京リージョンの場合):
export AWS_DEFAULT_REGION='ap-northeast-1'
```


0.2. 変数の確認
---------------

プロファイルとリージョンが想定のものになっていることを確認します。

```bash:変数の確認:
aws configure list
```

```text:結果(例):
            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile cloudwatchFull-prjZ-mbp13             env    AWS_DEFAULT_PROFILE
      access_key     ****************LOAQ shared-credentials-file
      secret_key     ****************I1O1 shared-credentials-file
          region           ap-northeast-1              env    AWS_DEFAULT_REGION
```


0.3. ロググループの指定
-----------------------

メトリックフィルタを作成するロググループを指定します。


```bash:コマンド:
LOG_GROUP_NAME='<ロググループ名>'
```


0.4. ロググループの内容確認
---------------------------

メトリックフィルタを作成するロググループの内容を確認します。


```bash:コマンド:
aws logs describe-log-groups \
        --log-group-name-prefix ${LOG_GROUP_NAME}
```

```json:結果(例):
      {
        "logGroups": [
          {
              "storedBytes": 136,
              "metricFilterCount": 1,
              "creationTime": 1430093242053,
              "logGroupName": "test/sample",
              "retentionInDays": 3653,
              "arn": "arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:log-group:test/sample:*"
          }
        ]
      }
```


0.5. ログストリームの決定
-------------------------

メトリックフィルタの動作確認で利用するログストリームを指定します。


```bash:コマンド:
LOG_STREAM_NAME='<ログストリーム名>'
```


0.6. ログストリームの確認
-------------------------

メトリックフィルタの動作確認で利用するログストリームの内容を確認します。

```bash:コマンド:
aws logs describe-log-streams \
        --log-group-name ${LOG_GROUP_NAME} \
        --log-stream-name-prefix ${LOG_STREAM_NAME}
```

```json:結果(例):
      {
        "logStreams": [
          {
              "firstEventTimestamp": 1430097329000,
              "lastEventTimestamp": 1430097440000,
              "creationTime": 1430097202493,
              "uploadSequenceToken": "49545657805657863444697949852012247908352473464309809682",
              "logStreamName": "test-stream",
              "lastIngestionTime": 1430097450933,
              "arn": "arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:log-group:test/sample:log-stream:test-stream",
              "storedBytes": 136
          }
        ]
      }
```


1. 事前作業
===========


1.1. メトリックフィルタ名の決定
-------------------------------

メトリックフィルタ名を決めます。

```bash:コマンド:
LOG_FILTER_NAME='test-filter'
```


1.2. 同名のメトリックフィルタの不存在確認
-----------------------------------------

同名のメトリックフィルタが存在しないことを確認します。

```bash:コマンド:
aws logs describe-metric-filters \
        --log-group-name ${LOG_GROUP_NAME}
```

```json:結果:
      {
          "metricFilters": []
      }
```


1.3. メトリックフィルタパターンの決定
-------------------------------------

メトリックに転送するデータのマッチングパターンを決めます。

```bash:コマンド:
STR_FILTER_PATTERN='Error'
```


1.4. メトリックフィルタパターンのテスト
---------------------------------------

メトリックフィルタパターンがメッセージに対して想定通りにマッチするかテストします。


```bash:コマンド:
LOG_EVENT_MSG="Error: event sample 1."
```

```bash:変数の確認:
cat << ETX

        STR_FILTER_PATTERN: "${STR_FILTER_PATTERN}"
        LOG_EVENT_MSG:       ${LOG_EVENT_MSG}

ETX
```

```bash:コマンド:
aws logs test-metric-filter \
        --filter-pattern "${STR_FILTER_PATTERN}" \
        --log-event-messages "${LOG_EVENT_MSG}"
```

```json:結果(例):
      {
        "matches": [
          {
              "eventNumber": 1,
              "eventMessage": "test: event sample 1.",
              "extractedValues": {}
          }
        ]
      }
```


1.5. メトリックの名前空間の決定
-------------------------------

マッチしたメッセージを転送するメトリックの名前空間を決めます。


```bash:コマンド:
CWATCH_NAMESPACE='testNS'
```


1.6. メトリック名の決定
-----------------------

マッチしたメッセージを転送するメトリックを決めます。


```bash:コマンド:
CWATCH_METRIC_NAME='testMetric'
```


1.7. メトリック値の決定
-----------------------

マッチしたメッセージを転送する条件を決めます。

*キーワードをカウントしている場合:  1
* バイト数をカウントしている場合: 閾値(byte)

```bash:コマンド:
LOG_METRIC_VALUE='1'
```


2. メトリックフィルタの作成
===========================


2.1. メトリックトランスフォーメーション内容の決定
-------------------------------------------------

先程決めたメトリックトランスフォーメーションの各パラメータを組み立てます。


```bash:コマンド:
STR_METRIC_TRANS="metricName=${CWATCH_METRIC_NAME},metricNamespace=${CWATCH_NAMESPACE},metricValue=${LOG_METRIC_VALUE}" \
        && echo "${STR_METRIC_TRANS}"
```


2.2. メトリックフィルタの作成
-----------------------------

メトリックフィルタを作成します。

```bash:変数の確認:
cat << ETX

        LOG_GROUP_NAME:     ${LOG_GROUP_NAME}
        LOG_FILTER_NAME:    ${LOG_FILTER_NAME}
        STR_FILTER_PATTERN: "${STR_FILTER_PATTERN}"
        STR_METRIC_TRANS    ${STR_METRIC_TRANS}

ETX
```

```bash:コマンド:
aws logs put-metric-filter \
        --log-group-name ${LOG_GROUP_NAME} \
        --filter-name ${LOG_FILTER_NAME} \
        --filter-pattern "${STR_FILTER_PATTERN}" \
        --metric-transformations ${STR_METRIC_TRANS}
```

```text:結果:
      (戻り値なし)
```


3. 事後作業
===========


3.1. メトリックフィルタの確認
-----------------------------

作成したメトリックフィルタを確認します。

```bash:コマンド:
aws logs describe-metric-filters \
        --log-group-name ${LOG_GROUP_NAME}
```

```json:結果(例):
      {
        "metricFilters": [
          {
              "filterName": "test-filter",
              "metricTransformations": [
                  {
                      "metricValue": "1",
                      "metricNamespace": "testNS",
                      "metricName": "testMetric"
                  }
              ],
              "creationTime": 1430103584640,
              "filterPattern": "Error"
          }
        ]
      }
```


3.2. ログイベントの作成
-----------------------

メトリックフィルタの動作確認用のログイベントを作成します。


```bash:コマンド:
LOG_PUT_TOKEN=`aws logs describe-log-streams --log-group-name ${LOG_GROUP_NAME} --log-stream-name-prefix ${LOG_STREAM_NAME} --query 'logStreams[].uploadSequenceToken' --output text` \
        && echo ${LOG_PUT_TOKEN}
```

```text:結果(例):
      49545657805836269406286217709901357107175578637378257042
```

```bash:コマンド:
TIME_EPOCH="`date +%s`000"
LOG_MSG='Error: event sample 3.'
LOG_EVENTS="timestamp=${TIME_EPOCH},message=\"${LOG_MSG}\""
```

```bash:変数の確認:
cat << ETX

        LOG_GROUP_NAME:   ${LOG_GROUP_NAME}
        LOG_STREAM_NAME:  ${LOG_STREAM_NAME}
        LOG_EVENTS:      "${LOG_EVENTS}"
        LOG_PUT_TOKEN:    ${LOG_PUT_TOKEN}

ETX
```

```bash:コマンド:
aws logs put-log-events \
        --log-group-name ${LOG_GROUP_NAME} \
        --log-stream-name ${LOG_STREAM_NAME} \
        --log-events "${LOG_EVENTS}" \
        --sequence-token ${LOG_PUT_TOKEN}
```

```json:結果(例):
      {
        "nextSequenceToken": "49545657805836269406286217727077775152260327876857954450"
      }
```


3.3. メトリックの存在確認
-------------------------

メトリックが生成されたことを確認します。 (15分程度かかるかもしれません)


```bash:コマンド:
aws cloudwatch list-metrics \
        --namespace ${CWATCH_NAMESPACE}
```

```json:結果(例):
      {
        "Metrics": [
          {
              "Namespace": "testNS",
              "Dimensions": [],
              "MetricName": "testMetric"
          }
        ]
      }
```


3.4. メトリックのデータ確認
---------------------------

メトリックに格納された統計情報を確認します。

統計情報の取得単位(周期)を秒単位で指定します。 
ここでは5分(300秒)周期にしてみます。

```bash:コマンド:
CWATCH_STAT_PERIOD='300'
```

統計情報の対象期間を指定します。 
ここでは、24時間(1440分)前から現在を対象にしてみます。

```bash:コマンド:
CWATCH_END_TIME=`date -u '+%FT%TZ'` \
        && echo ${CWATCH_END_TIME}
      TIME_BEFORE_MIN='1440'
```

```bash:コマンド(OSX/BSD系OSの場合):
CWATCH_START_TIME=`date -u -v-${TIME_BEFORE_MIN}M '+%FT%TZ'` \
        && echo ${CWATCH_START_TIME}
```

```bash:コマンド(Linux系OSの場合):
CWATCH_START_TIME=`date -u -d "${TIME_BEFORE_MIN} mins ago" '+%FT%TZ'` \
        && echo ${CWATCH_START_TIME}
```

集計方法を決定します。

```bash:コマンド:
CWATCH_STATISTICS='Sum'
```

統計情報を取得します。

```bash:変数の確認:
cat << ETX

        CWATCH_NAMESPACE:   ${CWATCH_NAMESPACE}
        CWATCH_METRIC_NAME: ${CWATCH_METRIC_NAME}
        CWATCH_START_TIME:  ${CWATCH_START_TIME}
        CWATCH_END_TIME:    ${CWATCH_END_TIME}
        CWATCH_STAT_PERIOD: ${CWATCH_STAT_PERIOD}
        CWATCH_STATISTICS:  ${CWATCH_STATISTICS}

ETX
```

```bash:コマンド:
aws cloudwatch get-metric-statistics \
        --namespace ${CWATCH_NAMESPACE} \
        --metric-name ${CWATCH_METRIC_NAME} \
        --start-time ${CWATCH_START_TIME} \
        --end-time ${CWATCH_END_TIME} \
        --period ${CWATCH_STAT_PERIOD} \
        --statistics ${CWATCH_STATISTICS}
```

```json:結果(例):
      {
        "Datapoints": [
          {
              "Timestamp": "2015-04-27T03:06:00Z",
              "Sum": 1.0,
              "Unit": "None"
          }
        ],
        "Label": "testMetric"
      }
```


完了
====

以上で、CloudWatch Logsにおける各エンティティの作成は完了しました。