Skip to content

Commit 3ef0f5d

Browse files
python2.7 is supported
1 parent c6af8e1 commit 3ef0f5d

File tree

4 files changed

+405
-177
lines changed

4 files changed

+405
-177
lines changed

README.md

Lines changed: 119 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
1-
# jsonformatter -- A formatter for python log json format
1+
Table of Contents
2+
=================
23

3-
**jsonformatter** is a json formatter for python log handler, you can use it easily output LogStash needed format or other custom json format.
4+
* [jsonformatter \-\- for python log json](#jsonformatter----for-python-log-json)
5+
* [Installation](#installation)
6+
* [Basic Usage](#basic-usage)
7+
* [Case 1\. Use default config](#case-1-use-default-config)
8+
* [Case 2\. config in python code](#case-2-config-in-python-code)
9+
* [Case 3\. config from config file](#case-3-config-from-config-file)
10+
* [More Usage](#more-usage)
11+
* [Case 1\. output multiple attributes in one key](#case-1-output-multiple-attributes-in-one-key)
12+
* [Case 2\. support json\.dumps all optional parameters](#case-2-support-jsondumps-all-optional-parameters)
13+
* [Case 3\. support cumtom(add/replace) LogRecord attribute](#case-3-support-cumtomaddreplace-logrecord--attribute)
14+
* [LogRecord Attributes](#logrecord-attributes)
415

5-
jsonformatter requires Python 3.X.
16+
17+
18+
# jsonformatter -- for python log json
19+
20+
**jsonformatter** is a formatter for python output json log, you can easily output **LogStash** needed log format or other **custom** json format and you can easily **custom(add/replace)** `LogRecord` attribute.
21+
22+
**Python 2.7** and **python 3** are supported from version 0.2.0, if you are using a version lower than 0.2.0, **python 3** is only supported.
623

724

825

@@ -22,44 +39,50 @@ $ cd jsonformatter
2239
$ python setup.py install
2340
```
2441

25-
## LogRecord Attributes
26-
Offical url: https://docs.python.org/3/library/logging.html#logrecord-attributes
2742

28-
Attribute name|Format|Description
29-
-|-|-
30-
args|You shouldn’t 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).
31-
asctime|%(asctime)s|Human-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
32-
created|%(created)f|Time when the LogRecord was created (as returned by time.time()).
33-
exc_info|You shouldn’t need to format this yourself.|Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
34-
filename|%(filename)s|Filename portion of pathname.
35-
funcName|%(funcName)s|Name of function containing the logging call.
36-
levelname|%(levelname)s|Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
37-
levelno|%(levelno)s|Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
38-
lineno|%(lineno)d|Source line number where the logging call was issued (if available).
39-
message|%(message)s|The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
40-
module|%(module)s|Module (name portion of filename).
41-
msecs|%(msecs)d|Millisecond portion of the time when the LogRecord was created.
42-
msg|You shouldn’t 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).
43-
name|%(name)s|Name of the logger used to log the call.
44-
pathname|%(pathname)s|Full pathname of the source file where the logging call was issued (if available).
45-
process|%(process)d|Process ID (if available).
46-
processName|%(processName)s|Process name (if available).
47-
relativeCreated|%(relativeCreated)d|Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
48-
stack_info|You shouldn’t 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.
49-
thread|%(thread)d|Thread ID (if available).
50-
threadName|%(threadName)s|Thread name (if available).
5143

5244
## Basic Usage
53-
### Case 1. config in python code
45+
46+
### Case 1. Use default config
47+
48+
```python
49+
import logging
50+
51+
from jsonformatter import JsonFormatter
52+
53+
root = logging.getLogger()
54+
root.setLevel(logging.INFO)
55+
56+
formatter = JsonFormatter()
57+
58+
sh = logging.StreamHandler()
59+
sh.setFormatter(formatter)
60+
sh.setLevel(logging.INFO)
61+
62+
root.addHandler(sh)
63+
64+
root.info("test %s config", 'default')
65+
```
66+
67+
output:
68+
69+
```shell
70+
{"levelname": "INFO", "name": "root", "message": "test default config"}
71+
```
72+
73+
74+
75+
### Case 2. config in python code
76+
5477
```python3
5578
import logging
5679

5780
from jsonformatter import JsonFormatter
5881

59-
# format can be json string, OrderedDict, dict.
60-
# if format is dict and python version<3.7.0, the output order is same of sorted keys.
61-
# the key needn't same as attribute name, can be whatever you like.
62-
# the value can be `Attribute name` or `Format`(`Attribute name` will diplay `LogRecord.attribute`, `Format` will diplay `str(LogRecord.attribute)`).
82+
# `format` can be json, OrderedDict, dict.
83+
# If `format` is `dict` and python version<3.7.0, the output ordered is sorted keys, otherwise will same as define ordered.
84+
# key: string, can be whatever you like.
85+
# value: `LogRecord` attribute name.
6386
STRING_FORMAT = '''{
6487
"Name": "name",
6588
"Levelno": "levelno",
@@ -79,8 +102,6 @@ STRING_FORMAT = '''{
79102
"Message": "message"
80103
}'''
81104

82-
83-
84105
root = logging.getLogger()
85106
root.setLevel(logging.INFO)
86107

@@ -95,7 +116,16 @@ root.addHandler(sh)
95116
root.info("test %s format", 'string')
96117
```
97118

98-
### Case 2. config from config file
119+
output:
120+
121+
```shell
122+
{"Name": "root", "Levelno": 20, "Levelname": "INFO", "Pathname": "test.py", "Filename": "test.py", "Module": "test", "Lineno": 75, "FuncName": "test_string_format", "Created": 1588185267.3198836, "Asctime": "2020-04-30 02:34:27,319", "Msecs": 319.8835849761963, "RelativeCreated": 88.2880687713623, "Thread": 16468, "ThreadName": "MainThread", "Process": 16828, "Message": "test string format"}
123+
```
124+
125+
126+
127+
### Case 3. config from config file
128+
99129
config file:
100130
```shell
101131
$ cat logger_config.ini
@@ -125,7 +155,7 @@ keys=form01
125155

126156
[formatter_form01]
127157
class=jsonformatter.JsonFormatter
128-
format={"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"}
158+
format={"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"}
129159
```
130160
python code:
131161
```python3
@@ -139,6 +169,14 @@ root.info('test file config')
139169

140170
```
141171

172+
output:
173+
174+
```shell
175+
{"name": "root", "levelno": 20, "levelname": "INFO", "pathname": "test.py", "filename": "test.py", "module": "test", "lineno": 315, "funcName": "test_file_config", "created": 1588185267.3020294, "asctime": "2020-04-30 02:34:27", "msecs": 302.0293712615967, "relativeCreated": 70.4338550567627, "thread": 16468, "threadName": "MainThread", "process": 16828, "message": "test file config"}
176+
```
177+
178+
179+
142180
## More Usage
143181

144182
### Case 1. output multiple attributes in one key
@@ -167,7 +205,10 @@ root.addHandler(sh)
167205
root.info('test multi attributes in one key')
168206
```
169207

208+
209+
170210
### Case 2. support `json.dumps` all optional parameters
211+
171212
```python3
172213
import logging
173214

@@ -208,7 +249,10 @@ root.addHandler(sh)
208249
root.info('test json optional paramter: 中文')
209250
```
210251

211-
### Case 3. add/replace `LogRecord`'s attribute value
252+
253+
254+
### Case 3. support cumtom(add/replace) `LogRecord` attribute
255+
212256
```python3
213257
import datetime
214258
import json
@@ -218,12 +262,12 @@ from collections import OrderedDict
218262

219263
from jsonformatter import JsonFormatter
220264

221-
# the key will add/replace `LogRecord`'s attribute
222-
# the value must be `callable` type and not support paramters, it returned value will as the value of LogRecord's attribute
265+
# the key will add/replace `LogRecord` attribute.
266+
# the value must be `callable` type and not support paramters, the returned value will be as the `LogRecord` attribute value.
223267
RECORD_CUSTOM_ATTRS = {
224-
# datetime.datetime type is not JSON serializable.
268+
# `datetime.datetime` type is not JSON serializable.
225269
# solve it in three ways.
226-
# 1. use `Format` %(asctme)s.
270+
# 1. use `LogRecord` attribute `Format`: %(asctme)s.
227271
# 2. use `json.dumps` optional parameter `default`.
228272
# 3. use `json.dumps` optional parameter `cls`.
229273
'asctime': lambda: datetime.datetime.today(),
@@ -241,7 +285,7 @@ RECORD_CUSTOM_FORMAT = OrderedDict([
241285
("Lineno", "lineno"),
242286
("FuncName", "funcName"),
243287
("Created", "created"),
244-
("Asctime", "%(asctime)s"), # use `Format` to convert returned value to string.
288+
("Asctime", "%(asctime)s"), # use `LogRecord` attribute `Format` to find matched key from RECORD_CUSTOM_ATTRS and call it value.
245289
("Msecs", "msecs"),
246290
("RelativeCreated", "relativeCreated"),
247291
("Thread", "thread"),
@@ -251,12 +295,14 @@ RECORD_CUSTOM_FORMAT = OrderedDict([
251295
])
252296

253297

298+
# use `json.dumps` optional parameter `default`
254299
def DEFAULT_SOLUTION(o):
255-
if not isinstance(o,(str, int, float, bool, type(None))):
300+
if not isinstance(o, (str, int, float, bool, type(None))):
256301
return str(o)
257302
else:
258303
return o
259304

305+
# use `json.dumps` optional parameter `cls`
260306
class CLS_SOLUTION(json.JSONEncoder):
261307
def default(self, o):
262308
if isinstance(o, datetime.datetime):
@@ -278,3 +324,32 @@ root.addHandler(sh)
278324
root.info('record custom attrs')
279325
```
280326

327+
328+
329+
## LogRecord Attributes
330+
331+
Offical url: https://docs.python.org/3/library/logging.html#logrecord-attributes
332+
333+
Attribute name|Format|Description
334+
-|-|-
335+
args|You shouldn’t 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).
336+
asctime|%(asctime)s|Human-readable time when the LogRecord was created. By default this is of the form ‘2003-07-08 16:49:45,896’ (the numbers after the comma are millisecond portion of the time).
337+
created|%(created)f|Time when the LogRecord was created (as returned by time.time()).
338+
exc_info|You shouldn’t need to format this yourself.|Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
339+
filename|%(filename)s|Filename portion of pathname.
340+
funcName|%(funcName)s|Name of function containing the logging call.
341+
levelname|%(levelname)s|Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
342+
levelno|%(levelno)s|Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL).
343+
lineno|%(lineno)d|Source line number where the logging call was issued (if available).
344+
message|%(message)s|The logged message, computed as msg % args. This is set when Formatter.format() is invoked.
345+
module|%(module)s|Module (name portion of filename).
346+
msecs|%(msecs)d|Millisecond portion of the time when the LogRecord was created.
347+
msg|You shouldn’t 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).
348+
name|%(name)s|Name of the logger used to log the call.
349+
pathname|%(pathname)s|Full pathname of the source file where the logging call was issued (if available).
350+
process|%(process)d|Process ID (if available).
351+
processName|%(processName)s|Process name (if available).
352+
relativeCreated|%(relativeCreated)d|Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
353+
stack_info|You shouldn’t 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.
354+
thread|%(thread)d|Thread ID (if available).
355+
threadName|%(threadName)s|Thread name (if available).

0 commit comments

Comments
 (0)