From de6d366dda99acc5027b124d054345ea6ba272fb Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Fri, 6 Nov 2026 18:45:41 +0400 Subject: [PATCH 1/2] Test that records written while a route runs carry its route (failing) policyengine-observability 3.0.4 writes `` as `http.route` on every record written while a FastAPI endpoint runs, because its middleware begins the request before FastAPI matches the route. These tests check the gateway's exception record for `/jobs/{job_id}` and the entrypoint's backend response event for the same route. They fail until the services lock 3.0.5 or later. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_app.py | 34 ++++++++++++++ .../tests/test_observability.py | 44 +++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/projects/policyengine-simulation-entry/tests/test_app.py b/projects/policyengine-simulation-entry/tests/test_app.py index 6c0443123..9598e9206 100644 --- a/projects/policyengine-simulation-entry/tests/test_app.py +++ b/projects/policyengine-simulation-entry/tests/test_app.py @@ -789,6 +789,40 @@ def test_job_status_records_structured_backend_telemetry( assert attributes["job_id"] == "fc-123" +def test_event_recorded_while_a_route_runs_carries_the_matched_route( + capsys: pytest.CaptureFixture[str], +): + backend = FakeBackend() + backend.responses[("GET", "/jobs/fc-123")] = response(202, {"status": "running"}) + # The runtime keeps the standard output it finds when it is built, so the + # app is built after capsys replaces it. + app = create_app( + settings=make_settings(), backend=backend, auth_dependency=lambda: None + ) + + from fastapi.testclient import TestClient + + with TestClient(app) as test_client: + capsys.readouterr() + job_response = test_client.get("/jobs/fc-123") + captured_output = capsys.readouterr().out + + assert job_response.status_code == 202 + routes_by_event_name: dict[object, list[object]] = {} + for output_line in captured_output.splitlines(): + try: + record = json.loads(output_line) + except json.JSONDecodeError: + continue + routes_by_event_name.setdefault(record.get("event.name"), []).append( + record.get("http.route") + ) + assert routes_by_event_name["simulation_entry_backend_response"] == [ + "/jobs/{job_id}" + ] + assert routes_by_event_name["request.completed"] == ["/jobs/{job_id}"] + + def test_budget_window_routes_use_original_batch_id(client, backend): backend.responses[("POST", "/simulate/economy/budget-window")] = response( 202, diff --git a/projects/policyengine-simulation-gateway/tests/test_observability.py b/projects/policyengine-simulation-gateway/tests/test_observability.py index 68b4930a1..ffe290059 100644 --- a/projects/policyengine-simulation-gateway/tests/test_observability.py +++ b/projects/policyengine-simulation-gateway/tests/test_observability.py @@ -1,10 +1,26 @@ """Gateway observability identity and request correlation tests.""" +import json + +import pytest from fastapi.testclient import TestClient from policyengine_observability import REQUEST_ID_HEADER from policyengine_simulation_gateway.testing import create_gateway_app +def _records_written(captured_output: str) -> list[dict[str, object]]: + """Return the JSON records the runtime wrote to standard output, in order.""" + records: list[dict[str, object]] = [] + for output_line in captured_output.splitlines(): + try: + record = json.loads(output_line) + except json.JSONDecodeError: + continue + if isinstance(record, dict): + records.append(record) + return records + + def test_gateway_preserves_policyengine_request_id(): app = create_gateway_app() response = TestClient(app).get( @@ -36,3 +52,31 @@ def test_gateway_response_survives_unavailable_collector(monkeypatch): assert response.status_code == 200 assert response.json() == {"status": "healthy"} + + +def test_exception_recorded_while_a_route_runs_carries_the_matched_route( + capsys: pytest.CaptureFixture[str], mock_modal +): + # The runtime keeps the standard output it finds when it is built, so the + # app is built after capsys replaces it. + client = TestClient(create_gateway_app(), raise_server_exceptions=False) + submit_response = client.post( + "/simulate/economy/comparison", + json={"country": "us", "scope": "macro", "reform": {}}, + ) + job_id = submit_response.json()["job_id"] + mock_modal["function_call"].from_id_errors[job_id] = RuntimeError( + "Modal control plane unavailable" + ) + capsys.readouterr() + + response = client.get(f"/jobs/{job_id}") + + assert response.status_code == 500 + routes_by_event_name: dict[object, list[object]] = {} + for record in _records_written(capsys.readouterr().out): + routes_by_event_name.setdefault(record["event.name"], []).append( + record.get("http.route") + ) + assert routes_by_event_name["exception.recorded"] == ["/jobs/{job_id}"] + assert routes_by_event_name["request.completed"] == ["/jobs/{job_id}"] From 63aa5a7c3421ff3b42edc468a3f9913d0e9fc6e9 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Fri, 6 Nov 2026 18:47:46 +0400 Subject: [PATCH 2/2] Require and lock policyengine-observability 3.0.6 3.0.5 reads the matched FastAPI route each time a record is written, so records written while an endpoint runs carry its route template instead of `` (PolicyEngine/policyengine-observability#40). 3.0.6 changes only the certifi version in that repository's own lock. Raise the floor to 3.0.6 in every pyproject that requires the package, and relock the six projects that hold it, upgrading only that package. Update the observability and type-checking guides to the new floor and describe which records carry the matched route. Co-Authored-By: Claude Opus 5.5 --- changelog.d/1018.fixed.md | 1 + docs/engineering/skills/observability.md | 17 ++++++++++++++--- docs/engineering/skills/type-checking.md | 6 +++--- libs/policyengine-simulation-contract/uv.lock | 8 ++++---- .../pyproject.toml | 2 +- .../uv.lock | 8 ++++---- libs/policyengine-stage12-persistence/uv.lock | 8 ++++---- .../pyproject.toml | 2 +- projects/policyengine-simulation-entry/uv.lock | 10 +++++----- .../pyproject.toml | 4 ++-- .../policyengine-simulation-executor/uv.lock | 14 +++++++------- .../pyproject.toml | 2 +- .../policyengine-simulation-gateway/uv.lock | 10 +++++----- 13 files changed, 52 insertions(+), 40 deletions(-) create mode 100644 changelog.d/1018.fixed.md diff --git a/changelog.d/1018.fixed.md b/changelog.d/1018.fixed.md new file mode 100644 index 000000000..eb419414b --- /dev/null +++ b/changelog.d/1018.fixed.md @@ -0,0 +1 @@ +Records the gateway and the entrypoint write while an endpoint runs, such as exception records and events, now carry the endpoint's route template as `http.route` (for example `/jobs/{job_id}`) instead of ``, so the daily telemetry error report groups them by route. Every service now requires policyengine-observability 3.0.6, which reads the matched route each time it writes a record. diff --git a/docs/engineering/skills/observability.md b/docs/engineering/skills/observability.md index c7ad2ac63..5332de28a 100644 --- a/docs/engineering/skills/observability.md +++ b/docs/engineering/skills/observability.md @@ -80,11 +80,22 @@ appropriate `StagePlan` and call `plan.name(Stage.VALUE)`. Do not add span name string literals in services or workers. Open a span with `runtime.span(plan.name(Stage.VALUE))`, and an operation with -`runtime.operation(...)`. policyengine-observability 3.0.4 types both scopes -correctly: their `__exit__` and `__aexit__` return `Literal[False]`, so Pyright -knows an exception raised in the block propagates; see +`runtime.operation(...)`. policyengine-observability 3.0.4 and later type both +scopes correctly: their `__exit__` and `__aexit__` return `Literal[False]`, so +Pyright knows an exception raised in the block propagates; see `docs/engineering/skills/type-checking.md`. +In every app instrumented with `init_simulation_observability` (the gateway, +the entrypoint and the executor's local FastAPI app), every record written +while a FastAPI endpoint runs, from `record_exception`, `event` or `log`, +carries the endpoint's route template as `http.route`, such as +`/jobs/{job_id}`, as the request's `request.completed` record does. +policyengine-observability 3.0.5 and later read the route when each record is +written; 3.0.4 wrote `` on every record written before the request +ended, because its middleware begins the request before FastAPI matches the +route. A record written before routing, such as one from a middleware, and a +request that matches no route still carry ``. + When adding a run configuration or runtime stage: 1. add it to `RunConfiguration` or `Stage`; diff --git a/docs/engineering/skills/type-checking.md b/docs/engineering/skills/type-checking.md index 56a444b58..1e0ff5ea2 100644 --- a/docs/engineering/skills/type-checking.md +++ b/docs/engineering/skills/type-checking.md @@ -174,11 +174,11 @@ section is still in the registry fails the guard on every pull request. - If an error shows a real bug, first write a test that demonstrates it, then fix it. - Open observability spans and operations with `runtime.span(...)` and - `runtime.operation(...)`. policyengine-observability 3.0.4 types them - correctly: their `__exit__` and `__aexit__` return `Literal[False]`, so + `runtime.operation(...)`. policyengine-observability 3.0.4 and later type + them correctly: their `__exit__` and `__aexit__` return `Literal[False]`, so Pyright knows they never suppress an exception and doesn't report a variable the block assigns as possibly unbound after it. Every package that depends - on policyengine-observability requires 3.0.4 or later, and + on policyengine-observability requires 3.0.6 or later, and `libs/policyengine-simulation-observability/tests/test_scope_exit_typing.py` fails if an older release is installed. - Before reading a simulation's output frames, narrow diff --git a/libs/policyengine-simulation-contract/uv.lock b/libs/policyengine-simulation-contract/uv.lock index 3fa7e7d15..6188bee12 100644 --- a/libs/policyengine-simulation-contract/uv.lock +++ b/libs/policyengine-simulation-contract/uv.lock @@ -1069,11 +1069,11 @@ wheels = [ [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -1145,7 +1145,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, diff --git a/libs/policyengine-simulation-observability/pyproject.toml b/libs/policyengine-simulation-observability/pyproject.toml index d7cf62251..0c203e3db 100644 --- a/libs/policyengine-simulation-observability/pyproject.toml +++ b/libs/policyengine-simulation-observability/pyproject.toml @@ -10,7 +10,7 @@ requires-python = ">=3.13" dependencies = [ "fastapi>=0.115.0", "pydantic>=2.0", - "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.4,<4", + "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.6,<4", ] [project.optional-dependencies] diff --git a/libs/policyengine-simulation-observability/uv.lock b/libs/policyengine-simulation-observability/uv.lock index 8e971eb08..6daa706b1 100644 --- a/libs/policyengine-simulation-observability/uv.lock +++ b/libs/policyengine-simulation-observability/uv.lock @@ -720,11 +720,11 @@ wheels = [ [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -768,7 +768,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, diff --git a/libs/policyengine-stage12-persistence/uv.lock b/libs/policyengine-stage12-persistence/uv.lock index 20d14c19b..dda65fe69 100644 --- a/libs/policyengine-stage12-persistence/uv.lock +++ b/libs/policyengine-stage12-persistence/uv.lock @@ -566,11 +566,11 @@ wheels = [ [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -627,7 +627,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, diff --git a/projects/policyengine-simulation-entry/pyproject.toml b/projects/policyengine-simulation-entry/pyproject.toml index 1b43b4f1d..e1330304a 100644 --- a/projects/policyengine-simulation-entry/pyproject.toml +++ b/projects/policyengine-simulation-entry/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ "fastapi>=0.115.0,<1", "httpx>=0.28.0,<1", "modal>=1.4,<2", - "policyengine-observability[fastapi,google,httpx,otlp-grpc]>=3.0.4,<4", + "policyengine-observability[fastapi,google,httpx,otlp-grpc]>=3.0.6,<4", "policyengine-simulation-contract", "policyengine-simulation-observability", "policyengine-stage12-persistence", diff --git a/projects/policyengine-simulation-entry/uv.lock b/projects/policyengine-simulation-entry/uv.lock index e9a587c24..0eb687564 100644 --- a/projects/policyengine-simulation-entry/uv.lock +++ b/projects/policyengine-simulation-entry/uv.lock @@ -840,11 +840,11 @@ wheels = [ [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -925,7 +925,7 @@ requires-dist = [ { name = "httpx", specifier = ">=0.28.0,<1" }, { name = "modal", specifier = ">=1.4,<2" }, { name = "openapi-python-client", marker = "extra == 'build'", specifier = ">=0.21.6" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "httpx", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "httpx", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "policyengine-simulation-contract", editable = "../../libs/policyengine-simulation-contract" }, { name = "policyengine-simulation-observability", editable = "../../libs/policyengine-simulation-observability" }, { name = "policyengine-stage12-persistence", editable = "../../libs/policyengine-stage12-persistence" }, @@ -954,7 +954,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, diff --git a/projects/policyengine-simulation-executor/pyproject.toml b/projects/policyengine-simulation-executor/pyproject.toml index faf357acd..759254cd3 100644 --- a/projects/policyengine-simulation-executor/pyproject.toml +++ b/projects/policyengine-simulation-executor/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "policyengine[models]==6.12.1", "tables>=3.10.2", "modal>=0.73.0", - "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.4,<4", + "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.6,<4", # Imported directly by the artifact store client; do not rely on the # transitive pin via policyengine. "google-cloud-storage>=2", @@ -49,7 +49,7 @@ modal-simulation-image = [ "policyengine[models]==6.12.1", "fastapi>=0.115.0", "tables>=3.10.2", - "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.4,<4", + "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.6,<4", # The artifact fetch layer and store client read GCS. The lib is also a # transitive dependency of policyengine, but the image must not depend # on an upstream package keeping it. diff --git a/projects/policyengine-simulation-executor/uv.lock b/projects/policyengine-simulation-executor/uv.lock index c74de3a42..58d9baca7 100644 --- a/projects/policyengine-simulation-executor/uv.lock +++ b/projects/policyengine-simulation-executor/uv.lock @@ -1840,11 +1840,11 @@ provides-extras = ["test", "build"] [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -1953,7 +1953,7 @@ requires-dist = [ { name = "opentelemetry-instrumentation-sqlalchemy", specifier = ">=0.65b0,<0.66" }, { name = "policyengine", extras = ["models"], specifier = "==6.12.1" }, { name = "policyengine-fastapi", editable = "../../libs/policyengine-fastapi" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "policyengine-simulation-contract", extras = ["modal"], editable = "../../libs/policyengine-simulation-contract" }, { name = "policyengine-simulation-observability", editable = "../../libs/policyengine-simulation-observability" }, { name = "policyengine-stage12-persistence", editable = "../../libs/policyengine-stage12-persistence" }, @@ -1974,7 +1974,7 @@ modal-simulation-image = [ { name = "google-cloud-storage", specifier = ">=2" }, { name = "huggingface-hub", specifier = ">=1,<2" }, { name = "policyengine", extras = ["models"], specifier = "==6.12.1" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "psycopg", extras = ["binary"], specifier = ">=3.2,<4" }, { name = "pyarrow", specifier = ">=20,<24" }, { name = "sqlalchemy", specifier = ">=2,<3" }, @@ -2004,7 +2004,7 @@ requires-dist = [ { name = "modal", specifier = ">=1.4,<2" }, { name = "openapi-python-client", marker = "extra == 'build'", specifier = ">=0.21.6" }, { name = "packaging", specifier = ">=24" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyjwt", specifier = ">=2.10.1,<3.0.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, @@ -2036,7 +2036,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" }, diff --git a/projects/policyengine-simulation-gateway/pyproject.toml b/projects/policyengine-simulation-gateway/pyproject.toml index 4518faa1e..4f5343dcc 100644 --- a/projects/policyengine-simulation-gateway/pyproject.toml +++ b/projects/policyengine-simulation-gateway/pyproject.toml @@ -25,7 +25,7 @@ dependencies = [ "pyjwt>=2.10.1,<3.0.0", # JWTDecoder (policyengine-fastapi lib) needs cryptography at runtime. "cryptography>=41.0.0", - "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.4,<4", + "policyengine-observability[fastapi,google,otlp-grpc]>=3.0.6,<4", "modal>=1.4,<2", ] diff --git a/projects/policyengine-simulation-gateway/uv.lock b/projects/policyengine-simulation-gateway/uv.lock index 8e709799d..90d70cb8d 100644 --- a/projects/policyengine-simulation-gateway/uv.lock +++ b/projects/policyengine-simulation-gateway/uv.lock @@ -1261,11 +1261,11 @@ provides-extras = ["test", "build"] [[package]] name = "policyengine-observability" -version = "3.0.4" +version = "3.0.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/d0/09b91aca37fb3efd493c164082097e85705fcac2062d2b5ef8a8c4e2be04/policyengine_observability-3.0.4.tar.gz", hash = "sha256:7e43a5d0e9b9e5f683623643efca7c47e651baaad7b557a50ec8b344602dc61f", size = 127972, upload-time = "2026-10-27T17:23:24.343Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/1e/3d7f7e22a415b27d6fc19739035df979dc9365d1e8b2fe39043cf55f25f5/policyengine_observability-3.0.6.tar.gz", hash = "sha256:648824176568342f0b048321cfc44e36098be49f143e52c567614add8c11fc2b", size = 129369, upload-time = "2026-11-04T10:22:28.886Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/00/d9c4850a12b4d0bef72034316909aac97228de302384af8936a958b7dc8e/policyengine_observability-3.0.4-py3-none-any.whl", hash = "sha256:1b3ebbfd00c138abcc2ec9580b13aa55679b91745783c5567cc73f8b2bbaaaf7", size = 42204, upload-time = "2026-10-27T17:23:22.641Z" }, + { url = "https://files.pythonhosted.org/packages/4e/d8/2e3b75e5b46d95af30891802260bc04ef11882732539ac31a09e9ae4d33e/policyengine_observability-3.0.6-py3-none-any.whl", hash = "sha256:364585ddfa2a9af14154049661c0d9c931185c42409bf3292d736a12d662cda0", size = 42575, upload-time = "2026-11-04T10:22:27.359Z" }, ] [package.optional-dependencies] @@ -1355,7 +1355,7 @@ requires-dist = [ { name = "modal", specifier = ">=1.4,<2" }, { name = "openapi-python-client", marker = "extra == 'build'", specifier = ">=0.21.6" }, { name = "packaging", specifier = ">=24" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyjwt", specifier = ">=2.10.1,<3.0.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, @@ -1387,7 +1387,7 @@ requires-dist = [ { name = "black", marker = "extra == 'build'", specifier = ">=25.1.0" }, { name = "fastapi", specifier = ">=0.115.0" }, { name = "httpx2", marker = "extra == 'test'" }, - { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.4,<4" }, + { name = "policyengine-observability", extras = ["fastapi", "google", "otlp-grpc"], specifier = ">=3.0.6,<4" }, { name = "pydantic", specifier = ">=2.0" }, { name = "pyright", marker = "extra == 'build'", specifier = ">=1.1.401" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.3.4" },