Skip to content

Commit d0dc4cc

Browse files
committed
Add multi-payload HTTP API, updated UI templates, and OpenAPI spec
Server API and UI changes for groups and multi-part payloads: - New /payload/{payload_id}/content route for individual payload access - Updated observation create/get/list endpoints for multi-payload support - Updated HTML templates for rendering multiple payloads - Updated OpenAPI specification
1 parent 4a77984 commit d0dc4cc

File tree

11 files changed

+487
-157
lines changed

11 files changed

+487
-157
lines changed

crates/observation-tools-client/openapi.json

Lines changed: 122 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,15 @@
8383
},
8484
{
8585
"properties": {
86-
"payload": {
87-
"$ref": "#/components/schemas/PayloadOrPointerResponse"
86+
"payloads": {
87+
"items": {
88+
"$ref": "#/components/schemas/GetPayload"
89+
},
90+
"type": "array"
8891
}
8992
},
9093
"required": [
91-
"payload"
94+
"payloads"
9295
],
9396
"type": "object"
9497
}
@@ -105,6 +108,39 @@
105108
],
106109
"type": "object"
107110
},
111+
"GetPayload": {
112+
"properties": {
113+
"data": {
114+
"$ref": "#/components/schemas/PayloadOrPointerResponse"
115+
},
116+
"id": {
117+
"$ref": "#/components/schemas/PayloadId"
118+
},
119+
"mime_type": {
120+
"type": "string"
121+
},
122+
"name": {
123+
"type": "string"
124+
},
125+
"size": {
126+
"minimum": 0,
127+
"type": "integer"
128+
}
129+
},
130+
"required": [
131+
"id",
132+
"name",
133+
"mime_type",
134+
"size",
135+
"data"
136+
],
137+
"type": "object"
138+
},
139+
"GroupId": {
140+
"description": "Unique identifier for a group\n\nGroup IDs are user-provided strings. By default, a UUID v7 string is generated,\nbut any string value is accepted.",
141+
"example": "018e9a3a2c1b7e3f8d2a4b5c6d7e8f9b",
142+
"type": "string"
143+
},
108144
"ListExecutionsResponse": {
109145
"description": "Response for listing executions",
110146
"properties": {
@@ -170,17 +206,17 @@
170206
"$ref": "#/components/schemas/ExecutionId",
171207
"description": "ID of the execution this observation belongs to"
172208
},
173-
"id": {
174-
"$ref": "#/components/schemas/ObservationId",
175-
"description": "Unique identifier for this observation"
176-
},
177-
"labels": {
178-
"description": "Hierarchical labels for grouping observations\nUses path convention (e.g., \"api/request/headers\")",
209+
"group_ids": {
210+
"description": "IDs of groups this observation belongs to",
179211
"items": {
180-
"type": "string"
212+
"$ref": "#/components/schemas/GroupId"
181213
},
182214
"type": "array"
183215
},
216+
"id": {
217+
"$ref": "#/components/schemas/ObservationId",
218+
"description": "Unique identifier for this observation"
219+
},
184220
"log_level": {
185221
"$ref": "#/components/schemas/LogLevel",
186222
"description": "Log level for this observation"
@@ -195,10 +231,6 @@
195231
},
196232
"type": "object"
197233
},
198-
"mime_type": {
199-
"description": "MIME type of the payload (e.g., \"text/plain\", \"application/json\")",
200-
"type": "string"
201-
},
202234
"name": {
203235
"description": "User-defined name for this observation",
204236
"type": "string"
@@ -207,16 +239,16 @@
207239
"$ref": "#/components/schemas/ObservationType",
208240
"description": "Type of observation"
209241
},
242+
"parent_group_id": {
243+
"$ref": "#/components/schemas/GroupId",
244+
"description": "Parent group ID (used when observation_type == Group)",
245+
"nullable": true
246+
},
210247
"parent_span_id": {
211248
"description": "Parent span ID (for tracing integration)",
212249
"nullable": true,
213250
"type": "string"
214251
},
215-
"payload_size": {
216-
"description": "Size of the payload in bytes",
217-
"minimum": 0,
218-
"type": "integer"
219-
},
220252
"source": {
221253
"$ref": "#/components/schemas/SourceInfo",
222254
"description": "Source location where this observation was created",
@@ -229,9 +261,7 @@
229261
"name",
230262
"observation_type",
231263
"log_level",
232-
"created_at",
233-
"mime_type",
234-
"payload_size"
264+
"created_at"
235265
],
236266
"type": "object"
237267
},
@@ -245,10 +275,16 @@
245275
"enum": [
246276
"LogEntry",
247277
"Payload",
248-
"Span"
278+
"Span",
279+
"Group"
249280
],
250281
"type": "string"
251282
},
283+
"PayloadId": {
284+
"description": "Unique identifier for a payload (UUIDv7)",
285+
"example": "018e9a3a2c1b7e3f8d2a4b5c6d7e8f9c",
286+
"type": "string"
287+
},
252288
"PayloadOrPointerResponse": {
253289
"oneOf": [
254290
{
@@ -556,7 +592,7 @@
556592
},
557593
"/api/exe/{execution_id}/obs/{observation_id}/content": {
558594
"get": {
559-
"operationId": "get_observation_blob",
595+
"operationId": "get_observation_blob_legacy",
560596
"parameters": [
561597
{
562598
"description": "Execution ID",
@@ -600,7 +636,68 @@
600636
"description": "Observation blob not found"
601637
}
602638
},
603-
"summary": "Get observation blob content",
639+
"summary": "Get observation blob content (legacy route for backward compat)\nThis is kept to support old URLs like /api/exe/{exec_id}/obs/{obs_id}/content",
640+
"tags": [
641+
"observations"
642+
]
643+
}
644+
},
645+
"/api/exe/{execution_id}/obs/{observation_id}/payload/{payload_id}/content": {
646+
"get": {
647+
"operationId": "get_observation_blob",
648+
"parameters": [
649+
{
650+
"description": "Execution ID",
651+
"in": "path",
652+
"name": "execution_id",
653+
"required": true,
654+
"schema": {
655+
"type": "string"
656+
}
657+
},
658+
{
659+
"description": "Observation ID",
660+
"in": "path",
661+
"name": "observation_id",
662+
"required": true,
663+
"schema": {
664+
"type": "string"
665+
}
666+
},
667+
{
668+
"description": "Payload ID",
669+
"in": "path",
670+
"name": "payload_id",
671+
"required": true,
672+
"schema": {
673+
"type": "string"
674+
}
675+
}
676+
],
677+
"responses": {
678+
"200": {
679+
"content": {
680+
"application/octet-stream": {
681+
"schema": {
682+
"items": {
683+
"format": "int32",
684+
"minimum": 0,
685+
"type": "integer"
686+
},
687+
"type": "array"
688+
}
689+
}
690+
},
691+
"description": "Payload content"
692+
},
693+
"400": {
694+
"description": "Bad request"
695+
},
696+
"404": {
697+
"description": "Payload not found"
698+
}
699+
},
700+
"summary": "Get observation payload content",
604701
"tags": [
605702
"observations"
606703
]

crates/observation-tools-server/src/api/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ pub fn build_api() -> (Router<AppState>, Router<AppState>, OpenApi) {
144144
.routes(routes!(observations::list_observations))
145145
.routes(routes!(observations::get_observation))
146146
.routes(routes!(observations::get_observation_blob))
147+
.routes(routes!(observations::get_observation_blob_legacy))
147148
.split_for_parts();
148149

149150
let mut openapi = OpenApi::default();

0 commit comments

Comments
 (0)