Skip to content
This repository was archived by the owner on Apr 26, 2024. It is now read-only.

Commit 35a521b

Browse files
committed
Implement a structured logging output system. (#5680)
2 parents 41992a2 + 7dc3985 commit 35a521b

31 files changed

+1328
-81
lines changed

.buildkite/docker-compose.py35.pg95.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ services:
66
image: postgres:9.5
77
environment:
88
POSTGRES_PASSWORD: postgres
9+
command: -c fsync=off
910

1011
testenv:
1112
image: python:3.5

.buildkite/docker-compose.py37.pg11.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ services:
66
image: postgres:11
77
environment:
88
POSTGRES_PASSWORD: postgres
9+
command: -c fsync=off
910

1011
testenv:
1112
image: python:3.7

.buildkite/docker-compose.py37.pg95.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ services:
66
image: postgres:9.5
77
environment:
88
POSTGRES_PASSWORD: postgres
9+
command: -c fsync=off
910

1011
testenv:
1112
image: python:3.7

.buildkite/pipeline.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ steps:
4545
- docker#v3.0.1:
4646
image: "python:3.6"
4747

48+
- command:
49+
- "python -m pip install tox"
50+
- "tox -e mypy"
51+
label: ":mypy: mypy"
52+
plugins:
53+
- docker#v3.0.1:
54+
image: "python:3.5"
55+
4856
- wait
4957

5058
- command:
@@ -54,6 +62,7 @@ steps:
5462
label: ":python: 3.5 / SQLite / Old Deps"
5563
env:
5664
TRIAL_FLAGS: "-j 2"
65+
LANG: "C.UTF-8"
5766
plugins:
5867
- docker#v3.0.1:
5968
image: "ubuntu:xenial" # We use xenail to get an old sqlite and python

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ _trial_temp*/
2020
/*.signing.key
2121
/env/
2222
/homeserver*.yaml
23+
/logs
2324
/media_store/
2425
/uploads
2526

@@ -29,13 +30,13 @@ _trial_temp*/
2930
/.vscode/
3031

3132
# build products
32-
/.coverage*
3333
!/.coveragerc
34+
/.coverage*
35+
/.mypy_cache/
3436
/.tox
3537
/build/
3638
/coverage.*
3739
/dist/
3840
/docs/build/
3941
/htmlcov
4042
/pip-wheel-metadata/
41-

changelog.d/5680.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lay the groundwork for structured logging output.

docs/structured_logging.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Structured Logging
2+
3+
A structured logging system can be useful when your logs are destined for a machine to parse and process. By maintaining its machine-readable characteristics, it enables more efficient searching and aggregations when consumed by software such as the "ELK stack".
4+
5+
Synapse's structured logging system is configured via the file that Synapse's `log_config` config option points to. The file must be YAML and contain `structured: true`. It must contain a list of "drains" (places where logs go to).
6+
7+
A structured logging configuration looks similar to the following:
8+
9+
```yaml
10+
structured: true
11+
12+
loggers:
13+
synapse:
14+
level: INFO
15+
synapse.storage.SQL:
16+
level: WARNING
17+
18+
drains:
19+
console:
20+
type: console
21+
location: stdout
22+
file:
23+
type: file_json
24+
location: homeserver.log
25+
```
26+
27+
The above logging config will set Synapse as 'INFO' logging level by default, with the SQL layer at 'WARNING', and will have two logging drains (to the console and to a file, stored as JSON).
28+
29+
## Drain Types
30+
31+
Drain types can be specified by the `type` key.
32+
33+
### `console`
34+
35+
Outputs human-readable logs to the console.
36+
37+
Arguments:
38+
39+
- `location`: Either `stdout` or `stderr`.
40+
41+
### `console_json`
42+
43+
Outputs machine-readable JSON logs to the console.
44+
45+
Arguments:
46+
47+
- `location`: Either `stdout` or `stderr`.
48+
49+
### `console_json_terse`
50+
51+
Outputs machine-readable JSON logs to the console, separated by newlines. This
52+
format is not designed to be read and re-formatted into human-readable text, but
53+
is optimal for a logging aggregation system.
54+
55+
Arguments:
56+
57+
- `location`: Either `stdout` or `stderr`.
58+
59+
### `file`
60+
61+
Outputs human-readable logs to a file.
62+
63+
Arguments:
64+
65+
- `location`: An absolute path to the file to log to.
66+
67+
### `file_json`
68+
69+
Outputs machine-readable logs to a file.
70+
71+
Arguments:
72+
73+
- `location`: An absolute path to the file to log to.
74+
75+
### `network_json_terse`
76+
77+
Delivers machine-readable JSON logs to a log aggregator over TCP. This is
78+
compatible with LogStash's TCP input with the codec set to `json_lines`.
79+
80+
Arguments:
81+
82+
- `host`: Hostname or IP address of the log aggregator.
83+
- `port`: Numerical port to contact on the host.

synapse/app/_base.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@
3636

3737
logger = logging.getLogger(__name__)
3838

39+
# list of tuples of function, args list, kwargs dict
3940
_sighup_callbacks = []
4041

4142

42-
def register_sighup(func):
43+
def register_sighup(func, *args, **kwargs):
4344
"""
4445
Register a function to be called when a SIGHUP occurs.
4546
4647
Args:
4748
func (function): Function to be called when sent a SIGHUP signal.
48-
Will be called with a single argument, the homeserver.
49+
Will be called with a single default argument, the homeserver.
50+
*args, **kwargs: args and kwargs to be passed to the target function.
4951
"""
50-
_sighup_callbacks.append(func)
52+
_sighup_callbacks.append((func, args, kwargs))
5153

5254

5355
def start_worker_reactor(appname, config, run_command=reactor.run):
@@ -248,8 +250,8 @@ def handle_sighup(*args, **kwargs):
248250
# we're not using systemd.
249251
sdnotify(b"RELOADING=1")
250252

251-
for i in _sighup_callbacks:
252-
i(hs)
253+
for i, args, kwargs in _sighup_callbacks:
254+
i(hs, *args, **kwargs)
253255

254256
sdnotify(b"READY=1")
255257

synapse/app/admin_cmd.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,6 @@ def start(config_options):
227227
config.start_pushers = False
228228
config.send_federation = False
229229

230-
setup_logging(config, use_worker_options=True)
231-
232230
synapse.events.USE_FROZEN_DICTS = config.use_frozen_dicts
233231

234232
database_engine = create_engine(config.database_config)
@@ -241,6 +239,8 @@ def start(config_options):
241239
database_engine=database_engine,
242240
)
243241

242+
setup_logging(ss, config, use_worker_options=True)
243+
244244
ss.setup()
245245

246246
# We use task.react as the basic run command as it correctly handles tearing

synapse/app/appservice.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,6 @@ def start(config_options):
141141

142142
assert config.worker_app == "synapse.app.appservice"
143143

144-
setup_logging(config, use_worker_options=True)
145-
146144
events.USE_FROZEN_DICTS = config.use_frozen_dicts
147145

148146
database_engine = create_engine(config.database_config)
@@ -167,6 +165,8 @@ def start(config_options):
167165
database_engine=database_engine,
168166
)
169167

168+
setup_logging(ps, config, use_worker_options=True)
169+
170170
ps.setup()
171171
reactor.addSystemEventTrigger(
172172
"before", "startup", _base.start, ps, config.worker_listeners

0 commit comments

Comments
 (0)