logging

  • 파이썬을 처음 배울 땐, 로그를 print문으로 남겼지만(이 당시에 이게 로그 개념인지도 몰랐음) 점점 서비스나 어플리케이션이 커지면 남기는 로그가 많아지고 관리도 어려워집니다
  • 이를 위해 로그 관련 라이브러리들이 만들어졌습니다. 대표적으로 파이썬 내장 모듈인 logging이 있습니다
  • 용도
    • 현재 상태보기
    • 버그 추적
    • 로그 분석(빈도 확인)

로그 생성하기


In [5]:
import logging
import time

In [2]:
logging.basicConfig(level=logging.DEBUG)

In [3]:
logger = logging.getLogger("test")

log level

  • DEBUG : 상세한 정보가 필요시, 보통 디버깅이나 문제 분석시 사용
  • INFO : 동작이 절차에 따라 진행되고 있는지 관찰할 때 사용
  • WARNING : 어떤 문제가 조만간 발생할 조짐이 있을 경우 사용(디스크 용량 부족)
  • ERROR : 프로그램에 문제가 발생해 기능 일부가 동작하지 않을 경우
  • CRITICAL : 심각한 문제가 발생해 시스템이 정상적으로 동작할 수 없을 경우

In [4]:
logger.debug("debug message")


DEBUG:test:debug message

In [8]:
logger.info("info message {a}".format(a=1))


INFO:test:info message 1

In [9]:
logger.warning("Warn message")


WARNING:test:Warn message

In [16]:
logger.error("error message")


ERROR:test:error message

In [17]:
logger.critical("critical!!!!")


CRITICAL:test:critical!!!!

In [18]:
dir(logger)


Out[18]:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_log',
 'addFilter',
 'addHandler',
 'callHandlers',
 'critical',
 'debug',
 'disabled',
 'error',
 'exception',
 'fatal',
 'filter',
 'filters',
 'findCaller',
 'getChild',
 'getEffectiveLevel',
 'handle',
 'handlers',
 'hasHandlers',
 'info',
 'isEnabledFor',
 'level',
 'log',
 'makeRecord',
 'manager',
 'name',
 'parent',
 'propagate',
 'removeFilter',
 'removeHandler',
 'root',
 'setLevel',
 'warn',
 'warning']

로그 생성 시간 추가하고 싶은 경우


In [40]:
mylogger = logging.getLogger("my")
mylogger.setLevel(logging.INFO)

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

In [41]:
stream_hander = logging.StreamHandler()
stream_hander.setFormatter(formatter)
mylogger.addHandler(stream_hander)

file_handler = logging.FileHandler('my.log')
mylogger.addHandler(file_handler)

mylogger.info("server start")


2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
1531669787.298816 - my - INFO - server start
1531669787.298816 - my - INFO - server start
1531669787.298816 - my - INFO - server start
1531669787.298816 - my - INFO - server start
2018-07-16 00:49:47,298 - my - INFO - server start
INFO:my:server start

로그 저장


In [42]:
logging.basicConfig(filename="test.log", 
                    filemode='a',
                    level=logging.DEBUG)

init


In [1]:
import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

In [2]:
def init():
    parser = optparse.OptionParser()
    parser.add_option('-l', '--logging-level', help='Logging level')
    parser.add_option('-f', '--logging-file', help='Logging file name')
    (options, args) = parser.parse_args()
    logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
    logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

In [4]:
logging.debug("디버깅용 로그~~")
logging.info("도움이 되는 정보를 남겨요~")
logging.warning("주의해야되는곳!")
logging.error("에러!!!")
logging.critical("심각한 에러!!")


WARNING:root:주의해야되는곳!
ERROR:root:에러!!!
CRITICAL:root:심각한 에러!!

In [ ]:


In [5]:
import logging

import logging.handlers

 

# 로거 인스턴스를 만든다

logger = logging.getLogger('mylogger')

 

# 포매터를 만든다

fomatter = logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s > %(message)s')

 

# 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.

fileHandler = logging.FileHandler('./myLoggerTest.log')

streamHandler = logging.StreamHandler()

 

# 각 핸들러에 포매터를 지정한다.

fileHandler.setFormatter(fomatter)

streamHandler.setFormatter(fomatter)

 

# 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.

logger.addHandler(fileHandler)

logger.addHandler(streamHandler)

 

# 로거 인스턴스로 로그를 찍는다.

logger.setLevel(logging.DEBUG)

logger.debug("===========================")

logger.info("TEST START")

logger.warning("스트림으로 로그가 남아요~")

logger.error("파일로도 남으니 안심이죠~!")

logger.critical("치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!")

logger.debug("===========================")

logger.info("TEST END!")


[DEBUG|<ipython-input-5-eba3c52bdc19>:47] 2018-07-19 00:14:45,243 > ===========================
DEBUG:mylogger:===========================
[INFO|<ipython-input-5-eba3c52bdc19>:49] 2018-07-19 00:14:45,246 > TEST START
INFO:mylogger:TEST START
[WARNING|<ipython-input-5-eba3c52bdc19>:51] 2018-07-19 00:14:45,248 > 스트림으로 로그가 남아요~
WARNING:mylogger:스트림으로 로그가 남아요~
[ERROR|<ipython-input-5-eba3c52bdc19>:53] 2018-07-19 00:14:45,249 > 파일로도 남으니 안심이죠~!
ERROR:mylogger:파일로도 남으니 안심이죠~!
[CRITICAL|<ipython-input-5-eba3c52bdc19>:55] 2018-07-19 00:14:45,250 > 치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!
CRITICAL:mylogger:치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!
[DEBUG|<ipython-input-5-eba3c52bdc19>:57] 2018-07-19 00:14:45,252 > ===========================
DEBUG:mylogger:===========================
[INFO|<ipython-input-5-eba3c52bdc19>:59] 2018-07-19 00:14:45,254 > TEST END!
INFO:mylogger:TEST END!

In [ ]: