{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# logging" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- 파이썬을 처음 배울 땐, 로그를 print문으로 남겼지만(이 당시에 이게 로그 개념인지도 몰랐음) 점점 서비스나 어플리케이션이 커지면 남기는 로그가 많아지고 관리도 어려워집니다\n", "- 이를 위해 로그 관련 라이브러리들이 만들어졌습니다. 대표적으로 파이썬 내장 모듈인 logging이 있습니다\n", "- 용도\n", " - 현재 상태보기\n", " - 버그 추적\n", " - 로그 분석(빈도 확인)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 로그 생성하기" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import logging\n", "import time" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "logging.basicConfig(level=logging.DEBUG)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "logger = logging.getLogger(\"test\") " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### log level\n", "- DEBUG : 상세한 정보가 필요시, 보통 디버깅이나 문제 분석시 사용\n", "- INFO : 동작이 절차에 따라 진행되고 있는지 관찰할 때 사용\n", "- WARNING : 어떤 문제가 조만간 발생할 조짐이 있을 경우 사용(디스크 용량 부족)\n", "- ERROR : 프로그램에 문제가 발생해 기능 일부가 동작하지 않을 경우\n", "- CRITICAL : 심각한 문제가 발생해 시스템이 정상적으로 동작할 수 없을 경우" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "DEBUG:test:debug message\n" ] } ], "source": [ "logger.debug(\"debug message\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:test:info message 1\n" ] } ], "source": [ "logger.info(\"info message {a}\".format(a=1))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:test:Warn message\n" ] } ], "source": [ "logger.warning(\"Warn message\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "ERROR:test:error message\n" ] } ], "source": [ "logger.error(\"error message\")" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "CRITICAL:test:critical!!!!\n" ] } ], "source": [ "logger.critical(\"critical!!!!\")" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__init_subclass__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " '_log',\n", " 'addFilter',\n", " 'addHandler',\n", " 'callHandlers',\n", " 'critical',\n", " 'debug',\n", " 'disabled',\n", " 'error',\n", " 'exception',\n", " 'fatal',\n", " 'filter',\n", " 'filters',\n", " 'findCaller',\n", " 'getChild',\n", " 'getEffectiveLevel',\n", " 'handle',\n", " 'handlers',\n", " 'hasHandlers',\n", " 'info',\n", " 'isEnabledFor',\n", " 'level',\n", " 'log',\n", " 'makeRecord',\n", " 'manager',\n", " 'name',\n", " 'parent',\n", " 'propagate',\n", " 'removeFilter',\n", " 'removeHandler',\n", " 'root',\n", " 'setLevel',\n", " 'warn',\n", " 'warning']" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(logger)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 로그 생성 시간 추가하고 싶은 경우" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "mylogger = logging.getLogger(\"my\")\n", "mylogger.setLevel(logging.INFO)\n", "\n", "formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "1531669787.298816 - my - INFO - server start\n", "1531669787.298816 - my - INFO - server start\n", "1531669787.298816 - my - INFO - server start\n", "1531669787.298816 - my - INFO - server start\n", "2018-07-16 00:49:47,298 - my - INFO - server start\n", "INFO:my:server start\n" ] } ], "source": [ "stream_hander = logging.StreamHandler()\n", "stream_hander.setFormatter(formatter)\n", "mylogger.addHandler(stream_hander)\n", "\n", "file_handler = logging.FileHandler('my.log')\n", "mylogger.addHandler(file_handler)\n", "\n", "mylogger.info(\"server start\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 로그 저장" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "logging.basicConfig(filename=\"test.log\", \n", " filemode='a',\n", " level=logging.DEBUG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# init" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import logging\n", "import optparse\n", "\n", "LOGGING_LEVELS = {'critical': logging.CRITICAL,\n", " 'error': logging.ERROR,\n", " 'warning': logging.WARNING,\n", " 'info': logging.INFO,\n", " 'debug': logging.DEBUG}\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def init():\n", " parser = optparse.OptionParser()\n", " parser.add_option('-l', '--logging-level', help='Logging level')\n", " parser.add_option('-f', '--logging-file', help='Logging file name')\n", " (options, args) = parser.parse_args()\n", " logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)\n", " logging.basicConfig(level=logging_level, filename=options.logging_file,\n", " format='%(asctime)s %(levelname)s: %(message)s',\n", " datefmt='%Y-%m-%d %H:%M:%S')" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING:root:주의해야되는곳!\n", "ERROR:root:에러!!!\n", "CRITICAL:root:심각한 에러!!\n" ] } ], "source": [ "logging.debug(\"디버깅용 로그~~\")\n", "logging.info(\"도움이 되는 정보를 남겨요~\")\n", "logging.warning(\"주의해야되는곳!\")\n", "logging.error(\"에러!!!\")\n", "logging.critical(\"심각한 에러!!\")\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[DEBUG|:47] 2018-07-19 00:14:45,243 > ===========================\n", "DEBUG:mylogger:===========================\n", "[INFO|:49] 2018-07-19 00:14:45,246 > TEST START\n", "INFO:mylogger:TEST START\n", "[WARNING|:51] 2018-07-19 00:14:45,248 > 스트림으로 로그가 남아요~\n", "WARNING:mylogger:스트림으로 로그가 남아요~\n", "[ERROR|:53] 2018-07-19 00:14:45,249 > 파일로도 남으니 안심이죠~!\n", "ERROR:mylogger:파일로도 남으니 안심이죠~!\n", "[CRITICAL|:55] 2018-07-19 00:14:45,250 > 치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!\n", "CRITICAL:mylogger:치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!\n", "[DEBUG|:57] 2018-07-19 00:14:45,252 > ===========================\n", "DEBUG:mylogger:===========================\n", "[INFO|:59] 2018-07-19 00:14:45,254 > TEST END!\n", "INFO:mylogger:TEST END!\n" ] } ], "source": [ "import logging\n", "\n", "import logging.handlers\n", "\n", " \n", "\n", "# 로거 인스턴스를 만든다\n", "\n", "logger = logging.getLogger('mylogger')\n", "\n", " \n", "\n", "# 포매터를 만든다\n", "\n", "fomatter = logging.Formatter('[%(levelname)s|%(filename)s:%(lineno)s] %(asctime)s > %(message)s')\n", "\n", " \n", "\n", "# 스트림과 파일로 로그를 출력하는 핸들러를 각각 만든다.\n", "\n", "fileHandler = logging.FileHandler('./myLoggerTest.log')\n", "\n", "streamHandler = logging.StreamHandler()\n", "\n", " \n", "\n", "# 각 핸들러에 포매터를 지정한다.\n", "\n", "fileHandler.setFormatter(fomatter)\n", "\n", "streamHandler.setFormatter(fomatter)\n", "\n", " \n", "\n", "# 로거 인스턴스에 스트림 핸들러와 파일핸들러를 붙인다.\n", "\n", "logger.addHandler(fileHandler)\n", "\n", "logger.addHandler(streamHandler)\n", "\n", " \n", "\n", "# 로거 인스턴스로 로그를 찍는다.\n", "\n", "logger.setLevel(logging.DEBUG)\n", "\n", "logger.debug(\"===========================\")\n", "\n", "logger.info(\"TEST START\")\n", "\n", "logger.warning(\"스트림으로 로그가 남아요~\")\n", "\n", "logger.error(\"파일로도 남으니 안심이죠~!\")\n", "\n", "logger.critical(\"치명적인 버그는 꼭 파일로 남기기도 하고 메일로 발송하세요!\")\n", "\n", "logger.debug(\"===========================\")\n", "\n", "logger.info(\"TEST END!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.5" }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }