-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathcodec_logging.py
More file actions
56 lines (47 loc) · 1.9 KB
/
Copy pathcodec_logging.py
File metadata and controls
56 lines (47 loc) · 1.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""CODEC structured logging — JSON format for log aggregation."""
import logging
import json
import sys
import time
import os
class JSONFormatter(logging.Formatter):
def format(self, record):
log_entry = {
"ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(record.created)),
"level": record.levelname,
"logger": record.name,
"msg": record.getMessage(),
"module": record.module,
"line": record.lineno,
}
if record.exc_info and record.exc_info[0]:
log_entry["exception"] = self.formatException(record.exc_info)
return json.dumps(log_entry, default=str)
def setup_logging(level=logging.INFO, json_output=True):
"""Configure root logger with JSON or plain formatting.
Call once at process startup. Set CODEC_LOG_JSON=0 for plain format.
Level-split handlers (2026-07 log review): DEBUG/INFO → stdout,
WARNING+ → stderr. PM2 maps stderr to `<name>-error.log`, so with a
single stderr StreamHandler the error logs were ~95% INFO chatter —
real errors were invisible. After the split, `*-error.log` only
contains WARNING and above.
"""
root = logging.getLogger()
if root.handlers:
return # already configured
if json_output and os.environ.get("CODEC_LOG_JSON", "1") != "0":
formatter = JSONFormatter()
else:
formatter = logging.Formatter(
"%(asctime)s [%(name)s] %(levelname)s: %(message)s",
datefmt="%H:%M:%S"
)
out_handler = logging.StreamHandler(sys.stdout)
out_handler.setFormatter(formatter)
out_handler.addFilter(lambda record: record.levelno < logging.WARNING)
err_handler = logging.StreamHandler(sys.stderr)
err_handler.setFormatter(formatter)
err_handler.setLevel(logging.WARNING)
root.addHandler(out_handler)
root.addHandler(err_handler)
root.setLevel(level)