interloper-api 0.53.1__tar.gz → 0.55.0__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 (21) hide show
  1. {interloper_api-0.53.1 → interloper_api-0.55.0}/PKG-INFO +4 -1
  2. {interloper_api-0.53.1 → interloper_api-0.55.0}/pyproject.toml +5 -1
  3. {interloper_api-0.53.1 → interloper_api-0.55.0}/pyproject.toml.orig +5 -1
  4. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/admin.py +20 -0
  5. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/runs.py +19 -14
  6. {interloper_api-0.53.1 → interloper_api-0.55.0}/README.md +0 -0
  7. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/__init__.py +0 -0
  8. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/app.py +0 -0
  9. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/components.py +0 -0
  10. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/dependencies.py +0 -0
  11. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/email.py +0 -0
  12. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/__init__.py +0 -0
  13. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/agent.py +0 -0
  14. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/auth.py +0 -0
  15. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/backfills.py +0 -0
  16. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/catalog.py +0 -0
  17. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/components.py +0 -0
  18. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/oauth.py +0 -0
  19. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/organisations.py +0 -0
  20. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/tokens.py +0 -0
  21. {interloper_api-0.53.1 → interloper_api-0.55.0}/src/interloper_api/routes/ws.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: interloper-api
3
- Version: 0.53.1
3
+ Version: 0.55.0
4
4
  Summary: Interloper FastAPI routes
5
5
  Author: Guillaume Onfroy
6
6
  Author-email: Guillaume Onfroy <guillaume@digitlcloud.com>
@@ -13,7 +13,10 @@ Requires-Dist: psycopg2-binary>=2.9.0
13
13
  Requires-Dist: uvicorn[standard]>=0.41.0
14
14
  Requires-Dist: wsproto>=1.2.0
15
15
  Requires-Dist: interloper-agent ; extra == 'agent'
16
+ Requires-Dist: interloper-core[otel] ; extra == 'otel'
17
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.63b0 ; extra == 'otel'
16
18
  Requires-Python: >=3.10
17
19
  Provides-Extra: agent
20
+ Provides-Extra: otel
18
21
  Description-Content-Type: text/markdown
19
22
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "interloper-api"
3
- version = "0.53.1"
3
+ version = "0.55.0"
4
4
  description = "Interloper FastAPI routes"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -21,6 +21,10 @@ email = "guillaume@digitlcloud.com"
21
21
 
22
22
  [project.optional-dependencies]
23
23
  agent = ["interloper-agent"]
24
+ otel = [
25
+ "interloper-core[otel]",
26
+ "opentelemetry-instrumentation-fastapi>=0.63b0",
27
+ ]
24
28
 
25
29
  [build-system]
26
30
  requires = ["uv_build>=0.11.5,<0.12"]
@@ -3,7 +3,7 @@
3
3
  # ###############
4
4
  [project]
5
5
  name = "interloper-api"
6
- version = "0.53.1"
6
+ version = "0.55.0"
7
7
  description = "Interloper FastAPI routes"
8
8
  readme = "README.md"
9
9
  authors = [{ name = "Guillaume Onfroy", email = "guillaume@digitlcloud.com" }]
@@ -21,6 +21,10 @@ dependencies = [
21
21
 
22
22
  [project.optional-dependencies]
23
23
  agent = ["interloper-agent"]
24
+ otel = [
25
+ "interloper-core[otel]",
26
+ "opentelemetry-instrumentation-fastapi>=0.63b0",
27
+ ]
24
28
 
25
29
  [build-system]
26
30
  requires = ["uv_build>=0.11.5,<0.12"]
@@ -194,6 +194,17 @@ class AdminSmtpConfig(BaseModel):
194
194
  from_addr: str
195
195
 
196
196
 
197
+ class AdminTelemetryConfig(BaseModel):
198
+ """OpenTelemetry status (endpoint/headers reduced to booleans)."""
199
+
200
+ enabled: bool
201
+ protocol: str
202
+ endpoint_configured: bool
203
+ traces: bool
204
+ metrics: bool
205
+ sample_ratio: float
206
+
207
+
197
208
  class AdminServicesConfig(BaseModel):
198
209
  """Background service roles and their tuning."""
199
210
 
@@ -201,6 +212,7 @@ class AdminServicesConfig(BaseModel):
201
212
  worker: AdminWorkerConfig
202
213
  reaper: AdminReaperConfig
203
214
  smtp: AdminSmtpConfig
215
+ telemetry: AdminTelemetryConfig
204
216
  mcp_external_url: str
205
217
 
206
218
 
@@ -374,6 +386,14 @@ def build_config_snapshot(settings: Any, features: dict[str, bool], catalog: Any
374
386
  host=settings.smtp.host,
375
387
  from_addr=settings.smtp.from_addr,
376
388
  ),
389
+ telemetry=AdminTelemetryConfig(
390
+ enabled=settings.otel.enabled,
391
+ protocol=settings.otel.protocol,
392
+ endpoint_configured=bool(settings.otel.endpoint),
393
+ traces=settings.otel.traces,
394
+ metrics=settings.otel.metrics,
395
+ sample_ratio=settings.otel.sample_ratio,
396
+ ),
377
397
  mcp_external_url=settings.mcp.external_url,
378
398
  ),
379
399
  data=AdminDataConfig(
@@ -80,13 +80,15 @@ class EventResponse(BaseModel):
80
80
  org_id: UUID
81
81
  run_id: UUID | None
82
82
  event_type: str
83
- asset_id: UUID | None = None
84
- asset_key: str | None
83
+ component_id: UUID | None = None
84
+ component_kind: str | None
85
+ component_key: str | None
85
86
  partition_or_window: str | None
86
87
  error: str | None
87
88
  traceback: str | None
88
89
  message: str | None
89
90
  level: str | None
91
+ data: dict[str, object] | None
90
92
  timestamp: str
91
93
 
92
94
 
@@ -153,13 +155,15 @@ def _event_to_response(event: Event) -> EventResponse:
153
155
  org_id=event.org_id,
154
156
  run_id=event.run_id,
155
157
  event_type=event.event_type,
156
- asset_id=event.asset_id,
157
- asset_key=event.asset_key,
158
+ component_id=event.component_id,
159
+ component_kind=event.component_kind,
160
+ component_key=event.component_key,
158
161
  partition_or_window=event.partition_or_window,
159
162
  error=event.error,
160
163
  traceback=event.traceback,
161
164
  message=event.message,
162
165
  level=event.level,
166
+ data=event.data,
163
167
  timestamp=str(event.timestamp),
164
168
  )
165
169
 
@@ -273,7 +277,7 @@ def list_run_events(
273
277
  response: Response,
274
278
  limit: int = 100,
275
279
  offset: int = 0,
276
- asset_id: Annotated[list[UUID] | None, Query()] = None,
280
+ component_id: Annotated[list[UUID] | None, Query()] = None,
277
281
  event_type: Annotated[list[str] | None, Query()] = None,
278
282
  user: Profile = Depends(get_current_user),
279
283
  store: Store = Depends(get_store),
@@ -281,20 +285,21 @@ def list_run_events(
281
285
  """List events for a run, oldest first.
282
286
 
283
287
  Events are ordered ``timestamp ASC`` and paged with ``limit``/``offset``.
284
- ``asset_id`` and ``event_type`` may each be repeated to narrow the listing
285
- to one or more assets (e.g. every asset sharing a status) and/or event
286
- types (e.g. a "Lifecycle"/"Errors"/"Logs" tab); the two compose. The total
287
- number of matching events (ignoring ``limit``/``offset``, honouring the
288
- filters) is returned in the ``X-Total-Count`` response header so clients can
289
- page through every event — including the terminal/outcome events
290
- (``asset_completed``, ``asset_failed``, ``run_failed``, …) that sort last.
288
+ ``component_id`` and ``event_type`` may each be repeated to narrow the
289
+ listing to one or more components (e.g. every asset sharing a status)
290
+ and/or event types (e.g. a "Lifecycle"/"Errors"/"Logs" tab); the two
291
+ compose. The total number of matching events (ignoring
292
+ ``limit``/``offset``, honouring the filters) is returned in the
293
+ ``X-Total-Count`` response header so clients can page through every event
294
+ — including the terminal/outcome events (``asset_completed``,
295
+ ``asset_failed``, ``run_failed``, …) that sort last.
291
296
  """
292
297
  _load_authorized_run(run_id, user, store)
293
298
  limit = max(1, min(limit, MAX_EVENTS_PAGE_SIZE))
294
299
  offset = max(0, offset)
295
- total = store.count_events(run_id=run_id, asset_ids=asset_id, event_types=event_type)
300
+ total = store.count_events(run_id=run_id, component_ids=component_id, event_types=event_type)
296
301
  response.headers["X-Total-Count"] = str(total)
297
302
  events = store.list_events(
298
- run_id=run_id, asset_ids=asset_id, event_types=event_type, limit=limit, offset=offset
303
+ run_id=run_id, component_ids=component_id, event_types=event_type, limit=limit, offset=offset
299
304
  )
300
305
  return [_event_to_response(e) for e in events]