のーずいだんぷ

主に自分用メモですが、もしかしたら誰かの役に立つかもしれません

CloudWatchLogsにログを保存する際に便利なこと

はじめに

webサーバやアプリケーションサーバ等を構築する際に、ログをどう集め分析するかが課題になるが 単一のサーバでの分析であれば、CloudWatchLogsエージェントを使用すれば簡単なログの収集、分析、監視、可視化が可能になる。

本記事では詳細は紹介しないが、CloudWatchLogsではロググループごとに独自の検索(フィルタリング)が可能である。 aws公式ドキュメント

CloudWatchLogsはログをjsonで引き渡すとよいという話

ドキュメント見てもらうとわかると思うがいくつかのフィルタパターンを指定できる。そしてログがjson形式で出力されている場合、

{ $.Key = "Value" }
{ $.Key != "Value" }
{ $.Key[0] = "Value"}

などなどありがちなjson形式を指定でき便利である。

という事でpythonでjson形式のログを出力したい場合、次のようにformatterjson.dumpsしてやればいい感じで出力される。

↓サンプルコード

import logging
import sys
import json

def set_logger(logger_name,log_file_name):

    logger = logging.getLogger(logger_name)
    # ルートロガー設定
    logger.setLevel(logging.DEBUG)
    # コンソール出力用のハンドラー
    to_stream = logging.StreamHandler(stream=sys.stdout)
    # ファイル出力用のハンドラー
    to_file = logging.handlers.FileHandler(filename=log_file_name)
    # ハンドラーごとの出力レベル定義
    to_stream.setLevel(logging.DEBUG)
    to_file.setLevel(logging.INFO)
    # ハンドラーにセットするformatterを設定(時刻以外)
    jsonFormat = json.dumps(dict(level="%(levelname)s", time="%(asctime)s",
                                 function="%(funcName)s", message="%(message)s"))
    # 引数:fmtにformatterを渡す&時刻の書式を好みの形になるように引数:datefmtへ
    log_format = logging.Formatter(fmt=jsonFormat,
                                   datefmt="%Y-%m-%d %H:%M:%S")
    # それぞれのハンドラへformatterをセットしてやる
    to_stream.setFormatter(log_format)
    to_file.setFormatter(log_format)
    # ロガーへハンドラーを追加する
    logger.addHandler(to_stream)
    logger.addHandler(to_file)
    logger.INFO("Hello World")
    return logger

私は基本上記のようにモジュール化しておき、使い回す形にしている。

 logger を利用する場合でもルートのレベルはちゃんと設定し直すこと。(default:warningのためログが出ない!?みたいなことに陥る。ルートは個人的には最も低レベルなDEBUGにしておき、ここのハンドラ、もしくは子loggerのレベルで調整してやるのが良い)

そしてこのコードだと以下の様、ログ出力が得られる。

{
    "level": "INFO",
    "time": "2019-06-24 02:11:18",
    "function": "<module>",
    "message": "Hello World"
}

具体的な値でフィルタリングをもう一度説明すると、例えばINFOレベルのログだけを表示させたければ…

{ $.level = "INFO" }

でフィルタリングが可能になる。