仕事中の問題と解決メモ。

最近はPythonとGoogle Cloud Platformがメイン。株式会社ビズオーシャンで企画と開発運用、データ活用とか。https://github.com/uyamazak/

Pythonで重複してログが出力されるとき

本番運用しながら絶賛開発中のoceanusで、本格的にログの必要性を感じ、ログレベルを分けながら使ってみている。

この記事を読んでloggerとloggingの違いをなんとなく感じ取って

qiita.com


フォーマットは統一したいので、こんな感じの共通で使える関数を作り

import logging
from os import environ

def oceanus_logging():
    LOG_LEVEL = os.environ['LOG_LEVEL']
    logger = logging.getLogger(__name__)
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s- '
                                  '%(levelname)s - '
                                  '%(message)s')
    handler.setFormatter(formatter)
    logger.setLevel(getattr(logging, LOG_LEVEL))
    logger.addHandler(handler)
    return logger

親クラスのinitで処理するようにしたが

from common.utils import oceanus_logging

class ExecutionResource(object):


    def __init__(self):
        self.logger = oceanus_logging()

falconのルーティングで下記のように子クラス読み込む度にloggerが作られてしまうようで、一つのイベントに5個も同じログが書き出されるようになってしまった。

app.add_route('/swallow', SwallowResource())
app.add_route('/swallow/{site_name}', SwallowResource())
app.add_route('/pirate/{site_name}', PirateResource())


検索したらちょうどいいのを見つけた。
stackoverflow.com

global変数に一度作ったものを保存して、同じ名前があればそれを使いまわせばいいらしい。

これを参考に

loggers = {}


def oceanus_logging(name=None):
    global loggers
    if name is None:
        name = __name__

    if loggers.get(name):
        return loggers.get(name)

    LOG_LEVEL = environ['LOG_LEVEL']
    handler = logging.StreamHandler()
    formatter = logging.Formatter("name:{}"
                                  '%(asctime)s- '
                                  '%(levelname)s - '
                                  '%(message)s'.format(name))
    handler.setFormatter(formatter)
    logger = logging.getLogger(name)
    logger.setLevel(getattr(logging, LOG_LEVEL))
    handler.setLevel(getattr(logging, LOG_LEVEL))
    logger.addHandler(handler)
    loggers[name] = logger
    return logger

と変更した所重複出力はなくなった。

入門 Python 3

入門 Python 3