|
73 | 73 | logging.basicConfig(format=format_string, level=logging.DEBUG) |
74 | 74 | """ |
75 | 75 |
|
| 76 | +import re |
76 | 77 | import logging |
77 | 78 | import inspect |
78 | 79 | import functools |
79 | 80 | from collections.abc import Mapping, Sequence |
80 | 81 |
|
81 | | -from ._constants import API_LOGGER_NAME, BLANKED_OUT_STRING |
| 82 | +from ._constants import API_LOGGER_NAME, BLANKED_OUT_STRING, \ |
| 83 | + BLANKED_OUT_PROPERTY_PATTERN, BLANKED_OUT_PROPERTY_REPLACE |
82 | 84 |
|
83 | 85 | __all__ = [] |
84 | 86 |
|
@@ -115,6 +117,8 @@ def logged_api_call( |
115 | 117 | The logger's name is the dotted module name of the module defining the |
116 | 118 | decorated function (e.g. 'zhmcclient._cpc'). |
117 | 119 |
|
| 120 | + The values of sensitive properties will be blanked out. |
| 121 | +
|
118 | 122 | Parameters: |
119 | 123 |
|
120 | 124 | org_func (function object): The original function being decorated. |
@@ -277,22 +281,43 @@ def blanked_args(args, kwargs): |
277 | 281 | blanked_dict(args[properties_pos]) |
278 | 282 | return tuple(logged_args), logged_kwargs |
279 | 283 |
|
| 284 | + def log_repr(obj, name, trunc): |
| 285 | + """ |
| 286 | + Return a Python repr() representation of the object, with |
| 287 | + sensitive properties blanked out. |
| 288 | + """ |
| 289 | + obj_str = log_escaped(repr(obj)) |
| 290 | + obj_str = re.sub(BLANKED_OUT_PROPERTY_PATTERN, |
| 291 | + BLANKED_OUT_PROPERTY_REPLACE, obj_str) |
| 292 | + obj_len = len(obj_str) |
| 293 | + if obj_len > trunc > 0: |
| 294 | + obj_str = (f"{name} (first {trunc} B of {obj_len} B): " |
| 295 | + f"{obj_str[0:trunc]} ...(truncated)") |
| 296 | + else: |
| 297 | + obj_str = f"{name}: {obj_str}" |
| 298 | + return obj_str |
| 299 | + |
280 | 300 | def log_call(args, kwargs): |
281 | 301 | """ |
282 | 302 | Log the call to the API function. |
283 | 303 | """ |
284 | | - logged_args, logged_kwargs = blanked_args(args, kwargs) |
285 | | - logger.debug("Called: %s, args: %.500s, kwargs: %.500s", |
286 | | - apifunc_str, |
287 | | - log_escaped(repr(logged_args)), |
288 | | - log_escaped(repr(logged_kwargs))) |
| 304 | + trunc = 500 |
| 305 | + # We are calling log_trunc() also on args, because their values |
| 306 | + # (in theory) may contain dicts with sensitive properties. |
| 307 | + _args, _kwargs = blanked_args(args, kwargs) |
| 308 | + args_str = log_repr(_args, "args", trunc) |
| 309 | + kwargs_str = log_repr(_kwargs, "kwargs", trunc) |
| 310 | + logger.debug("Called: %s, %s, %s", |
| 311 | + apifunc_str, args_str, kwargs_str) |
289 | 312 |
|
290 | 313 | def log_return(result): |
291 | 314 | """ |
292 | 315 | Log the return from the API function. |
293 | 316 | """ |
294 | | - logger.debug("Return: %s, result: %.1000s", |
295 | | - apifunc_str, log_escaped(repr(result))) |
| 317 | + trunc = 1000 |
| 318 | + result_str = log_repr(result, "result", trunc) |
| 319 | + logger.debug("Return: %s, %s", |
| 320 | + apifunc_str, result_str) |
296 | 321 |
|
297 | 322 | @functools.wraps(func) |
298 | 323 | def log_api_call(*args, **kwargs): |
|
0 commit comments