logging-objects-with-schema 1.0.3__tar.gz → 1.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logging-objects-with-schema
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: Schema-aware Python logging with strict extra validation and schema-driven field projection.
5
5
  Keywords: logging,schema,validation,structured-logging,structured-logs
6
6
  Author: Dmitrii Safronov
@@ -23,6 +23,13 @@ Description-Content-Type: text/markdown
23
23
 
24
24
  # python-logging-objects-with-schema
25
25
 
26
+ Arbitrary `extra` fields let log producers use different names, structures, and
27
+ types for the same information, making downstream searches, alerts, and
28
+ dashboards harder to maintain. A shared schema makes these structured fields a
29
+ contract between producers and consumers. `SchemaLogger` emits the valid fields
30
+ and reports data-validation violations separately, so a malformed field does
31
+ not discard the valid part of the record.
32
+
26
33
  `SchemaLogger` extends Python's standard `logging.Logger` with schema-driven
27
34
  validation and projection of `extra` fields. It preserves the standard logging
28
35
  API while invalid structured data is dropped and reported separately.
@@ -236,8 +243,10 @@ An example of a valid empty schema (no leaves, no problems):
236
243
  - **`item_type`**: Optional field for list-typed leaves. Must be a string if
237
244
  present. See "List-typed fields" section below.
238
245
  - **Root key restrictions**: Root keys cannot conflict with standard `logging`
239
- module fields (e.g., `name`, `levelno`, `pathname`). Such conflicts cause
240
- schema validation to fail.
246
+ module fields (e.g., `name`, `levelno`, `pathname`). This includes the
247
+ `message` and `asctime` fields, which are populated by formatters and are
248
+ rejected by `logging.Logger.makeRecord()`. Such conflicts cause schema
249
+ validation to fail.
241
250
 
242
251
  **List-typed fields:**
243
252
 
@@ -1,5 +1,12 @@
1
1
  # python-logging-objects-with-schema
2
2
 
3
+ Arbitrary `extra` fields let log producers use different names, structures, and
4
+ types for the same information, making downstream searches, alerts, and
5
+ dashboards harder to maintain. A shared schema makes these structured fields a
6
+ contract between producers and consumers. `SchemaLogger` emits the valid fields
7
+ and reports data-validation violations separately, so a malformed field does
8
+ not discard the valid part of the record.
9
+
3
10
  `SchemaLogger` extends Python's standard `logging.Logger` with schema-driven
4
11
  validation and projection of `extra` fields. It preserves the standard logging
5
12
  API while invalid structured data is dropped and reported separately.
@@ -213,8 +220,10 @@ An example of a valid empty schema (no leaves, no problems):
213
220
  - **`item_type`**: Optional field for list-typed leaves. Must be a string if
214
221
  present. See "List-typed fields" section below.
215
222
  - **Root key restrictions**: Root keys cannot conflict with standard `logging`
216
- module fields (e.g., `name`, `levelno`, `pathname`). Such conflicts cause
217
- schema validation to fail.
223
+ module fields (e.g., `name`, `levelno`, `pathname`). This includes the
224
+ `message` and `asctime` fields, which are populated by formatters and are
225
+ rejected by `logging.Logger.makeRecord()`. Such conflicts cause schema
226
+ validation to fail.
218
227
 
219
228
  **List-typed fields:**
220
229
 
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "logging-objects-with-schema"
7
- version = "1.0.3"
7
+ version = "1.0.4"
8
8
  description = "Schema-aware Python logging with strict extra validation and schema-driven field projection."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "logging-objects-with-schema"
7
- version = "1.0.3"
7
+ version = "1.0.4"
8
8
  description = "Schema-aware Python logging with strict extra validation and schema-driven field projection."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -645,11 +645,16 @@ def _get_builtin_logrecord_attributes() -> set[str]:
645
645
  Returns:
646
646
  Set of attribute names that are reserved by the logging system.
647
647
  Examples include: 'name', 'levelno', 'pathname', 'lineno', 'msg', etc.
648
+ Also includes 'message' and 'asctime', which are not set on a fresh
649
+ LogRecord instance but are rejected by Logger.makeRecord() and
650
+ populated by formatters.
648
651
 
649
652
  Example:
650
653
  >>> forbidden = _get_builtin_logrecord_attributes()
651
654
  >>> "name" in forbidden
652
655
  True
656
+ >>> "message" in forbidden
657
+ True
653
658
  >>> "ServicePayload" in forbidden
654
659
  False
655
660
  """
@@ -672,6 +677,12 @@ def _get_builtin_logrecord_attributes() -> set[str]:
672
677
  if not callable(attr_value):
673
678
  forbidden.add(attr_name)
674
679
 
680
+ # makeRecord() rejects these names even though dir(record) does not list
681
+ # them: both "message" and "asctime" are set by Formatter.format() before
682
+ # formatting. Without this, such root keys would pass schema validation
683
+ # and later raise KeyError when a log record is created.
684
+ forbidden.update({"message", "asctime"})
685
+
675
686
  return forbidden
676
687
 
677
688