{ "info": { "author": "MyColorfulDays", "author_email": "my_colorful_days@163.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Utilities" ], "description": "# jsonformatter -- A formatter for python log json format\n\n**jsonformatter** is a json formatter for python log handler, you can use it easily output LogStash needed format or other custom json format.\n\njsonformatter requires Python 3.X.\n\n\n\n## Installation\n\njsonformatter is available on PyPI.\nUse pip to install:\n\n```shell\n$ pip install jsonformatter\n```\nor:\n\n```shell\n$ git clone https://github.com/MyColorfulDays/jsonformatter.git\n$ cd jsonformatter\n$ python setup.py install\n```\n\n## LogRecord Attributes \nOffical url: https://docs.python.org/3/library/logging.html#logrecord-attributes\n\nAttribute name|Format|Description\n-|-|-\nargs|You shouldn\u2019t need to format this yourself.|The tuple of arguments merged into msg to produce message, or a dict whose values are used for the merge (when there is only one argument, and it is a dictionary).\nasctime|%(asctime)s|Human-readable time when the LogRecord was created. By default this is of the form \u20182003-07-08 16:49:45,896\u2019 (the numbers after the comma are millisecond portion of the time).\ncreated|%(created)f|Time when the LogRecord was created (as returned by time.time()).\nexc_info|You shouldn\u2019t need to format this yourself.|Exception tuple (\u00e0 la sys.exc_info) or, if no exception has occurred, None.\nfilename|%(filename)s|Filename portion of pathname.\nfuncName|%(funcName)s|Name of function containing the logging call.\nlevelname|%(levelname)s|Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').\nlevelno|%(levelno)s|Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).\nlineno|%(lineno)d|Source line number where the logging call was issued (if available).\nmessage|%(message)s|The logged message, computed as msg % args. This is set when Formatter.format() is invoked.\nmodule|%(module)s|Module (name portion of filename).\nmsecs|%(msecs)d|Millisecond portion of the time when the LogRecord was created.\nmsg|You shouldn\u2019t need to format this yourself.|The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).\nname|%(name)s|Name of the logger used to log the call.\npathname|%(pathname)s|Full pathname of the source file where the logging call was issued (if available).\nprocess|%(process)d|Process ID (if available).\nprocessName|%(processName)s|Process name (if available).\nrelativeCreated|%(relativeCreated)d|Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.\nstack_info|You shouldn\u2019t need to format this yourself.|Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.\nthread|%(thread)d|Thread ID (if available).\nthreadName|%(threadName)s|Thread name (if available).\n\n## Basic Usage\n### Case 1. config in python code\n```python3\nimport logging\n\nfrom jsonformatter import JsonFormatter\n\n# format can be json string, OrderedDict, dict.\n# if format is dict and python version<3.7.0, the output order is same of sorted keys.\n# the key needn't same as attribute name, can be whatever you like.\n# the value can be `Attribute name` or `Format`(`Attribute name` will diplay `LogRecord.attribute`, `Format` will diplay `str(LogRecord.attribute)`).\nSTRING_FORMAT = '''{\n \"Name\": \"name\",\n \"Levelno\": \"levelno\",\n \"Levelname\": \"levelname\",\n \"Pathname\": \"pathname\",\n \"Filename\": \"filename\",\n \"Module\": \"module\",\n \"Lineno\": \"lineno\",\n \"FuncName\": \"funcName\",\n \"Created\": \"created\",\n \"Asctime\": \"asctime\",\n \"Msecs\": \"msecs\",\n \"RelativeCreated\": \"relativeCreated\",\n \"Thread\": \"thread\",\n \"ThreadName\": \"threadName\",\n \"Process\": \"process\",\n \"Message\": \"message\"\n}'''\n\n\n\nroot = logging.getLogger()\nroot.setLevel(logging.INFO)\n\nformatter = JsonFormatter(STRING_FORMAT)\n\nsh = logging.StreamHandler()\nsh.setFormatter(formatter)\nsh.setLevel(logging.INFO)\n\nroot.addHandler(sh)\n\nroot.info(\"test %s format\", 'string')\n```\n\n### Case 2. config from config file\nconfig file:\n```shell\n$ cat logger_config.ini\n[loggers]\nkeys=root\n\n[logger_root]\nlevel=DEBUG\nhandlers=infohandler\n\n\n###############################################\n\n[handlers]\nkeys=infohandler\n\n[handler_infohandler]\nclass=StreamHandler\nlevel=INFO\nformatter=form01\nargs=(sys.stdout,)\n\n###############################################\n\n[formatters]\nkeys=form01\n\n[formatter_form01]\nclass=jsonformatter.JsonFormatter\nformat={\"Name\": \"name\",\"Levelno\": \"levelno\",\"Levelname\": \"levelname\",\"Pathname\": \"pathname\",\"Filename\": \"filename\",\"Module\": \"module\",\"Lineno\": \"lineno\",\"FuncName\": \"funcName\",\"Created\": \"created\",\"Asctime\": \"asctime\",\"Msecs\": \"msecs\",\"RelativeCreated\": \"relativeCreated\",\"Thread\": \"thread\",\"ThreadName\": \"threadName\",\"Process\": \"process\",\"Message\": \"message\"}\n```\npython code:\n```python3\nimport logging\nimport os\nfrom logging.config import fileConfig\n\nfileConfig(os.path.join(os.path.dirname(__file__), 'logger_config.ini'))\nroot = logging.getLogger('root')\nroot.info('test file config')\n\n```\n\n## More Usage\n\n### Case 1. output multiple attributes in one key\n```python3\nimport logging\n\nfrom jsonformatter import JsonFormatter\n\nMULTI_ATTRIBUTES_FORMAT = '''{\n \"multi attributes in one key\": \"%(name)s - %(levelno)s - %(levelname)s - %(pathname)s - %(filename)s - %(module)s - %(lineno)d - %(funcName)s - %(created)f - %(asctime)s - %(msecs)d - %(relativeCreated)d - %(thread)d - %(threadName)s - %(process)d - %(message)s\"\n}\n'''\n\n\nroot = logging.getLogger()\nroot.setLevel(logging.INFO)\n\nformatter = JsonFormatter(MULTI_ATTRIBUTES_FORMAT)\n\nsh = logging.StreamHandler()\nsh.setFormatter(formatter)\n\nsh.setLevel(logging.INFO)\n\nroot.addHandler(sh)\nroot.info('test multi attributes in one key')\n```\n\n### Case 2. support `json.dumps` all optional parameters\n```python3\nimport logging\n\nfrom jsonformatter import JsonFormatter\n\nSTRING_FORMAT = '''{\n \"Name\": \"name\",\n \"Levelno\": \"levelno\",\n \"Levelname\": \"levelname\",\n \"Pathname\": \"pathname\",\n \"Filename\": \"filename\",\n \"Module\": \"module\",\n \"Lineno\": \"lineno\",\n \"FuncName\": \"funcName\",\n \"Created\": \"created\",\n \"Asctime\": \"asctime\",\n \"Msecs\": \"msecs\",\n \"RelativeCreated\": \"relativeCreated\",\n \"Thread\": \"thread\",\n \"ThreadName\": \"threadName\",\n \"Process\": \"process\",\n \"Message\": \"message\"\n}'''\n\nroot = logging.getLogger()\nroot.setLevel(logging.INFO)\n\n\nformatter = JsonFormatter(STRING_FORMAT, indent=4, ensure_ascii=False)\n\nsh = logging.StreamHandler()\nsh.setFormatter(formatter)\n\nsh.setLevel(logging.INFO)\n\nroot.addHandler(sh)\n\nroot.info('test json optional paramter: \u4e2d\u6587')\n```\n\n### Case 3. add/replace `LogRecord`'s attribute value\n```python3\nimport datetime\nimport json\nimport logging\nimport random\nfrom collections import OrderedDict\n\nfrom jsonformatter import JsonFormatter\n\n# the key will add/replace `LogRecord`'s attribute\n# the value must be `callable` type and not support paramters, it returned value will as the value of LogRecord's attribute\nRECORD_CUSTOM_ATTRS = {\n # datetime.datetime type is not JSON serializable.\n # solve it in three ways.\n # 1. use `Format` %(asctme)s.\n # 2. use `json.dumps` optional parameter `default`.\n # 3. use `json.dumps` optional parameter `cls`.\n 'asctime': lambda: datetime.datetime.today(),\n 'user id': lambda: str(random.random())[2:10]\n}\n\nRECORD_CUSTOM_FORMAT = OrderedDict([\n (\"User id\", \"user id\"), # new custom attrs\n (\"Name\", \"name\"),\n (\"Levelno\", \"levelno\"),\n (\"Levelname\", \"levelname\"),\n (\"Pathname\", \"pathname\"),\n (\"Filename\", \"filename\"),\n (\"Module\", \"module\"),\n (\"Lineno\", \"lineno\"),\n (\"FuncName\", \"funcName\"),\n (\"Created\", \"created\"),\n (\"Asctime\", \"%(asctime)s\"), # use `Format` to convert returned value to string.\n (\"Msecs\", \"msecs\"),\n (\"RelativeCreated\", \"relativeCreated\"),\n (\"Thread\", \"thread\"),\n (\"ThreadName\", \"threadName\"),\n (\"Process\", \"process\"),\n (\"Message\", \"message\")\n])\n\n\ndef DEFAULT_SOLUTION(o):\n if not isinstance(o,(str, int, float, bool, type(None))):\n return str(o)\n else:\n return o\n\nclass CLS_SOLUTION(json.JSONEncoder):\n def default(self, o):\n if isinstance(o, datetime.datetime):\n return o.isoformat()\n\n return json.JSONEncoder.default(self, o)\n\nroot = logging.getLogger()\nroot.setLevel(logging.INFO)\n\nformatter = JsonFormatter(RECORD_CUSTOM_FORMAT, record_custom_attrs=RECORD_CUSTOM_ATTRS, default=DEFAULT_SOLUTION, cls=CLS_SOLUTION)\n\nsh = logging.StreamHandler()\nsh.setFormatter(formatter)\n\nsh.setLevel(logging.INFO)\n\nroot.addHandler(sh)\nroot.info('record custom attrs')\n```", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/MyColorfulDays/jsonformatter.git", "keywords": "", "license": "BSD License", "maintainer": "", "maintainer_email": "", "name": "jsonformatter", "package_url": "https://pypi.org/project/jsonformatter/", "platform": "all", "project_url": "https://pypi.org/project/jsonformatter/", "project_urls": { "Homepage": "https://github.com/MyColorfulDays/jsonformatter.git" }, "release_url": "https://pypi.org/project/jsonformatter/0.1.3/", "requires_dist": null, "requires_python": ">=3", "summary": "Python log in json format.", "version": "0.1.3" }, "last_serial": 5949004, "releases": { "0.1.2": [ { "comment_text": "", "digests": { "md5": "858c339c63727412a0ff97bb005da9ad", "sha256": "f89b700adc258586b09b34b302fc00a374920f31cf8dea37ff96f204fa42822b" }, "downloads": -1, "filename": "jsonformatter-0.1.2.tar.gz", "has_sig": false, "md5_digest": "858c339c63727412a0ff97bb005da9ad", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 8466, "upload_time": "2019-07-10T19:03:09", "url": "https://files.pythonhosted.org/packages/0d/9d/bf0affacc2e1907ed164e19d0c6eb7260b489ca8be86dd5f58ab9d2a1fe2/jsonformatter-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "44aaf9ed3b74c2e29cee99b570ac9efc", "sha256": "bbe056cdae9a7e608bca72e8613fc04dae262bcf4596f78762522694ee96c11b" }, "downloads": -1, "filename": "jsonformatter-0.1.3.tar.gz", "has_sig": false, "md5_digest": "44aaf9ed3b74c2e29cee99b570ac9efc", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 9327, "upload_time": "2019-10-09T10:29:50", "url": "https://files.pythonhosted.org/packages/99/b4/0ecf9a4c5c89c751d4f35bd7b9484df048457fed4b664c45ebdc4680e19d/jsonformatter-0.1.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "44aaf9ed3b74c2e29cee99b570ac9efc", "sha256": "bbe056cdae9a7e608bca72e8613fc04dae262bcf4596f78762522694ee96c11b" }, "downloads": -1, "filename": "jsonformatter-0.1.3.tar.gz", "has_sig": false, "md5_digest": "44aaf9ed3b74c2e29cee99b570ac9efc", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 9327, "upload_time": "2019-10-09T10:29:50", "url": "https://files.pythonhosted.org/packages/99/b4/0ecf9a4c5c89c751d4f35bd7b9484df048457fed4b664c45ebdc4680e19d/jsonformatter-0.1.3.tar.gz" } ] }