LoginSignup
0
0

More than 1 year has passed since last update.

Lambda(SAM)からAmazon CloudWatch Logs(LocalStack) のログイベントを取得する方法 メモ

Posted at
  • LocalStack上で動くAmazon CloudWatch LogsのログイベントをAWS SAM CLIで動くLambdaから取得する方法をメモする。

構成

sam-logs.png

LocalStack 準備

  • docker-compose.yml
  version: "3.8"
  networks:
    container-link:
      name: docker.internal
  services:
    localstack:
      container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
      image: localstack/localstack
      ports:
        - "127.0.0.1:53:53"                # only required for Pro
        - "127.0.0.1:53:53/udp"            # only required for Pro
        - "127.0.0.1:443:443"              # only required for Pro
        - "127.0.0.1:4510-4530:4510-4530"  # only required for Pro
        - "127.0.0.1:4566:4566"
        - "127.0.0.1:4571:4571"
      environment:
        - SERVICES=${SERVICES- }
        - DEBUG=${DEBUG- }
        - DATA_DIR=${DATA_DIR- }
        - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR- }
        - LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY- }  # only required for Pro
        - HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
        - DOCKER_HOST=unix:///var/run/docker.sock
      volumes:
        - "${TMPDIR:-/tmp}/localstack:/tmp/localstack"
        - "/var/run/docker.sock:/var/run/docker.sock"
      networks:
        - container-link
  • 起動
  docker-compose up

Cloudwatch logs準備

  • AWS CLIを使用し、ロググループを作成する。

1. ロググループを作成する

  • ロググループtest-log-groupを作成する。
$ aws logs create-log-group --log-group-name test-log-group --endpoint-url=http://localhost:4566 --profile localstack

2. ログストリームを作成する

  • ロググループtest-log-groupにログストリームtest-log-streamを作成する。
$ aws logs create-log-stream --log-group-name test-log-group --log-stream-name test-log-stream --endpoint-url=http://localhost:4566 --profile localstack

3. ログイベントをPUTする

初回PUT時

  • ログストリームtest-log-streamにログイベントをPUTする
$ aws logs put-log-events --log-group-name test-log-group --log-stream-name test-log-stream --log-events timestamp=1635589048,message='LOG EVENTS 1' --endpoint-url=http://localhost:4566 --profile localstack

2回目以降のPUT時

  • トークンを取得してから、ログイベントをPUTする。
$ TOKEN=$(aws logs describe-log-streams --log-group-name test-log-group --query 'logStreams[].uploadSequenceToken' --endpoint-url=http://localhost:4566 --profile localstack --output text)
$ aws logs put-log-events \
        --log-group-name test-log-group \
        --log-stream-name test-log-stream \
        --log-events timestamp=1635589048,message='LOG EVENTS 2' \
        --sequence-token ${TOKEN} --endpoint-url=http://localhost:4566 --profile localstack

4. ログイベントを確認する

$ aws logs get-log-events --log-group-name test-log-group --log-stream-name test-log-stream --endpoint-url=http://localhost:4566 --profile localstack
{
    "events": [
        {
            "timestamp": 1635589048,
            "message": "LOG EVENTS 1",
            "ingestionTime": 1635591467580
        },
        {
            "timestamp": 1635589048,
            "message": "LOG EVENTS 2",
            "ingestionTime": 1635591480764
        }
    ],
    "nextForwardToken": "f/00000000000000000000000000000000000000000000000000000001",
    "nextBackwardToken": "b/00000000000000000000000000000000000000000000000000000000"
}

Lambda準備

Lambda

  • ひな形作成
  sam init

※ランタイムはPython3.8を選択。

  • template.yml

    • Hello World Exampleを利用する。
  • requrements.txt

  requests
  boto3

※CloudWatch logsアクセス用にboto3追加

  • Lambda処理(app.py)修正
  import json
  from boto3.session import Session
  from datetime import datetime


  # Cloudwatch logs 接続設定
  session = Session(
      aws_access_key_id='dummy',
      aws_secret_access_key='dummy',
      region_name='ap-northeast-1'
  )
  client = session.client(
      service_name='logs', 
      endpoint_url='http://localstack:4566'
  )


  def lambda_handler(event, context):
      # ロググループ名
      group_name="test-log-group"
      # ログストリーム取得
      streams = client.describe_log_streams(
          logGroupName="test-log-group",
          orderBy='LastEventTime',
          descending=True
      )
      response = {}
      response["group"] = group_name
      response["streams"]=[]
      for stream in streams['logStreams']:
          stream_name = stream['logStreamName']
          stream_response = {}
          stream_response["stream_name"] = stream_name
          # ログ取得
          logs = client.get_log_events(
              logGroupName=group_name,
              logStreamName=stream_name,
              startFromHead=True
          )
          body = logs['events']
          stream_response["logs"]=[]        
          for line in body:
              message = '[{}] {}'.format(datetime.fromtimestamp(int(str(line['timestamp'])[:10])), line['message'])
              stream_response["logs"].append(message)
          response["streams"].append(stream_response)
      return {
          "statusCode": 200,
          "body": json.dumps(response),
      }

動作確認

  • ビルド
  sam build
  • 実行
  sam local start-api --docker-network docker.internal
  • リクエスト
  GET /hello HTTP/1.1
  Host: localhost:3000
  Content-Type: application/json
  • レスポンス
  {
      "group": "test-log-group",
      "streams": [
          {
              "stream_name": "test-log-stream",
              "logs": [
                  "[2021-10-30 10:17:28] LOG EVENTS 1",
                  "[2021-10-30 10:17:28] LOG EVENTS 2"
              ]
          }
      ]
  }

参考情報

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0