Skip to content

Commit ce74fc8

Browse files
author
thang
committed
update documentation
1 parent 43fc308 commit ce74fc8

File tree

3 files changed

+227
-19
lines changed

3 files changed

+227
-19
lines changed

.gitignore

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Python template
3+
# Byte-compiled / optimized / DLL files
4+
__pycache__/
5+
*.py[cod]
6+
*$py.class
7+
8+
# C extensions
9+
*.so
10+
11+
# Distribution / packaging
12+
.Python
13+
build/
14+
develop-eggs/
15+
dist/
16+
downloads/
17+
eggs/
18+
.eggs/
19+
lib/
20+
lib64/
21+
parts/
22+
sdist/
23+
var/
24+
wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.coverage
44+
.coverage.*
45+
.cache
46+
nosetests.xml
47+
coverage.xml
48+
*.cover
49+
.hypothesis/
50+
51+
# Translations
52+
*.mo
53+
*.pot
54+
55+
# Django stuff:
56+
*.log
57+
.static_storage/
58+
.media/
59+
local_settings.py
60+
61+
# Flask stuff:
62+
instance/
63+
.webassets-cache
64+
65+
# Scrapy stuff:
66+
.scrapy
67+
68+
# Sphinx documentation
69+
docs/_build/
70+
71+
# PyBuilder
72+
target/
73+
74+
# Jupyter Notebook
75+
.ipynb_checkpoints
76+
77+
# pyenv
78+
.python-version
79+
80+
# celery beat schedule file
81+
celerybeat-schedule
82+
83+
# SageMath parsed files
84+
*.sage.py
85+
86+
# Environments
87+
.env
88+
.venv
89+
env/
90+
venv/
91+
ENV/
92+
env.bak/
93+
venv.bak/
94+
95+
# Spyder project settings
96+
.spyderproject
97+
.spyproject
98+
99+
# Rope project settings
100+
.ropeproject
101+
102+
# mkdocs documentation
103+
/site
104+
105+
# mypy
106+
.mypy_cache/
107+
### JetBrains template
108+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
109+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
110+
111+
# User-specific stuff:
112+
.idea/**/workspace.xml
113+
.idea/**/tasks.xml
114+
.idea/dictionaries
115+
116+
# Sensitive or high-churn files:
117+
.idea/**/dataSources/
118+
.idea/**/dataSources.ids
119+
.idea/**/dataSources.xml
120+
.idea/**/dataSources.local.xml
121+
.idea/**/sqlDataSources.xml
122+
.idea/**/dynamic.xml
123+
.idea/**/uiDesigner.xml
124+
125+
# Gradle:
126+
.idea/**/gradle.xml
127+
.idea/**/libraries
128+
129+
# CMake
130+
cmake-build-debug/
131+
132+
# Mongo Explorer plugin:
133+
.idea/**/mongoSettings.xml
134+
135+
## File-based project format:
136+
*.iws
137+
138+
## Plugin-specific files:
139+
140+
# IntelliJ
141+
out/
142+
143+
# mpeltonen/sbt-idea plugin
144+
.idea_modules/
145+
146+
# JIRA plugin
147+
atlassian-ide-plugin.xml
148+
149+
# Cursive Clojure plugin
150+
.idea/replstate.xml
151+
152+
# Crashlytics plugin (for Android Studio and IntelliJ)
153+
com_crashlytics_export_strings.xml
154+
crashlytics.properties
155+
crashlytics-build.properties
156+
fabric.properties

README.md

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# json-logging
22
Python logging library to emit JSON log that can be easily indexed and searchable by logging infrastructure such as [ELK](https://www.elastic.co/webinars/introduction-elk-stack).
3-
If you're using Cloud Foundry, it worth to check out this library [cf-python-logging-support](https://github.com/SAP/cf-python-logging-support) which I'm also original author and contributor.
3+
If you're using Cloud Foundry, it worth to check out the library [SAP/cf-python-logging-support](https://github.com/SAP/cf-python-logging-support) which I'm also original author and contributor.
44
# Content
55
1. [Features](#1-features)
66
2. [Installation](#2-installation)
@@ -27,10 +27,11 @@ If you're using Cloud Foundry, it worth to check out this library [cf-python-log
2727
# 2. Usage
2828
This library is very intrusive, once configured library will try to configure all loggers (existing and newly created) to emit log in JSON format.
2929
Install by running this command:
30-
> pip install json-logging
30+
> pip install json-logging
31+
3132
The most important method is **init(framework_name)**.
3233

33-
TODO: using ELK stack to view log
34+
TODO: update guide on how to use ELK stack to view log
3435

3536
## 2.1 Non-web application log
3637
This mode don't support **correlation-id**.
@@ -110,14 +111,15 @@ logger.info("test log statement", extra = {'props' : {'extra_property' : 'extra_
110111
```
111112
## 2.5 Root logger
112113
If you want to use root logger as main logger to emit log. Made sure you call **config_root_logger()** after initialize root logger (by
113-
**logging.basicConfig()** or **logging.getLogger('root')**) [\[2\]](#2-python-logging-propagate)
114+
logging.basicConfig() or logging.getLogger('root')) [\[2\]](#2-python-logging-propagate)
114115
```python
115116
logging.basicConfig()
116117
json_logging.config_root_logger()
117118
```
118119

119120
# 4. Configuration
120121
logging library can be configured by setting the value in json_logging
122+
121123
Name | Description | Default value
122124
--- | --- | ---
123125
ENABLE_JSON_LOGGING | Whether to enable JSON logging mode.Can be set as an environment variable, enable when set to to either one in following list (case-insensitive) **['true', '1', 'y', 'yes']** | false
@@ -126,17 +128,18 @@ CORRELATION_ID_HEADERS | List of HTTP headers that will be used to look for corr
126128
EMPTY_VALUE | Default value when a logging record property is None | '-'
127129
CORRELATION_ID_GENERATOR | function to generate unique correlation-id | uuid.uuid1
128130
JSON_SERIALIZER | function to encode object to JSON | json.dumps
129-
LAYER | The execution layer in the component that emitted the message | 'python'
130-
COMPONENT_TYPE | A human-friendly name representing the software component |
131-
CREATE_CORRELATION_ID_IF_NOT_EXISTS | Whether to generate an new correlation-id in case one is not present.| True
131+
COMPONENT_ID | Uniquely identifies the software component that has processed the current
132+
request | EMPTY_VALUE
133+
COMPONENT_NAME | A human-friendly name representing the software component | EMPTY_VALUE
134+
COMPONENT_INSTANCE_INDEX | Instance's index of horizontally scaled service | 0
135+
CREATE_CORRELATION_ID_IF_NOT_EXISTS | Whether to generate an new correlation-id in case one is not present| True
132136

133137
# 5. Python References
134138

135139
TODO: update Python API docs on Github page
136140

137141
# 6. Framework support plugin development
138-
139-
To add support for a new web framework, you need to extend following classes in **framework_base** and register support using **register_framework_support** method:
142+
To add support for a new web framework, you need to extend following classes in [**framework_base**](/blob/master/json_logging/framework_base.py) and register support using [**json_logging.register_framework_support**](https://github.com/thangbn/json-logging-python/blob/master/json_logging/__init__.py#L38) method:
140143

141144
Class | Description | Mandatory
142145
--- | --- | ---
@@ -145,7 +148,7 @@ ResponseAdapter | Helper class help to extract logging-relevant information from
145148
FrameworkConfigurator | Class to perform logging configuration for given framework as needed | no
146149
AppRequestInstrumentationConfigurator | Class to perform request instrumentation logging configuration | no
147150

148-
Take a look at **json_logging/base_framework.py**, **json_logging.flask** and **json_logging.sanic** packages for reference implementations
151+
Take a look at [**json_logging/base_framework.py**](blob/master/json_logging/framework_base.py), [**json_logging.flask**](tree/master/json_logging/framework/flask) and [**json_logging.sanic**](/tree/master/json_logging/framework/sanic) packages for reference implementations.
149152

150153
# 7. FAQ & Troubleshooting
151154
1. I configured everything, but no logs are printed out?
@@ -168,9 +171,45 @@ pip3 install .
168171
```
169172
# 8. References
170173
## [0] Full logging format references
171-
- application logs: https://github.com/SAP/cf-java-logging-support/blob/master/cf-java-logging-support-core/beats/app-logs/docs/fields.asciidoc#exported-fields-app-logs
174+
- Common field
175+
Field | Description | Format | Example
176+
--- | --- | --- | ---
177+
written_at | The date when this log message was written. | ISO 8601 YYYY-MM-DDTHH:MM:SS.milliZ | 2017-12-23T15:14:02.208Z
178+
written_ts | The timestamp in nano-second precision when this request metric message was written. | long number | 1456820553816849408
179+
correlation_id | The timestamp in nano-second precision when this request metric message was written. | string | db2d002e-2702-41ec-66f5-c002a80a3d3f
180+
type | Type of message. "logs" or "request" | string | db2d002e-2702-41ec-66f5-c002a80a3d3f
181+
component_id | Uniquely identifies the software component that has processed the current
182+
request | string | 9e6f3ecf-def0-4baf-8fac-9339e61d5645
183+
component_name | A human-friendly name representing the software component | string | my-fancy-component
184+
component_instance | Instance's index of horizontally scaled service | string | 0
172185

173-
- request logs: https://github.com/SAP/cf-java-logging-support/blob/master/cf-java-logging-support-core/beats/request-metrics/docs/fields.asciidoc
186+
- application logs: https://github.com/SAP/cf-java-logging-support/blob/master/cf-java-logging-support-core/beats/app-logs/docs/fields.asciidoc#exported-fields-app-logs
187+
Field | Description | Format | Example
188+
--- | --- | --- | ---
189+
msg | The actual message string passed to the logger. | string | This is a log message
190+
level | The log "level" indicating the severity of the log message. | string | INFO
191+
thread | Identifies the execution thread in which this log message has been written. | string | http-nio-4655
192+
logger | The logger name that emits the log message.
193+
| string | requests-logger
194+
195+
- request logs:
196+
Field | Description | Format | Example
197+
--- | --- | --- | ---
198+
request | request path that has been processed. | string | /get/api/v2
199+
request_received_at | The date when an incoming request was received by the producer.| ISO 8601 YYYY-MM-DDTHH:MM:SS.milliZ The precision is in milliseconds. The timezone is UTC. | 2015-01-24 14:06:05.071Z
200+
response_sent_at | The date when the response to an incoming request was sent to the consumer. | ditto | 2015-01-24 14:06:05.071Z
201+
response_time_ms | How many milliseconds it took the producer to prepare the response. | float | 43.476
202+
protocol | Which protocol was used to issue a request to a producer. In most cases, this will be HTTP (including a version specifier), but for outgoing requests reported by a producer it may contain other values. E.g. a database call via JDBC may report, e.g. "JDBC/1.2" | string | HTTP/1.1
203+
method | The corresponding protocol method. | string | GET
204+
remote_ip | IP address of the consumer (might be a proxy, might be the actual client) | string | 192.168.0.1
205+
remote_host | host name of the consumer (might be a proxy, might be the actual client) | string | my.happy.host
206+
remote_port | Which TCP port is used by the consumer to establish a connection to the remote producer. | string | 1234
207+
remote_user | The username associated with the request | string | user_name
208+
request_size_b | The size in bytes of the request entity or "body" (e.g., in case of POST requests). | long | 1234
209+
response_status | The status code of the response. | long | 200
210+
response_content_type | The MIME type associated with the entity of the response if available/specified | long | application/json
211+
referer | For HTTP requests, identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested. | string | /index.html
212+
x_forwarded_for | Comma-separated list of IP addresses, the left-most being the original client, followed by proxy server addresses that forwarded the client request. | string | 192.0.2.60,10.12.9.23
174213

175214
## [1] What is correlation-id/request id
176215
https://stackoverflow.com/questions/25433258/what-is-the-x-request-id-http-header

json_logging/__init__.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
CREATE_CORRELATION_ID_IF_NOT_EXISTS = True
2020
JSON_SERIALIZER = json.dumps
2121
CORRELATION_ID_HEADERS = ['X-Correlation-ID', 'X-Request-ID']
22+
COMPONENT_ID = EMPTY_VALUE
23+
COMPONENT_NAME = EMPTY_VALUE
24+
COMPONENT_INSTANCE_INDEX = 0
25+
2226
_framework_support_map = {}
2327
_current_framework = None
2428
_logger = get_library_logger(__name__)
@@ -192,6 +196,9 @@ def format(self, record):
192196
"type": "request",
193197
"written_at": util.iso_time_format(utcnow),
194198
"written_ts": util.epoch_nano_second(utcnow),
199+
"component_id": COMPONENT_ID,
200+
"component_name": COMPONENT_NAME,
201+
"component_instance": COMPONENT_INSTANCE_INDEX,
195202
"correlation_id": _request_util.get_correlation_id(request),
196203
"remote_user": request_adapter.get_remote_user(request),
197204
"request": request_adapter.get_path(request),
@@ -220,13 +227,17 @@ class JSONLogFormatter(logging.Formatter):
220227
def format(self, record):
221228
utcnow = datetime.utcnow()
222229
json_log_object = {"type": "log",
230+
"written_at": util.iso_time_format(utcnow),
231+
"written_ts": util.epoch_nano_second(utcnow),
232+
"component_id": COMPONENT_ID,
233+
"component_name": COMPONENT_NAME,
234+
"component_instance": COMPONENT_INSTANCE_INDEX,
223235
"logger": record.name,
224236
"thread": record.threadName,
225237
"level": record.levelname,
226238
"line_no": record.lineno,
227-
"written_at": util.iso_time_format(utcnow),
228-
"written_ts": util.epoch_nano_second(utcnow),
229-
"msg": record.getMessage()}
239+
"msg": record.getMessage()
240+
}
230241

231242
if hasattr(record, 'props'):
232243
json_log_object.update(record.props)
@@ -242,14 +253,16 @@ class JSONLogWebFormatter(logging.Formatter):
242253
def format(self, record):
243254
utcnow = datetime.utcnow()
244255
json_log_object = {"type": "log",
256+
"written_at": util.iso_time_format(utcnow),
257+
"written_ts": util.epoch_nano_second(utcnow),
258+
"component_id": COMPONENT_ID,
259+
"component_name": COMPONENT_NAME,
260+
"component_instance": COMPONENT_INSTANCE_INDEX,
245261
"logger": record.name,
246262
"thread": record.threadName,
247263
"level": record.levelname,
248264
"line_no": record.lineno,
249-
"written_at": util.iso_time_format(utcnow),
250-
"written_ts": util.epoch_nano_second(utcnow),
251-
"correlation_id": _request_util.get_correlation_id(),
252-
"msg": record.getMessage()}
265+
"correlation_id": _request_util.get_correlation_id()}
253266

254267
if hasattr(record, 'props'):
255268
json_log_object.update(record.props)

0 commit comments

Comments
 (0)