본문 바로가기

web/Django

EFK docker + django logger 커스텀

EFK의 설치는 아래의 포스팅을 참조했습니다. 

https://lng1982.tistory.com/281

 

EFK Stack 구축 using Docker compose

Elasticsearch + Fluentd + Kibana 조합을 EFK Stack이라 부른다. 참고로 Elasticsearch + logstash + Kibana 조합은 ELK Stack 이다. Fluentd : 오픈소스 log collector Elasticsearch : Lucene 기반 분산 검색..

lng1982.tistory.com

위의 포스팅을 잘 따라 했다면 kibana에서 로그를 볼수 있는 화면이 나온다. 

그러면 실제 django의 logger를 전송해보자.

 

1. django-fluentd 패키지 설치 

$ pip install django-fluentd

or

git clone https://github.com/jayfk/django-fluentd.git
cd django-fluentd
python setup.py install

2. settings에 logger 설정 추가 

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': {
        'fluent_formatter': {
            '()': 'fluent.handler.FluentRecordFormatter',
            'format': {
                'level': '%(levelname)s',
                'module': '%(name)s',
                'message': '%(message)s',
                'time': '%(asctime)s',
                'file': '%(filename)s',
                'line': '%(lineno)d',
            },
            'datefmt': '%Y-%m-%d %H:%M:%S',
        }
    },
    'handlers': {
        'fluent': {
            'level': 'INFO',
            'class': 'fluent_support.DjangoFluentHandler',
            'tag': 'app.log',
            'host': 'localhost',
            'port': 24224,
            'formatter': 'fluent_formatter'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['fluent'],
            'propagate': False,
            'level': 'INFO',
        },
    }
}

formatters은 로그의 포멧을 지정합니다. 

handlers은 사용할 로그 패키지와, 어떠한 포멧으로 할지 지정합니다. 

loggers은 지정한 app / 프로젝트를 지정하며('', django로 설정하면 프로젝트 전체가 됩니다. ),

           사용할 handler, 로그의 레벨을 지정합니다. 

즉  loggers에서 INFO로그로 핸들러를 'fluent'로 지정했으며, 핸들러에서는  fluent에서 포멧을 'fluent_formatter'로 지정했으며, fluent_support로 설정했습니다. 

 

 

3. fluent_support.py 파일 추가 (프로젝트 최상위에 추가 해주세요.)

# coding: utf-8
import json
import logging
import socket

from fluent import sender


class DjangoFluentHandler(logging.Handler):
    def __init__(
            self, tag, host='localhost', port=24224, timeout=3.0,
            verbose=True):
        logging.Handler.__init__(self)
        self.tag = tag
        self.sender = sender.FluentSender(tag,
                                          host=host, port=port,
                                          timeout=timeout, verbose=verbose)
        self.hostname = socket.gethostname()

    def emit(self, record):
        if record.levelno < self.level:
            return
        msg = self.format(record)
        data = {
            'host': self.hostname,
            'name': record.name,
            'levelname': record.levelname,
            'process': record.process,
            'message': json.dumps(msg),
        }
        self.sender.emit(None, data)

    def _close(self):
        self.sender._close()

django logger는 emit의 함수가 호출되는데 결국 data를 fluentd로 전송하게 됩니다. 이제 data에 필요한 부분만 넣어주시면 마음껏 커스텀이 됩니다. 

 

서버를 실행하고, 페이지를 출력 해보면 kibana에서 로그를 확인을 할 수 있습니다!!

 

 

 

참조

https://tokibito.hatenablog.com/entry/20131203/1386006672

 

Djangoのログ出力をFluentdで集める - 偏った言語信者の垂れ流し

Djangoのログ出力をFluentdで集める方法について。 ログレベルがERRORやWARNINGのものはSentryを使うのが便利だと思うけど、それ以外のINFOやDEBUGはSentryに入れるには数が多すぎるのでどうするか考えてて、最初はローカルのファイルに書き出していた。 けどまあ複数のサーバーにログファイルがあるとやっぱり不便だったので、Fluentdを使って一箇所に集めることにした。 簡単にできるかなーと思ってたんだけど、fluent-logger-pythonのlogging用のハンドラのイ

tokibito.hatenablog.com