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

Commit 00b24aa

Browse files
authored
Support generating structured logs in addition to standard logs. (#8607)
This modifies the configuration of structured logging to be usable from the standard Python logging configuration. This also separates the formatting of logs from the transport allowing JSON logs to files or standard logs to sockets.
1 parent 9a7e0d2 commit 00b24aa

File tree

19 files changed

+706
-1011
lines changed

19 files changed

+706
-1011
lines changed

UPGRADE.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,22 @@ for example:
7575
wget https://packages.matrix.org/debian/pool/main/m/matrix-synapse-py3/matrix-synapse-py3_1.3.0+stretch1_amd64.deb
7676
dpkg -i matrix-synapse-py3_1.3.0+stretch1_amd64.deb
7777
78+
Upgrading to v1.23.0
79+
====================
80+
81+
Structured logging configuration breaking changes
82+
-------------------------------------------------
83+
84+
This release deprecates use of the ``structured: true`` logging configuration for
85+
structured logging. If your logging configuration contains ``structured: true``
86+
then it should be modified based on the `structured logging documentation
87+
<https://github.com/matrix-org/synapse/blob/master/docs/structured_logging.md>`_.
88+
89+
The ``structured`` and ``drains`` logging options are now deprecated and should
90+
be replaced by standard logging configuration of ``handlers`` and ``formatters`.
91+
92+
A future will release of Synapse will make using ``structured: true`` an error.
93+
7894
Upgrading to v1.22.0
7995
====================
8096

changelog.d/8607.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Re-organize the structured logging code to separate the TCP transport handling from the JSON formatting.

docs/sample_log_config.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
# This is a YAML file containing a standard Python logging configuration
44
# dictionary. See [1] for details on the valid settings.
55
#
6+
# Synapse also supports structured logging for machine readable logs which can
7+
# be ingested by ELK stacks. See [2] for details.
8+
#
69
# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema
10+
# [2]: https://github.com/matrix-org/synapse/blob/master/docs/structured_logging.md
711

812
version: 1
913

docs/structured_logging.md

Lines changed: 121 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,161 @@
11
# Structured Logging
22

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".
3+
A structured logging system can be useful when your logs are destined for a
4+
machine to parse and process. By maintaining its machine-readable characteristics,
5+
it enables more efficient searching and aggregations when consumed by software
6+
such as the "ELK stack".
47

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).
8+
Synapse's structured logging system is configured via the file that Synapse's
9+
`log_config` config option points to. The file should include a formatter which
10+
uses the `synapse.logging.TerseJsonFormatter` class included with Synapse and a
11+
handler which uses the above formatter.
12+
13+
There is also a `synapse.logging.JsonFormatter` option which does not include
14+
a timestamp in the resulting JSON. This is useful if the log ingester adds its
15+
own timestamp.
616

717
A structured logging configuration looks similar to the following:
818

919
```yaml
10-
structured: true
20+
version: 1
21+
22+
formatters:
23+
structured:
24+
class: synapse.logging.TerseJsonFormatter
25+
26+
handlers:
27+
file:
28+
class: logging.handlers.TimedRotatingFileHandler
29+
formatter: structured
30+
filename: /path/to/my/logs/homeserver.log
31+
when: midnight
32+
backupCount: 3 # Does not include the current log file.
33+
encoding: utf8
1134

1235
loggers:
1336
synapse:
1437
level: INFO
38+
handlers: [remote]
1539
synapse.storage.SQL:
1640
level: WARNING
17-
18-
drains:
19-
console:
20-
type: console
21-
location: stdout
22-
file:
23-
type: file_json
24-
location: homeserver.log
2541
```
2642
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
43+
The above logging config will set Synapse as 'INFO' logging level by default,
44+
with the SQL layer at 'WARNING', and will log to a file, stored as JSON.
3045
31-
Drain types can be specified by the `type` key.
46+
It is also possible to figure Synapse to log to a remote endpoint by using the
47+
`synapse.logging.RemoteHandler` class included with Synapse. It takes the
48+
following arguments:
3249

33-
### `console`
50+
- `host`: Hostname or IP address of the log aggregator.
51+
- `port`: Numerical port to contact on the host.
52+
- `maximum_buffer`: (Optional, defaults to 1000) The maximum buffer size to allow.
3453

35-
Outputs human-readable logs to the console.
54+
A remote structured logging configuration looks similar to the following:
3655

37-
Arguments:
56+
```yaml
57+
version: 1
3858
39-
- `location`: Either `stdout` or `stderr`.
59+
formatters:
60+
structured:
61+
class: synapse.logging.TerseJsonFormatter
4062
41-
### `console_json`
63+
handlers:
64+
remote:
65+
class: synapse.logging.RemoteHandler
66+
formatter: structured
67+
host: 10.1.2.3
68+
port: 9999
4269
43-
Outputs machine-readable JSON logs to the console.
70+
loggers:
71+
synapse:
72+
level: INFO
73+
handlers: [remote]
74+
synapse.storage.SQL:
75+
level: WARNING
76+
```
4477

45-
Arguments:
78+
The above logging config will set Synapse as 'INFO' logging level by default,
79+
with the SQL layer at 'WARNING', and will log JSON formatted messages to a
80+
remote endpoint at 10.1.2.3:9999.
4681

47-
- `location`: Either `stdout` or `stderr`.
82+
## Upgrading from legacy structured logging configuration
4883

49-
### `console_json_terse`
84+
Versions of Synapse prior to v1.23.0 included a custom structured logging
85+
configuration which is deprecated. It used a `structured: true` flag and
86+
configured `drains` instead of ``handlers`` and `formatters`.
5087

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.
88+
Synapse currently automatically converts the old configuration to the new
89+
configuration, but this will be removed in a future version of Synapse. The
90+
following reference can be used to update your configuration. Based on the drain
91+
`type`, we can pick a new handler:
5492

55-
Arguments:
93+
1. For a type of `console`, `console_json`, or `console_json_terse`: a handler
94+
with a class of `logging.StreamHandler` and a `stream` of `ext://sys.stdout`
95+
or `ext://sys.stderr` should be used.
96+
2. For a type of `file` or `file_json`: a handler of `logging.FileHandler` with
97+
a location of the file path should be used.
98+
3. For a type of `network_json_terse`: a handler of `synapse.logging.RemoteHandler`
99+
with the host and port should be used.
56100

57-
- `location`: Either `stdout` or `stderr`.
101+
Then based on the drain `type` we can pick a new formatter:
58102

59-
### `file`
103+
1. For a type of `console` or `file` no formatter is necessary.
104+
2. For a type of `console_json` or `file_json`: a formatter of
105+
`synapse.logging.JsonFormatter` should be used.
106+
3. For a type of `console_json_terse` or `network_json_terse`: a formatter of
107+
`synapse.logging.TerseJsonFormatter` should be used.
60108

61-
Outputs human-readable logs to a file.
109+
For each new handler and formatter they should be added to the logging configuration
110+
and then assigned to either a logger or the root logger.
62111

63-
Arguments:
112+
An example legacy configuration:
64113

65-
- `location`: An absolute path to the file to log to.
114+
```yaml
115+
structured: true
66116
67-
### `file_json`
117+
loggers:
118+
synapse:
119+
level: INFO
120+
synapse.storage.SQL:
121+
level: WARNING
68122
69-
Outputs machine-readable logs to a file.
123+
drains:
124+
console:
125+
type: console
126+
location: stdout
127+
file:
128+
type: file_json
129+
location: homeserver.log
130+
```
70131

71-
Arguments:
132+
Would be converted into a new configuration:
72133

73-
- `location`: An absolute path to the file to log to.
134+
```yaml
135+
version: 1
74136
75-
### `network_json_terse`
137+
formatters:
138+
json:
139+
class: synapse.logging.JsonFormatter
76140
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`.
141+
handlers:
142+
console:
143+
class: logging.StreamHandler
144+
location: ext://sys.stdout
145+
file:
146+
class: logging.FileHandler
147+
formatter: json
148+
filename: homeserver.log
79149
80-
Arguments:
150+
loggers:
151+
synapse:
152+
level: INFO
153+
handlers: [console, file]
154+
synapse.storage.SQL:
155+
level: WARNING
156+
```
81157

82-
- `host`: Hostname or IP address of the log aggregator.
83-
- `port`: Numerical port to contact on the host.
158+
The new logging configuration is a bit more verbose, but significantly more
159+
flexible. It allows for configuration that were not previously possible, such as
160+
sending plain logs over the network, or using different handlers for different
161+
modules.

scripts-dev/lint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ else
8080
# then lint everything!
8181
if [[ -z ${files+x} ]]; then
8282
# Lint all source code files and directories
83-
files=("synapse" "tests" "scripts-dev" "scripts" "contrib" "synctl" "setup.py")
83+
files=("synapse" "tests" "scripts-dev" "scripts" "contrib" "synctl" "setup.py" "synmark")
8484
fi
8585
fi
8686

0 commit comments

Comments
 (0)