elven-logs-interceptor-python 0.1.14__tar.gz → 0.1.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/PKG-INFO +15 -9
  2. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/README.md +14 -8
  3. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/pyproject.toml +1 -1
  4. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/application/config_service.py +2 -0
  5. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/filter/log_filter.py +3 -3
  6. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/utils.py +89 -5
  7. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/.gitignore +0 -0
  8. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/ARCHITECTURE.md +0 -0
  9. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/__init__.py +0 -0
  10. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/application/__init__.py +0 -0
  11. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/application/log_service.py +0 -0
  12. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/config.py +0 -0
  13. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/domain/__init__.py +0 -0
  14. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/domain/entities.py +0 -0
  15. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/domain/interfaces.py +0 -0
  16. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/domain/value_objects.py +0 -0
  17. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/__init__.py +0 -0
  18. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/buffer/__init__.py +0 -0
  19. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/buffer/memory_buffer.py +0 -0
  20. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/circuit_breaker/__init__.py +0 -0
  21. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/circuit_breaker/circuit_breaker.py +0 -0
  22. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/__init__.py +0 -0
  23. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/base.py +0 -0
  24. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/brotli_compressor.py +0 -0
  25. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/factory.py +0 -0
  26. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/gzip_compressor.py +0 -0
  27. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/compression/noop_compressor.py +0 -0
  28. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/context/__init__.py +0 -0
  29. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/context/context_provider.py +0 -0
  30. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/dlq/__init__.py +0 -0
  31. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/dlq/file_dlq.py +0 -0
  32. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/dlq/memory_dlq.py +0 -0
  33. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/filter/__init__.py +0 -0
  34. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/interceptors/__init__.py +0 -0
  35. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/interceptors/runtime_interceptor.py +0 -0
  36. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/internal_capture_guard.py +0 -0
  37. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/log_noise_filter.py +0 -0
  38. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/log_record_extra.py +0 -0
  39. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/memory/__init__.py +0 -0
  40. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/memory/memory_tracker.py +0 -0
  41. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/metrics/__init__.py +0 -0
  42. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/metrics/metrics_collector.py +0 -0
  43. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/__init__.py +0 -0
  44. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/loki_json_transport.py +0 -0
  45. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/loki_protobuf_transport.py +0 -0
  46. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/otlp_json_transport.py +0 -0
  47. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/resilient_transport.py +0 -0
  48. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/transport/transport_factory.py +0 -0
  49. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/workers/__init__.py +0 -0
  50. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/infrastructure/workers/worker_pool.py +0 -0
  51. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/__init__.py +0 -0
  52. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/celery.py +0 -0
  53. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/django.py +0 -0
  54. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/fastapi.py +0 -0
  55. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/flask.py +0 -0
  56. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/logging_handler.py +0 -0
  57. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/loguru.py +0 -0
  58. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/integrations/structlog.py +0 -0
  59. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/preload.py +0 -0
  60. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/presentation/__init__.py +0 -0
  61. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/presentation/factory.py +0 -0
  62. {elven_logs_interceptor_python-0.1.14 → elven_logs_interceptor_python-0.1.16}/src/logs_interceptor/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: elven-logs-interceptor-python
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Production-grade logs interceptor for Python with Loki transport, resilience, batching, and framework integrations.
5
5
  Author: Elven Observability
6
6
  License: MIT
@@ -123,9 +123,12 @@ logging.getLogger(__name__).info(
123
123
 
124
124
  Supported aliases: `warning(...)`, `exception(...)` and `critical(...)`.
125
125
 
126
- Sensitive fields such as `cpf`, `password`, `token` and `authorization` are
127
- redacted by default. Set `LOGS_FILTER_SANITIZE=false` only when raw sensitive
128
- data is explicitly required and approved.
126
+ Sensitive fields such as `cpf`, `cnpj`, `cpfCnpj`, `password`, `token` and `authorization` are
127
+ redacted by default. In messages, the library redacts only the sensitive
128
+ fragment/value and preserves the rest of the log. In structured context,
129
+ sensitive keys redact the full value. Set `LOGS_FILTER_SANITIZE=false`,
130
+ `LOGS_SANITIZE=false`, or `UO_LOGS_SANITIZE=false` only when raw sensitive data
131
+ is explicitly required and approved.
129
132
 
130
133
  ## Environment Variables
131
134
 
@@ -139,10 +142,13 @@ Required for direct Loki mode:
139
142
  - `LOGS_APP_NAME`
140
143
 
141
144
  For collector-first mode, set `LOGS_EXPORTER=otlp` (or `collector`) and use
142
- `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. In this mode `LOGS_URL`, `LOKI_URL`,
143
- `LOGS_TENANT` and `LOGS_TOKEN` are not required by the library. `LOGS_URL` is
144
- intentionally ignored in collector mode to avoid accidentally posting OTLP logs
145
- to a direct Loki `/loki/api/v1/push` endpoint. Put tenant or auth headers in
145
+ `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. If the explicit logs endpoint is missing,
146
+ the library derives `/v1/logs` from `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`,
147
+ `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`, or `OTEL_EXPORTER_OTLP_ENDPOINT`.
148
+ In this mode `LOGS_URL`, `LOKI_URL`, `LOGS_TENANT` and `LOGS_TOKEN` are not
149
+ required by the library. `LOGS_URL` is intentionally ignored in collector mode
150
+ to avoid accidentally posting OTLP logs to a direct Loki `/loki/api/v1/push`
151
+ endpoint. Put tenant or auth headers in
146
152
  `OTEL_EXPORTER_OTLP_HEADERS`/`LOGS_OTLP_HEADERS` if your collector gateway
147
153
  requires them.
148
154
 
@@ -182,7 +188,7 @@ Filter:
182
188
 
183
189
  - `LOGS_FILTER_LEVELS`
184
190
  - `LOGS_FILTER_SAMPLING_RATE`
185
- - `LOGS_FILTER_SANITIZE`
191
+ - `LOGS_FILTER_SANITIZE` (aliases: `LOGS_SANITIZE`, `UO_LOGS_SANITIZE`)
186
192
  - `LOGS_FILTER_MAX_MESSAGE_LENGTH`
187
193
  - `LOGS_FILTER_EXCLUDE_LOGGER_PREFIXES` (comma-separated)
188
194
 
@@ -62,9 +62,12 @@ logging.getLogger(__name__).info(
62
62
 
63
63
  Supported aliases: `warning(...)`, `exception(...)` and `critical(...)`.
64
64
 
65
- Sensitive fields such as `cpf`, `password`, `token` and `authorization` are
66
- redacted by default. Set `LOGS_FILTER_SANITIZE=false` only when raw sensitive
67
- data is explicitly required and approved.
65
+ Sensitive fields such as `cpf`, `cnpj`, `cpfCnpj`, `password`, `token` and `authorization` are
66
+ redacted by default. In messages, the library redacts only the sensitive
67
+ fragment/value and preserves the rest of the log. In structured context,
68
+ sensitive keys redact the full value. Set `LOGS_FILTER_SANITIZE=false`,
69
+ `LOGS_SANITIZE=false`, or `UO_LOGS_SANITIZE=false` only when raw sensitive data
70
+ is explicitly required and approved.
68
71
 
69
72
  ## Environment Variables
70
73
 
@@ -78,10 +81,13 @@ Required for direct Loki mode:
78
81
  - `LOGS_APP_NAME`
79
82
 
80
83
  For collector-first mode, set `LOGS_EXPORTER=otlp` (or `collector`) and use
81
- `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. In this mode `LOGS_URL`, `LOKI_URL`,
82
- `LOGS_TENANT` and `LOGS_TOKEN` are not required by the library. `LOGS_URL` is
83
- intentionally ignored in collector mode to avoid accidentally posting OTLP logs
84
- to a direct Loki `/loki/api/v1/push` endpoint. Put tenant or auth headers in
84
+ `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`. If the explicit logs endpoint is missing,
85
+ the library derives `/v1/logs` from `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`,
86
+ `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`, or `OTEL_EXPORTER_OTLP_ENDPOINT`.
87
+ In this mode `LOGS_URL`, `LOKI_URL`, `LOGS_TENANT` and `LOGS_TOKEN` are not
88
+ required by the library. `LOGS_URL` is intentionally ignored in collector mode
89
+ to avoid accidentally posting OTLP logs to a direct Loki `/loki/api/v1/push`
90
+ endpoint. Put tenant or auth headers in
85
91
  `OTEL_EXPORTER_OTLP_HEADERS`/`LOGS_OTLP_HEADERS` if your collector gateway
86
92
  requires them.
87
93
 
@@ -121,7 +127,7 @@ Filter:
121
127
 
122
128
  - `LOGS_FILTER_LEVELS`
123
129
  - `LOGS_FILTER_SAMPLING_RATE`
124
- - `LOGS_FILTER_SANITIZE`
130
+ - `LOGS_FILTER_SANITIZE` (aliases: `LOGS_SANITIZE`, `UO_LOGS_SANITIZE`)
125
131
  - `LOGS_FILTER_MAX_MESSAGE_LENGTH`
126
132
  - `LOGS_FILTER_EXCLUDE_LOGGER_PREFIXES` (comma-separated)
127
133
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "elven-logs-interceptor-python"
7
- version = "0.1.14"
7
+ version = "0.1.16"
8
8
  description = "Production-grade logs interceptor for Python with Loki transport, resilience, batching, and framework integrations."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -30,6 +30,8 @@ DEFAULT_SENSITIVE_PATTERNS = [
30
30
  r"authorization",
31
31
  r"credit[_-]?card",
32
32
  r"ssn",
33
+ r"cpf[_-]?cnpj",
34
+ r"cnpj",
33
35
  r"cpf",
34
36
  ]
35
37
 
@@ -5,7 +5,7 @@ import re
5
5
  from ...config import ResolvedFilterConfig
6
6
  from ...domain.entities import LogEntryEntity
7
7
  from ...types import LogLevel
8
- from ...utils import detect_sensitive_data, sanitize_data, should_sample
8
+ from ...utils import redact_sensitive_text, sanitize_data, should_sample
9
9
 
10
10
 
11
11
  class LogFilter:
@@ -35,8 +35,8 @@ class LogFilter:
35
35
  if self._config.sanitize and context is not None:
36
36
  context = sanitize_data(context, self._config.sensitive_patterns)
37
37
 
38
- if self._config.sanitize and detect_sensitive_data(message, self._config.sensitive_patterns):
39
- message = "[REDACTED]"
38
+ if self._config.sanitize:
39
+ message = redact_sensitive_text(message, self._config.sensitive_patterns)
40
40
 
41
41
  return LogEntryEntity(
42
42
  id=entry.id,
@@ -392,6 +392,87 @@ def detect_sensitive_data(text: str, patterns: Iterable[str]) -> bool:
392
392
  return any(pattern.search(text) for pattern in common_patterns)
393
393
 
394
394
 
395
+ def redact_sensitive_text(text: str, sensitive_patterns: Iterable[str]) -> str:
396
+ """Redact sensitive values while preserving the surrounding log message."""
397
+ patterns = list(sensitive_patterns)
398
+ redacted = text
399
+
400
+ for pattern in patterns:
401
+ redacted = _redact_key_value_pattern(redacted, pattern)
402
+
403
+ common_replacements: tuple[tuple[re.Pattern[str], str], ...] = (
404
+ (
405
+ re.compile(r"(Bearer)\s+[A-Za-z0-9\-._~+/=]+", re.IGNORECASE),
406
+ r"\1 [REDACTED]",
407
+ ),
408
+ (
409
+ re.compile(r"(Basic)\s+[A-Za-z0-9+/=]+", re.IGNORECASE),
410
+ r"\1 [REDACTED]",
411
+ ),
412
+ (
413
+ re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b"),
414
+ "[REDACTED]",
415
+ ),
416
+ (
417
+ re.compile(r"\b(?:\d{4}[-\s]?){3}\d{4}\b"),
418
+ "[REDACTED]",
419
+ ),
420
+ (
421
+ re.compile(r"\b\d{3}-\d{2}-\d{4}\b"),
422
+ "[REDACTED]",
423
+ ),
424
+ (
425
+ re.compile(r"\b\d{3}\.\d{3}\.\d{3}-\d{2}\b"),
426
+ "[REDACTED]",
427
+ ),
428
+ )
429
+ for common_pattern, replacement in common_replacements:
430
+ redacted = common_pattern.sub(replacement, redacted)
431
+
432
+ for pattern in patterns:
433
+ if _looks_like_value_pattern(pattern):
434
+ redacted = re.sub(pattern, "[REDACTED]", redacted, flags=re.IGNORECASE)
435
+
436
+ return redacted
437
+
438
+
439
+ def _redact_key_value_pattern(text: str, key_pattern: str) -> str:
440
+ quoted = re.compile(
441
+ rf"(?P<prefix>(?:[\"']?{key_pattern}[\"']?)\s*[:=]\s*)(?P<quote>[\"'])(?P<value>.*?)(?P=quote)",
442
+ re.IGNORECASE,
443
+ )
444
+ redacted = quoted.sub(r"\g<prefix>\g<quote>[REDACTED]\g<quote>", text)
445
+
446
+ unquoted = re.compile(
447
+ rf"(?P<prefix>(?:[\"']?{key_pattern}[\"']?)\s*[:=]\s*)(?P<value>[^\s,;&}}\]\"']+)",
448
+ re.IGNORECASE,
449
+ )
450
+
451
+ def _replace_unquoted(match: re.Match[str]) -> str:
452
+ value = match.group("value")
453
+ if value.lower() in {"bearer", "basic"} or value == "[REDACTED]":
454
+ return match.group(0)
455
+ return f"{match.group('prefix')}[REDACTED]"
456
+
457
+ redacted = unquoted.sub(_replace_unquoted, redacted)
458
+
459
+ query = re.compile(
460
+ rf"(?P<prefix>[?&](?:{key_pattern})=)(?P<value>[^&#\s]+)",
461
+ re.IGNORECASE,
462
+ )
463
+ return query.sub(r"\g<prefix>[REDACTED]", redacted)
464
+
465
+
466
+ def _looks_like_value_pattern(pattern: str) -> bool:
467
+ # Plain words such as "token" and "password" are key indicators by default;
468
+ # redacting those words directly would destroy harmless messages like
469
+ # "Gerando token de acesso". Regex-looking patterns are treated as values.
470
+ keyish_terms = r"password|token|secret|api|key|authorization|credit|card|ssn|cpf|cnpj"
471
+ if re.search(keyish_terms, pattern, re.IGNORECASE):
472
+ return False
473
+ return bool(re.search(r"\\d|\[0-9|\{\d|[\^$]", pattern))
474
+
475
+
395
476
  def sanitize_data(
396
477
  data: dict[str, Any],
397
478
  sensitive_patterns: Iterable[str],
@@ -415,16 +496,14 @@ def sanitize_data(
415
496
  continue
416
497
 
417
498
  if isinstance(value, str):
418
- sanitized[key] = "[REDACTED]" if detect_sensitive_data(value, sensitive_patterns) else value
499
+ sanitized[key] = redact_sensitive_text(value, sensitive_patterns)
419
500
  continue
420
501
 
421
502
  if isinstance(value, list):
422
503
  transformed: list[Any] = []
423
504
  for item in value:
424
505
  if isinstance(item, str):
425
- transformed.append(
426
- "[REDACTED]" if detect_sensitive_data(item, sensitive_patterns) else item
427
- )
506
+ transformed.append(redact_sensitive_text(item, sensitive_patterns))
428
507
  elif isinstance(item, dict):
429
508
  transformed.append(sanitize_data(item, sensitive_patterns, seen))
430
509
  else:
@@ -619,7 +698,12 @@ def load_config_from_env() -> LogsInterceptorConfig:
619
698
  filter=FilterConfig(
620
699
  levels=_env_levels(env.get("LOGS_FILTER_LEVELS")),
621
700
  sampling_rate=parse_float_range(env.get("LOGS_FILTER_SAMPLING_RATE"), 1.0, 0.0, 1.0),
622
- sanitize=parse_bool(env.get("LOGS_FILTER_SANITIZE"), True),
701
+ sanitize=parse_bool(
702
+ env.get("LOGS_FILTER_SANITIZE")
703
+ or env.get("LOGS_SANITIZE")
704
+ or env.get("UO_LOGS_SANITIZE"),
705
+ True,
706
+ ),
623
707
  max_message_length=parse_int_range(
624
708
  env.get("LOGS_FILTER_MAX_MESSAGE_LENGTH"), 8192, 64, 1_000_000
625
709
  ),