log-foundry 0.10.2.dev128__tar.gz → 0.10.2.dev129__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.
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/PKG-INFO +5 -4
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/README.md +4 -3
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/pyproject.toml +1 -1
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/__init__.py +2 -2
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/config.py +8 -2
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/ids.py +3 -1
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/kinesis.py +8 -3
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/LICENSE +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/_diag.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/_fork.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/_lifecycle.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/api.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/console.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/context.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/decorator.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/model.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/py.typed +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/results.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sanitize.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/__init__.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/_batch.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/_chunk.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/_retry.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/_socket.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/_time.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/base.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/callback.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/clickhouse.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/datadog.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/elasticsearch.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/eventhubs.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/file.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/filtering.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/firehose.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/honeycomb.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/http.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/kafka.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/logging_sink.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/logstash.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/loki.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/memory.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/mongodb.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/multi.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/nats.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/newrelic.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/null.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/postgres.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/pubsub.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/rabbitmq.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/redis.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/sentry.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/sns.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/splunk.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/sqlite.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/sqs.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/stdout.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/syslog.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/transform.py +0 -0
- {log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/worker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: log-foundry
|
|
3
|
-
Version: 0.10.2.
|
|
3
|
+
Version: 0.10.2.dev129
|
|
4
4
|
Summary: Generate logs for your console and JSON events for downstream consumption.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -1086,7 +1086,7 @@ They tell you different things, and they want different responses:
|
|
|
1086
1086
|
|
|
1087
1087
|
| Field | Means | What to do |
|
|
1088
1088
|
|---|---|---|
|
|
1089
|
-
| `dropped` | The queue filled — the destination is not keeping up. Delivery continues. | Make the destination keep up: scale the sink, or reduce what you log. The worker's batch size, flush interval and queue depth are **not** reachable from the public API, so tuning them is not an option this version offers you. |
|
|
1089
|
+
| `dropped` | The queue filled — the destination is not keeping up. Delivery continues. It counts **submissions** — one per span close, or per open span a `flush()` sweeps — so the events lost are a multiple of it. | Make the destination keep up: scale the sink, or reduce what you log. The worker's batch size, flush interval and queue depth are **not** reachable from the public API, so tuning them is not an option this version offers you. |
|
|
1090
1090
|
| `failed_batches` | A sink stayed broken through the whole retry budget. Delivery continues. | Fix the destination. |
|
|
1091
1091
|
| `stopped_reason` | The background thread **died** on that exception type. Nothing further will be delivered, ever. | Restart the process; investigate the named exception. |
|
|
1092
1092
|
| `sink.dropped` | The sink discarded events **before** attempting delivery — an oversized record, or one the client refused outright. | Read the stderr line: it names the cause. An oversized record means shrink what you log; a refused local produce/publish (Kafka, Pub/Sub) points at the client — a saturated buffer, a bad topic, a credential. |
|
|
@@ -1095,12 +1095,13 @@ They tell you different things, and they want different responses:
|
|
|
1095
1095
|
| `incomplete_swaps` | A late `configure(sink=...)` could not confirm the previous sink was drained. The swap took effect; that sink was left open and some queued events may have gone to the new one. | Investigate the previous sink — it was hung or failing. Configure the sink before the first log where you can. |
|
|
1096
1096
|
| `inherited_sink` | This process is delivering to a sink it **inherited across a `fork`** and may not release, so it will not be closed here. Not a loss and not an alert term. | Nothing, usually. It explains a handle still open after `shutdown()`, and tells you a deployment shares one sink across a fork at all. `True` for a shared `StdoutSink` too, whose `close()` only flushes — so a `True` is not by itself evidence that anything is held. If you want the child to own its transport, build the sink in the worker process (see Forking). |
|
|
1097
1097
|
| `orphan_lost` | An event logged **with no open span** never reached the sink. That call emits on your own thread with no worker behind it, so no other field here can carry it — it is not a batch, there was no retry, and there may be no worker at all. Covers a sink that failed to *construct* as well as one that raised. | Fix the destination, or the data. The stderr line names the exception type. If a process logs this way at all, this is the field to alert on: nothing else describes that path. |
|
|
1098
|
-
| `in_span_lost` | An event logged **inside a span**
|
|
1098
|
+
| `in_span_lost` | An event logged **inside a span** was lost before delivery, for one of two reasons the count tells apart: **the data** — a value that could not be turned into an event, one per call — or **no drain thread at all** — the process could not start the worker, and the span's whole buffer is counted at once (SPEC-050). Never a destination that failed at delivery; that is `failed_batches`. | One event at a time: fix the call site — a non-string message (an exception object, say) is the common cause. A whole buffer at once: the process cannot start a thread; the stderr line names it. |
|
|
1099
1099
|
| `closing_sinks` | Swapped-out sinks inside `close()` **right now** — a live gauge, not a counter. It and `queued` are the two fields here that fall as well as rise; the other integer counters only climb. Non-zero on a single read is normal during a swap. | Nothing, unless it stays non-zero. That means a destination is stuck in `close()` and will not release its resources. |
|
|
1100
1100
|
|
|
1101
1101
|
`orphan_lost` and `in_span_lost` are deliberately two fields and their sum is deliberately not
|
|
1102
1102
|
reported. They aggregate different failure populations — one can mean the destination *or* the
|
|
1103
|
-
data
|
|
1103
|
+
data; the other never the destination — the data, or no drain thread at all (SPEC-050) — so a
|
|
1104
|
+
single number would hide which fix applies.
|
|
1104
1105
|
|
|
1105
1106
|
`h.sink` is a `SinkLosses`, carrying `dropped` and `failed`, or `None` — `None` when no worker
|
|
1106
1107
|
exists yet, or when the configured sink reports nothing (`losses()` is optional, and a sink whose
|
|
@@ -1035,7 +1035,7 @@ They tell you different things, and they want different responses:
|
|
|
1035
1035
|
|
|
1036
1036
|
| Field | Means | What to do |
|
|
1037
1037
|
|---|---|---|
|
|
1038
|
-
| `dropped` | The queue filled — the destination is not keeping up. Delivery continues. | Make the destination keep up: scale the sink, or reduce what you log. The worker's batch size, flush interval and queue depth are **not** reachable from the public API, so tuning them is not an option this version offers you. |
|
|
1038
|
+
| `dropped` | The queue filled — the destination is not keeping up. Delivery continues. It counts **submissions** — one per span close, or per open span a `flush()` sweeps — so the events lost are a multiple of it. | Make the destination keep up: scale the sink, or reduce what you log. The worker's batch size, flush interval and queue depth are **not** reachable from the public API, so tuning them is not an option this version offers you. |
|
|
1039
1039
|
| `failed_batches` | A sink stayed broken through the whole retry budget. Delivery continues. | Fix the destination. |
|
|
1040
1040
|
| `stopped_reason` | The background thread **died** on that exception type. Nothing further will be delivered, ever. | Restart the process; investigate the named exception. |
|
|
1041
1041
|
| `sink.dropped` | The sink discarded events **before** attempting delivery — an oversized record, or one the client refused outright. | Read the stderr line: it names the cause. An oversized record means shrink what you log; a refused local produce/publish (Kafka, Pub/Sub) points at the client — a saturated buffer, a bad topic, a credential. |
|
|
@@ -1044,12 +1044,13 @@ They tell you different things, and they want different responses:
|
|
|
1044
1044
|
| `incomplete_swaps` | A late `configure(sink=...)` could not confirm the previous sink was drained. The swap took effect; that sink was left open and some queued events may have gone to the new one. | Investigate the previous sink — it was hung or failing. Configure the sink before the first log where you can. |
|
|
1045
1045
|
| `inherited_sink` | This process is delivering to a sink it **inherited across a `fork`** and may not release, so it will not be closed here. Not a loss and not an alert term. | Nothing, usually. It explains a handle still open after `shutdown()`, and tells you a deployment shares one sink across a fork at all. `True` for a shared `StdoutSink` too, whose `close()` only flushes — so a `True` is not by itself evidence that anything is held. If you want the child to own its transport, build the sink in the worker process (see Forking). |
|
|
1046
1046
|
| `orphan_lost` | An event logged **with no open span** never reached the sink. That call emits on your own thread with no worker behind it, so no other field here can carry it — it is not a batch, there was no retry, and there may be no worker at all. Covers a sink that failed to *construct* as well as one that raised. | Fix the destination, or the data. The stderr line names the exception type. If a process logs this way at all, this is the field to alert on: nothing else describes that path. |
|
|
1047
|
-
| `in_span_lost` | An event logged **inside a span**
|
|
1047
|
+
| `in_span_lost` | An event logged **inside a span** was lost before delivery, for one of two reasons the count tells apart: **the data** — a value that could not be turned into an event, one per call — or **no drain thread at all** — the process could not start the worker, and the span's whole buffer is counted at once (SPEC-050). Never a destination that failed at delivery; that is `failed_batches`. | One event at a time: fix the call site — a non-string message (an exception object, say) is the common cause. A whole buffer at once: the process cannot start a thread; the stderr line names it. |
|
|
1048
1048
|
| `closing_sinks` | Swapped-out sinks inside `close()` **right now** — a live gauge, not a counter. It and `queued` are the two fields here that fall as well as rise; the other integer counters only climb. Non-zero on a single read is normal during a swap. | Nothing, unless it stays non-zero. That means a destination is stuck in `close()` and will not release its resources. |
|
|
1049
1049
|
|
|
1050
1050
|
`orphan_lost` and `in_span_lost` are deliberately two fields and their sum is deliberately not
|
|
1051
1051
|
reported. They aggregate different failure populations — one can mean the destination *or* the
|
|
1052
|
-
data
|
|
1052
|
+
data; the other never the destination — the data, or no drain thread at all (SPEC-050) — so a
|
|
1053
|
+
single number would hide which fix applies.
|
|
1053
1054
|
|
|
1054
1055
|
`h.sink` is a `SinkLosses`, carrying `dropped` and `failed`, or `None` — `None` when no worker
|
|
1055
1056
|
exists yet, or when the configured sink reports nothing (`losses()` is optional, and a sink whose
|
|
@@ -74,7 +74,7 @@ keywords = [
|
|
|
74
74
|
# vulnerability-reporting channel. The repository is still named `log-forge` — the ORIGINAL name,
|
|
75
75
|
# which PyPI rejected for the distribution — so these URLs deliberately do not match the package
|
|
76
76
|
# name. See the note on `name` above before "correcting" them.
|
|
77
|
-
version = "0.10.2.
|
|
77
|
+
version = "0.10.2.dev129"
|
|
78
78
|
|
|
79
79
|
[project.urls]
|
|
80
80
|
Homepage = "https://github.com/agriffi10/log-forge"
|
|
@@ -87,8 +87,8 @@ def health() -> Health:
|
|
|
87
87
|
an event that cannot be *built* never reaches a queue at all — so every other field here
|
|
88
88
|
describes machinery those two losses never touched, and a process that only logs outside a
|
|
89
89
|
span read all zeros over total loss until they existed. They stay separate because one can
|
|
90
|
-
mean the destination or the data and the other
|
|
91
|
-
nobody can act on.
|
|
90
|
+
mean the destination or the data and the other never the destination — the data, or no drain
|
|
91
|
+
thread at all (SPEC-050 FR-003); their sum is a number nobody can act on.
|
|
92
92
|
|
|
93
93
|
``retired`` alone is not a fault — a process that shuts down and then stops logging is
|
|
94
94
|
doing the right thing, which is why it is paired with the count rather than alerted on.
|
|
@@ -271,7 +271,12 @@ def get_config() -> Config:
|
|
|
271
271
|
validation :func:`configure` performs — ``max_value_bytes = 0`` was accepted and emptied
|
|
272
272
|
every event it touched. Both measured. :func:`configure` is the only route to a change.
|
|
273
273
|
|
|
274
|
-
It is a **copy**, not the frozen original, and ``defaults`` is copied with it
|
|
274
|
+
It is a **copy**, not the frozen original, and ``defaults`` is copied with it — **one level
|
|
275
|
+
deep**: the mapping is the caller's own, its values are shared with the library, so a nested
|
|
276
|
+
mutable value edited through the copy still reaches every later event (2026-09-04 audit,
|
|
277
|
+
N8). Deep-copying was declined because a default can be any object and copying an arbitrary
|
|
278
|
+
object can raise or be wrong; a caller who needs isolation for a nested value copies it. A
|
|
279
|
+
caller who
|
|
275
280
|
defeats the freeze — ``object.__setattr__`` reaches through any frozen dataclass — then
|
|
276
281
|
edits an object the library does not read, rather than the live config; and ``defaults`` is
|
|
277
282
|
a plain mutable ``dict``, so sharing it would leave the freeze cosmetic at the one field
|
|
@@ -282,7 +287,8 @@ def get_config() -> Config:
|
|
|
282
287
|
None.
|
|
283
288
|
|
|
284
289
|
Returns:
|
|
285
|
-
A copy of the process-wide :class:`Config`, with its own ``defaults
|
|
290
|
+
A copy of the process-wide :class:`Config`, with its own top-level ``defaults`` mapping
|
|
291
|
+
whose values are shared.
|
|
286
292
|
|
|
287
293
|
Raises:
|
|
288
294
|
None.
|
|
@@ -137,7 +137,9 @@ def parse_traceparent(value: object) -> tuple[str, str] | None:
|
|
|
137
137
|
its own identity.
|
|
138
138
|
|
|
139
139
|
Args:
|
|
140
|
-
value: An inbound header value of any type, from outside the process.
|
|
140
|
+
value: An inbound header value of any type, from outside the process. Surrounding
|
|
141
|
+
whitespace is stripped before parsing, since a header value arrives trimmed from some
|
|
142
|
+
transports and not others; whitespace anywhere else is a malformed field.
|
|
141
143
|
|
|
142
144
|
Returns:
|
|
143
145
|
A ``(trace_id, span_id)`` tuple, or ``None`` if the value is unusable.
|
|
@@ -282,11 +282,15 @@ class KinesisSink:
|
|
|
282
282
|
|
|
283
283
|
|
|
284
284
|
MAX_PARTITION_KEY_BYTES = 256
|
|
285
|
-
"""
|
|
285
|
+
"""This sink's ceiling on a ``PutRecords`` partition key, in UTF-8 bytes.
|
|
286
|
+
|
|
287
|
+
At or below the service's own limit, which its API reference states as 256 **characters**: a
|
|
288
|
+
byte bound is stricter for any non-ASCII key and therefore safe (2026-09-04 audit, N12).
|
|
289
|
+
"""
|
|
286
290
|
|
|
287
291
|
|
|
288
292
|
def _partition_key(raw: str) -> str:
|
|
289
|
-
"""Bounds a partition key to
|
|
293
|
+
"""Bounds a partition key to 256 UTF-8 **bytes**, at or below the service's 256-character limit.
|
|
290
294
|
|
|
291
295
|
Both encodes carry an ``errors=`` and both are load-bearing. Assembly replaces a lone
|
|
292
296
|
surrogate since SPEC-055 FR-001, so an event field cannot carry one — but this key is derived
|
|
@@ -319,7 +323,8 @@ def _record_size(record: dict[str, Any]) -> int:
|
|
|
319
323
|
"""Measures one request entry, partition key included (SPEC-038 FR-009).
|
|
320
324
|
|
|
321
325
|
``PutRecords`` charges the partition key against the 5 MiB request limit, and a key may be up
|
|
322
|
-
to 256 bytes, so a 500-record request could
|
|
326
|
+
to 256 characters at the service (bounded here to 256 bytes), so a 500-record request could
|
|
327
|
+
understate itself by ~128 KB — enough to have the
|
|
323
328
|
service reject a chunk this sink believed was inside the budget. ``SQSSink`` charges its FIFO
|
|
324
329
|
ids for the same reason and records the same rationale.
|
|
325
330
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/elasticsearch.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{log_foundry-0.10.2.dev128 → log_foundry-0.10.2.dev129}/src/log_foundry/sinks/logging_sink.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|