본문 바로가기

개발/Python & Flask

Python logging 에 원하는 값 찍기 (inject variable to logging)

로그에 커스텀값을 출력할 때,

보통 loggerAdapter를 사용한다.

 

근데 이 방법을 사용하면, 예약된 이름에 원하는 변수를 출력할 수 없다.

'myfavoritemovie' = 'realsteel' 과 같은 출력은 가능하지만,

'ip' = '123.123.123.123' 과 같은 코드는 "trying to overwrite exist name" 뭐시기 같은 오류가 난다.

 

여기서 문제 :

원래 ip를 출력하면 서버의 ip가 나오는데, 그때 그때 클라이언트의 ip를 출력하고 싶다면?

 

계속 고민하다가

신입개발자의 짧은 생각으로 편법을 만들어냈으니...

 

#logSetter.py

import logging
import logging.handlers


client_ip = ''

class ContextFilter(logging.Filter):
    def filter(self, record):
        record.ip = getIP()

def getIP():
    global client_ip
    output = client_ip
    client_ip = ''
    return output
    
def setIP(request):
    global client_ip
    client_ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr)
    
    
mylogger = logging.getLogger('my')

contextFilter = ContextFilter()
mylogger.addFilter(contextFilter)

formatter = logging.Formatter(' [%(asctime)s - %(ip)s] [%(message)s] ')

streamHandler = logging.StreamHandler()
streamHandler.setFormatter(formatter)
mylogger.addHandler(streamHandler)

ContextFilter와 그 밑에 filter는 아무리해도 parameter가 들어가지 않는다.

client_ip 를 전역변수로 두고 ip값을 담아 옮기는 것이 핵심이다.

 

 

 

사용법:

이 파일의 이름을 logSetter.py 라고 했을 때,

외부 py파일에서 사용하는 방법은 아래와 같다.

import logSetter
from logSetter import mylogger
from flask import request



@app.route('/')
def index():
    logSetter.setIP(request)
    mylogger.info('whats up!!')
    return "hello world"

저렇게 request 들어온 것을 넘기면,

request 속에서 ip 를 뽑아서 전역변수에 넣어주고,

로그 속 contextFilter에서 전역변수 ip를 뽑아서 출력하고,

초기화 시켜놓는다.

 

사실 getIP 함수는 없어도 된다. 그냥 초기화용.

 

나 스스로도 편법이라고 생각되어서 그리 추천하고 싶진 않지만..

이런 방법도 할 수 있구나 라고 참고만 하시길

 

반응형