fix(slog): masking of grouped attributes (#11606)

# Which Problems Are Solved

Group attributes weren't masked if their corresponding key was
configured. For example setting `data` as a masked key entry in the
runtime config would still print unmasked event data. This was because
ReplaceAttr does not receive group attributes, only the flattened
attributes with group information.

# How the Problems Are Solved

Check the current groups stack in the replacer. When a configured key is
found in the group, mask the current attribute. This means that the
attribute structure is preserved and all sub-keys of a masked group are
still printed.

# Additional Changes

- Use a binary search for key matching. As we are now comparing slice
against slice, a binary search should make the process a little faster
if many keys are configured.

# Additional Context

- Follow-up for PR #11435

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: muhlemmer <[email protected]>
This commit is contained in:
Tim Möhlmann
2026-02-18 06:00:13 +00:00
committed by GitHub
co-authored by Copilot Copilot muhlemmer
parent 93c6099482
commit c02d812b6c
5 changed files with 58 additions and 11 deletions
+4 -2
View File
@@ -59,8 +59,10 @@ Instrumentation:
# Keys are unqualified attribute names and apply to all attributes with the specified name,
# regardless of their position in the attribute hierarchy.
# Eg. "some_key" matches "some_key" and "parent.some_key" etc.
# If the matched log attribute is a nested object or array,
# the entire structure is replaced with the specified Value.
# When the key matches a group of attributes (e.g. slog.Group), all attribute values in the
# group are masked and the structure of the group is preserved.
# When the key matches a non-group attribute whose value is a nested object/array
# (e.g. added via slog.Any), the entire value is replaced with Value and its structure is not preserved.
Keys: # ZITADEL_INSTRUMENTATION_LOG_MASK_KEYS (comma separated list)
# - "first_name"
# - "last_name"
+4 -2
View File
@@ -59,8 +59,10 @@ Instrumentation:
# Keys are unqualified attribute names and apply to all attributes with the specified name,
# regardless of their position in the attribute hierarchy.
# Eg. "some_key" matches "some_key" and "parent.some_key" etc.
# If the matched log attribute is a nested object or array,
# the entire structure is replaced with the specified Value.
# When the key matches a group of attributes (e.g. slog.Group), all attribute values in the
# group are masked and the structure of the group is preserved.
# When the key matches a non-group attribute whose value is a nested object/array
# (e.g. added via slog.Any), the entire value is replaced with Value and its structure is not preserved.
Keys: # ZITADEL_INSTRUMENTATION_LOG_MASK_KEYS (comma separated list)
# - "first_name"
# - "last_name"
+4 -2
View File
@@ -59,8 +59,10 @@ Instrumentation:
# Keys are unqualified attribute names and apply to all attributes with the specified name,
# regardless of their position in the attribute hierarchy.
# Eg. "some_key" matches "some_key" and "parent.some_key" etc.
# If the matched log attribute is a nested object or array,
# the entire structure is replaced with the specified Value.
# When the key matches a group of attributes (e.g. slog.Group), all attribute values in the
# group are masked and the structure of the group is preserved.
# When the key matches a non-group attribute whose value is a nested object/array
# (e.g. added via slog.Any), the entire value is replaced with Value and its structure is not preserved.
Keys: # ZITADEL_INSTRUMENTATION_LOG_MASK_KEYS (comma separated list)
# - "first_name"
# - "last_name"