Skip to content

Commit f12dcdf

Browse files
committed
Custom formatters for pool, host, vm, snapshot and vdi loggers
Signed-off-by: Vincent Michel <vincent.michel@vates.tech>
1 parent 859e5a0 commit f12dcdf

1 file changed

Lines changed: 111 additions & 11 deletions

File tree

lib/logging.py

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
def drop_column(key: str, value: object) -> str:
66
return ""
77

8+
89
def millisecond_timestamper(
910
logger: structlog.typing.WrappedLogger,
1011
method_name: str,
@@ -17,35 +18,125 @@ def millisecond_timestamper(
1718
return event_dict
1819

1920

20-
def render_console_or_ssh_output(
21-
console_renderer: structlog.dev.ConsoleRenderer,
21+
def make_kv_identifier_column(key: str, styles: structlog.dev.ColumnStyles) -> structlog.dev.Column:
22+
width = 16 - len(key)
23+
value_format = f"{{:>{width}}}"
24+
col = structlog.dev.Column(
25+
key,
26+
structlog.dev.KeyValueColumnFormatter(
27+
key_style=styles.kv_key,
28+
value_style=styles.kv_value,
29+
reset_style=styles.reset,
30+
value_repr=value_format.format,
31+
prefix="[",
32+
postfix="]",
33+
width=16 - len(key),
34+
),
35+
)
36+
return col
37+
38+
def render_to_console(
39+
default_renderer: structlog.dev.ConsoleRenderer,
40+
pool_renderer: structlog.dev.ConsoleRenderer,
41+
host_renderer: structlog.dev.ConsoleRenderer,
42+
vm_renderer: structlog.dev.ConsoleRenderer,
43+
snapshot_renderer: structlog.dev.ConsoleRenderer,
44+
vdi_renderer: structlog.dev.ConsoleRenderer,
2245
ssh_output_renderer: structlog.dev.ConsoleRenderer,
2346
) -> structlog.typing.Processor:
47+
dispatch = {
48+
"Pool": pool_renderer,
49+
"Host": host_renderer,
50+
"VM": vm_renderer,
51+
"Snapshot": snapshot_renderer,
52+
"VDI": vdi_renderer,
53+
}
54+
noise_keys = {
55+
"Pool": [],
56+
"Host": ["pool"],
57+
"VM": ["pool", "ip"],
58+
"Snapshot": ["pool"],
59+
"VDI": [],
60+
}
61+
info_noise_keys = {
62+
"Pool": [],
63+
"Host": [],
64+
"VM": ["host", "vm_uuid", "ip"],
65+
"Snapshot": ["host", "vm_uuid", "snapshot_uuid"],
66+
"VDI": ["vdi_uuid", "sr_uuid"],
67+
}
68+
2469
def processor(
2570
logger: structlog.typing.WrappedLogger,
2671
method_name: str,
2772
event_dict: structlog.typing.EventDict,
2873
) -> str:
74+
# SSH output renderer
2975
if event_dict.pop("ssh_output", False):
3076
event_dict["ssh_prefix"] = ">"
3177
return ssh_output_renderer(logger, method_name, event_dict)
32-
return console_renderer(logger, method_name, event_dict)
78+
79+
# Default renderer
80+
logger_name = event_dict.get("logger", None)
81+
if logger_name not in dispatch:
82+
return default_renderer(logger, method_name, event_dict)
83+
event_dict.pop("logger")
84+
85+
# Prepare identifier
86+
if logger_name == "VM":
87+
ip = event_dict.get("ip")
88+
vm_uuid = event_dict.get("vm_uuid", "")
89+
event_dict["vm"] = ip if ip else vm_uuid[:8]
90+
elif logger_name == "Snapshot":
91+
snapshot_uuid = event_dict.get("snapshot_uuid", "")
92+
event_dict["snapshot"] = snapshot_uuid[:8]
93+
elif logger_name == "VDI":
94+
vdi_uuid = event_dict.get("vdi_uuid", "")
95+
event_dict["vdi"] = vdi_uuid[:8]
96+
97+
# Remove noisy key-value pairs
98+
for key in noise_keys[logger_name]:
99+
event_dict.pop(key, None)
100+
if event_dict.get("level") == "info":
101+
for key in info_noise_keys[logger_name]:
102+
event_dict.pop(key, None)
103+
104+
# Render
105+
renderer = dispatch[logger_name]
106+
return renderer(logger, method_name, event_dict)
33107

34108
return processor
35109

36110

37111
def configure_logging():
38-
console_renderer = structlog.dev.ConsoleRenderer(colors=True, pad_event_to=40, sort_keys=False)
39-
logger_name_column = console_renderer.columns[-1]
40-
assert logger_name_column.key == "logger_name"
41-
console_renderer.columns[2].formatter.width = 5 # type: ignore
42-
logger_name_column.formatter.width = 8 # type: ignore
43112
styles = structlog.dev.ConsoleRenderer.get_default_column_styles(colors=True)
113+
114+
default_renderer = structlog.dev.ConsoleRenderer(colors=True, pad_event_to=40, sort_keys=False)
115+
col_extras = default_renderer.columns[0]
116+
col_timestamp = default_renderer.columns[1]
117+
col_level = default_renderer.columns[2]
118+
col_event = default_renderer.columns[3]
119+
col_logger = default_renderer.columns[4]
120+
col_level.formatter.width = 5 # type: ignore
121+
col_logger.formatter.width = 17 # type: ignore
122+
123+
def make_renderer(identifier_column: structlog.dev.Column) -> structlog.dev.ConsoleRenderer:
124+
return structlog.dev.ConsoleRenderer(
125+
sort_keys=False,
126+
columns=[col_timestamp, col_level, col_event, identifier_column, col_extras],
127+
)
128+
129+
pool_renderer = make_renderer(make_kv_identifier_column("pool", styles))
130+
host_renderer = make_renderer(make_kv_identifier_column("host", styles))
131+
vm_renderer = make_renderer(make_kv_identifier_column("vm", styles))
132+
snapshot_renderer = make_renderer(make_kv_identifier_column("snapshot", styles))
133+
vdi_renderer = make_renderer(make_kv_identifier_column("vdi", styles))
134+
44135
ssh_output_renderer = structlog.dev.ConsoleRenderer(
45136
sort_keys=False,
46137
columns=[
47-
console_renderer.columns[1],
48-
console_renderer.columns[2],
138+
col_timestamp,
139+
col_level,
49140
structlog.dev.Column("", drop_column),
50141
structlog.dev.Column(
51142
"ssh_prefix",
@@ -67,14 +158,23 @@ def configure_logging():
67158
),
68159
],
69160
)
161+
70162
structlog.configure(
71163
processors=[
72164
structlog.stdlib.add_log_level,
73165
structlog.stdlib.add_logger_name,
74166
millisecond_timestamper,
75167
structlog.stdlib.PositionalArgumentsFormatter(),
76168
structlog.processors.StackInfoRenderer(),
77-
render_console_or_ssh_output(console_renderer, ssh_output_renderer),
169+
render_to_console(
170+
default_renderer,
171+
pool_renderer,
172+
host_renderer,
173+
vm_renderer,
174+
snapshot_renderer,
175+
vdi_renderer,
176+
ssh_output_renderer,
177+
),
78178
],
79179
logger_factory=structlog.stdlib.LoggerFactory(),
80180
cache_logger_on_first_use=True,

0 commit comments

Comments
 (0)