|
| 1 | +# Conformance |
| 2 | + |
| 3 | +Scenario-by-scenario status of this SDK against the LogTide SDK contract. |
| 4 | +Each scenario ID is stable across all official SDKs; "n/a" entries explain |
| 5 | +why a scenario does not apply. TODO entries are tracked work. |
| 6 | + |
| 7 | +| ID | Scenario | Status | Test reference | |
| 8 | +|---|---|---|---| |
| 9 | +| C01 | basic log: one POST to /api/v1/ingest with X-API-Key, {logs:[...]} body, RFC 3339 time, metadata.sdk | ✅ | `tests/test_v084.py` (paths/headers), `tests/test_spec_tier1.py` (sdk stamp) | |
| 10 | +| C02 | batch by size: batchSize entries flush automatically, order preserved | ✅ | `tests/test_client.py` (batching) | |
| 11 | +| C03 | batch by interval: entries delivered without explicit flush | partial | timer-based flush exists; no dedicated test | |
| 12 | +| C04 | wire format strictness: SDK fields nested in metadata, only contract fields top-level | ✅ | `tests/test_trace_w3c.py` (top-level trace fields), `test_v084.py` | |
| 13 | +| C05 | exception capture: structured metadata.exception with type/message/language/frames/cause | ✅ | `tests/test_client.py::test_error_serialization`, `test_v084.py` | |
| 14 | +| C06 | exception chain cap: cause depth ≤ 10, no infinite loop on cycles | ✅ | `tests/test_v084.py` (chained exceptions) | |
| 15 | +| C07 | retry on 5xx with growing backoff | ✅ | `tests/test_retry_policy.py` | |
| 16 | +| C08 | no retry on permanent 4xx (400/401/403/413) | ✅ | `tests/test_retry_policy.py` (400/401 not retried) | |
| 17 | +| C09 | Retry-After overrides computed backoff | ✅ | `tests/test_retry_policy.py::test_retry_after_overrides_backoff` | |
| 18 | +| C10 | circuit breaker opens after threshold failures | ✅ | `tests/test_client.py` (circuit breaker) | |
| 19 | +| C11 | circuit breaker half-open probe and recovery | ✅ | `logtide_sdk/circuit_breaker.py` half-open; covered in client tests | |
| 20 | +| C12 | buffer cap: drops beyond maxBufferSize, counted, never throws | ✅ | `tests/test_client.py` (buffer full silent drop) | |
| 21 | +| C13 | flush on close; capture after close is a silent no-op | partial | atexit + close() flush; add explicit post-close no-op test | |
| 22 | +| C14 | DSN parsing incl. base path; invalid DSN fails at init | ✅ | `tests/test_spec_tier1.py` (DSN incl. base path, init errors) | |
| 23 | +| C15 | inbound traceparent lands on entry trace_id | ✅ | `tests/middleware/test_trace_propagation.py` | |
| 24 | +| C16 | no PII by default; API key never logged | ✅ | explicit-only user context (`tests/test_scope.py`) | |
| 25 | +| C17 | serialisation robustness: circular/unserialisable values never throw | ✅ | `tests/test_client.py` (unjsonable payloads), `json_encoder` | |
| 26 | +| C18 | timestamp fidelity: time reflects capture, not delivery | ✅ | time stamped at LogEntry creation (`models.py`) | |
| 27 | +| C20 | scope isolation across concurrent requests | ✅ | `tests/middleware/test_trace_propagation.py` (isolated scopes), `tests/test_scope.py` (async tasks) | |
| 28 | +| C21 | breadcrumb ring buffer eviction, oldest first | ✅ | `tests/test_scope.py` (ring buffer) | |
| 29 | +| C22 | beforeSend can mutate or drop entries | TODO | beforeSend hook not implemented | |
| 30 | +| C23 | sampling: rate 0 sends nothing (logs) / no-op spans (traces) | TODO | sampling not implemented | |
| 31 | +| C24 | OTLP span export with service.name resource | TODO | span export: planned via OpenTelemetry exporter preset | |
| 32 | +| C25 | outbound traceparent injection on instrumented HTTP clients | TODO | outbound traceparent helper not implemented | |
| 33 | +| C26 | log/trace correlation: active span ids on entries | partial | scope trace context applied to entries; no span manager | |
| 34 | +| C27 | middleware error capture rethrows after logging | ✅ | middleware re-raise after logging (`middleware/*.py`) | |
| 35 | +| C28 | logging-bridge level mapping and scope context | ✅ | `tests/test_structlog.py`, `handler.py` stdlib mapping | |
0 commit comments