@ancplua/qyl-api-schema 11.5.0 → 11.6.0-rc.1

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.
@@ -0,0 +1,198 @@
1
+ import "../common/types.tsp";
2
+
3
+ using Qyl.Api.Contracts.Common;
4
+
5
+ namespace Qyl.Api.Contracts.OTel.Metrics;
6
+
7
+ @doc("Shape of a stored metric stream.")
8
+ enum MetricKind {
9
+ @doc("A value sampled at a point in time.")
10
+ gauge: "gauge",
11
+
12
+ @doc("An additive value; see `temporality` and `monotonic` for how to read it.")
13
+ sum: "sum",
14
+
15
+ @doc("A distribution recorded against explicit bucket boundaries.")
16
+ histogram: "histogram",
17
+
18
+ @doc("""
19
+ An OTLP exponential histogram. Its buckets are stored in the same explicit
20
+ bound vector `histogram` uses, so both kinds answer the same queries; the
21
+ distinct name records only where the distribution came from.
22
+ """)
23
+ exponential_histogram: "exponential_histogram",
24
+ }
25
+
26
+ @doc("How successive points of a sum or histogram relate to each other.")
27
+ enum MetricTemporality {
28
+ unspecified: "unspecified",
29
+
30
+ @doc("Each point covers only the interval since the previous one.")
31
+ delta: "delta",
32
+
33
+ @doc("Each point is the running total since the stream's start time.")
34
+ cumulative: "cumulative",
35
+ }
36
+
37
+ @doc("Server-side reducer applied to the points falling in one time bucket.")
38
+ enum MetricAggregation {
39
+ avg: "avg",
40
+ min: "min",
41
+ max: "max",
42
+ sum: "sum",
43
+ count: "count",
44
+
45
+ @doc("The value of the latest point in the bucket.")
46
+ last: "last",
47
+
48
+ @doc("50th percentile, interpolated from bucket boundaries. Histogram kinds only.")
49
+ p50: "p50",
50
+
51
+ @doc("90th percentile, interpolated from bucket boundaries. Histogram kinds only.")
52
+ p90: "p90",
53
+
54
+ @doc("95th percentile, interpolated from bucket boundaries. Histogram kinds only.")
55
+ p95: "p95",
56
+
57
+ @doc("99th percentile, interpolated from bucket boundaries. Histogram kinds only.")
58
+ p99: "p99",
59
+ }
60
+
61
+ @doc("""
62
+ One metric name recorded for a project, collapsed across all of its series.
63
+ This is the catalog entry a client reads before it knows which series exist.
64
+ """)
65
+ model MetricDescriptor {
66
+ @doc("Instrument name, e.g. `http.server.request.duration`.")
67
+ name: string;
68
+
69
+ kind: MetricKind;
70
+
71
+ temporality: MetricTemporality;
72
+
73
+ @doc("Whether a sum only ever increases. Meaningless for other kinds.")
74
+ monotonic: boolean;
75
+
76
+ @doc("UCUM unit as reported by the producer, e.g. `s` or `{request}`.")
77
+ unit?: string;
78
+
79
+ @doc("Producer-supplied description of the instrument.")
80
+ description?: string;
81
+
82
+ @doc("Number of distinct attribute streams recorded under this name.")
83
+ @encodedName("application/json", "series_count")
84
+ seriesCount: int64;
85
+
86
+ @doc("Timestamp of the most recent point recorded under this name.")
87
+ @encodedName("application/json", "last_seen")
88
+ lastSeen: utcDateTime;
89
+ }
90
+
91
+ @doc("One distinct attribute stream recorded under a metric name.")
92
+ model MetricSeries {
93
+ @doc("Stable identifier for this stream, derived from its name, attributes and resource.")
94
+ @encodedName("application/json", "series_id")
95
+ seriesId: string;
96
+
97
+ @doc("Instrument name this series belongs to.")
98
+ name: string;
99
+
100
+ kind: MetricKind;
101
+
102
+ @doc("The attributes that distinguish this series from others under the same name.")
103
+ attributes: Attribute[];
104
+
105
+ @encodedName("application/json", "service_name")
106
+ serviceName?: string;
107
+
108
+ unit?: string;
109
+
110
+ @encodedName("application/json", "first_seen")
111
+ firstSeen: utcDateTime;
112
+
113
+ @encodedName("application/json", "last_seen")
114
+ lastSeen: utcDateTime;
115
+ }
116
+
117
+ @doc("One aggregated time bucket of a metric range query.")
118
+ model MetricBucket {
119
+ @doc("Inclusive start of the bucket, aligned to the query's step from the query's start.")
120
+ @encodedName("application/json", "bucket_start")
121
+ bucketStart: utcDateTime;
122
+
123
+ @doc("""
124
+ The aggregation applied to the points in this bucket. Null when the bucket
125
+ holds no value: either no point landed in it, or every point that did was
126
+ an OTLP `NO_RECORDED_VALUE` marker.
127
+ """)
128
+ value: float64 | null;
129
+
130
+ @doc("Number of stored points folded into this bucket.")
131
+ @encodedName("application/json", "point_count")
132
+ pointCount: int64;
133
+ }
134
+
135
+ @doc("""
136
+ One result stream of a metric range query. With no `group_by` the whole
137
+ result is a single stream whose `attributes` are empty; with `group_by` there
138
+ is one stream per distinct combination of the requested attribute values.
139
+ """)
140
+ model MetricSeriesResult {
141
+ @doc("The grouping key that produced this stream.")
142
+ attributes: Attribute[];
143
+
144
+ buckets: MetricBucket[];
145
+ }
146
+
147
+ @doc("The answer to a metric range query: what was asked, and the streams it produced.")
148
+ model MetricQueryResult {
149
+ @doc("Instrument name the query ran against.")
150
+ name: string;
151
+
152
+ kind: MetricKind;
153
+
154
+ unit?: string;
155
+
156
+ aggregation: MetricAggregation;
157
+
158
+ @doc("Bucket width actually used, which may be widened from the requested step.")
159
+ @encodedName("application/json", "step_ms")
160
+ stepMs: int64;
161
+
162
+ @encodedName("application/json", "start_time")
163
+ startTime: utcDateTime;
164
+
165
+ @encodedName("application/json", "end_time")
166
+ endTime: utcDateTime;
167
+
168
+ series: MetricSeriesResult[];
169
+
170
+ @doc("Whether streams were dropped because the result exceeded the series limit.")
171
+ truncated: boolean;
172
+ }
173
+
174
+ @doc("How a structured attribute matcher compares an attribute value.")
175
+ enum MetricMatcherOp {
176
+ @doc("The attribute equals `value`; serialized to the `attr` query parameter as `key=value`.")
177
+ eq: "eq",
178
+
179
+ @doc("The attribute starts with `value`; serialized to the `attr_prefix` query parameter as `key=value`.")
180
+ prefix: "prefix",
181
+ }
182
+
183
+ @doc("""
184
+ One structured attribute matcher. Tool inputs and saved queries carry
185
+ matchers in this form; the HTTP routes keep their `key=value` string
186
+ parameters, and a client serializes each matcher to one of them.
187
+ """)
188
+ model MetricAttributeMatcher {
189
+ @doc("Attribute key, e.g. `http.route`.")
190
+ @minLength(1)
191
+ @maxLength(256)
192
+ key: string;
193
+
194
+ `op`: MetricMatcherOp;
195
+
196
+ @maxLength(1024)
197
+ value: string;
198
+ }
@@ -0,0 +1,212 @@
1
+ // =============================================================================
2
+ // Saved queries: named, structured filters for traces, logs or metrics
3
+ // =============================================================================
4
+ // A saved query stores a filter, never results. `:run` evaluates it against
5
+ // the current telemetry with a window relative to the time of the run.
6
+ // Names are unique per project; a duplicate is refused with 409.
7
+ // =============================================================================
8
+
9
+ import "@typespec/http";
10
+ import "@typespec/openapi";
11
+ import "../common/types.tsp";
12
+ import "../common/resource.tsp";
13
+ import "../otel/enums.tsp";
14
+ import "../otel/span.tsp";
15
+ import "../otel/logs.tsp";
16
+ import "./metrics.tsp";
17
+
18
+ using TypeSpec.OpenAPI;
19
+ using Qyl.Api.Contracts.Common;
20
+ using Qyl.Api.Contracts.OTel.Enums;
21
+ using Qyl.Api.Contracts.OTel.Logs;
22
+ using Qyl.Api.Contracts.OTel.Metrics;
23
+ using Qyl.Api.Contracts.OTel.Traces;
24
+
25
+ namespace Qyl.Api.Contracts.SavedQueries;
26
+
27
+ @doc("The telemetry signal a saved query reads.")
28
+ enum SavedQuerySignal {
29
+ traces: "traces",
30
+ logs: "logs",
31
+ metrics: "metrics",
32
+ }
33
+
34
+ @doc("Look-back window shared by every saved-query filter.")
35
+ model SavedQueryWindow {
36
+ @doc("Window ending at the time of the run, in minutes. Omitted, the run's own `start_time`/`end_time` or the last 60 minutes apply.")
37
+ @encodedName("application/json", "lookback_minutes")
38
+ @minValue(1)
39
+ @maxValue(43200)
40
+ lookbackMinutes?: int32;
41
+ }
42
+
43
+ @doc("A saved filter over traces.")
44
+ model SavedTraceQueryFilter {
45
+ signal: "traces";
46
+ ...SavedQueryWindow;
47
+
48
+ @encodedName("application/json", "service_name")
49
+ @minLength(1)
50
+ @maxLength(256)
51
+ serviceName?: string;
52
+
53
+ @doc("Keep only traces with at least one error span.")
54
+ @encodedName("application/json", "errors_only")
55
+ errorsOnly?: boolean;
56
+ }
57
+
58
+ @doc("A saved filter over log records.")
59
+ model SavedLogQueryFilter {
60
+ signal: "logs";
61
+ ...SavedQueryWindow;
62
+
63
+ @encodedName("application/json", "service_name")
64
+ @minLength(1)
65
+ @maxLength(256)
66
+ serviceName?: string;
67
+
68
+ @encodedName("application/json", "severity_min")
69
+ severityMin?: SeverityNumber;
70
+
71
+ @encodedName("application/json", "session_id")
72
+ sessionId?: SessionId;
73
+
74
+ @encodedName("application/json", "trace_id")
75
+ traceId?: TraceId;
76
+
77
+ @doc("Substring searched in the log body.")
78
+ @minLength(1)
79
+ @maxLength(1024)
80
+ query?: string;
81
+ }
82
+
83
+ @doc("A saved metric range query.")
84
+ model SavedMetricQueryFilter {
85
+ signal: "metrics";
86
+ ...SavedQueryWindow;
87
+
88
+ @encodedName("application/json", "metric_name")
89
+ @minLength(1)
90
+ @maxLength(256)
91
+ metricName: string;
92
+
93
+ aggregation?: MetricAggregation = MetricAggregation.avg;
94
+
95
+ @doc("Bucket width in integer milliseconds.")
96
+ @encodedName("application/json", "step_ms")
97
+ @minValue(1)
98
+ @maxValue(86400000)
99
+ stepMs?: int64 = 60000;
100
+
101
+ @doc("Attribute keys to split the result by.")
102
+ @encodedName("application/json", "group_by")
103
+ @maxItems(16)
104
+ groupBy?: string[];
105
+
106
+ @doc("Attribute matchers a series must all satisfy.")
107
+ @maxItems(32)
108
+ matchers?: MetricAttributeMatcher[];
109
+ }
110
+
111
+ @doc("Exactly one structured filter; `signal` selects which.")
112
+ @oneOf
113
+ union SavedQueryFilter {
114
+ traces: SavedTraceQueryFilter,
115
+ logs: SavedLogQueryFilter,
116
+ metrics: SavedMetricQueryFilter,
117
+ }
118
+
119
+ @doc("A named filter for traces, logs or metrics, owned by one project.")
120
+ model SavedQuery extends ResourceBase {
121
+ @doc("Unique within the project; a duplicate is refused with 409.")
122
+ @minLength(1)
123
+ @maxLength(200)
124
+ name: string;
125
+
126
+ @maxLength(2000)
127
+ description?: string;
128
+
129
+ filter: SavedQueryFilter;
130
+ }
131
+
132
+ @doc("Body of POST /api/v1/saved-queries: the `Lifecycle.Create` members of SavedQuery.")
133
+ model SavedQueryCreateRequest {
134
+ @doc("Unique within the project; a duplicate is refused with 409.")
135
+ @minLength(1)
136
+ @maxLength(200)
137
+ name: string;
138
+
139
+ @maxLength(2000)
140
+ description?: string;
141
+
142
+ filter: SavedQueryFilter;
143
+ }
144
+
145
+ @doc("Body of PATCH /api/v1/saved-queries/{saved_query_id}: the `Lifecycle.Update` members of SavedQuery, each optional; omitted members keep their value.")
146
+ model SavedQueryUpdateRequest {
147
+ @doc("New name, unique within the project; a duplicate is refused with 409.")
148
+ @minLength(1)
149
+ @maxLength(200)
150
+ name?: string;
151
+
152
+ @maxLength(2000)
153
+ description?: string;
154
+
155
+ filter?: SavedQueryFilter;
156
+ }
157
+
158
+ @doc("Optional overrides for one run of a saved query.")
159
+ model SavedQueryRunRequest {
160
+ @doc("Overrides the saved look-back window together with `end_time`.")
161
+ @encodedName("application/json", "start_time")
162
+ startTime?: utcDateTime;
163
+
164
+ @encodedName("application/json", "end_time")
165
+ endTime?: utcDateTime;
166
+
167
+ @doc("Page size for trace and log runs.")
168
+ @minValue(1)
169
+ @maxValue(1000)
170
+ limit?: int32 = 100;
171
+
172
+ @doc("`next_cursor` of a previous run of the same saved query.")
173
+ cursor?: Cursor;
174
+ }
175
+
176
+ @doc("One page of trace summaries produced by a saved trace query, like list_traces; get_trace reads one full span tree.")
177
+ model SavedTraceQueryRun {
178
+ signal: "traces";
179
+ items: TraceSummary[];
180
+
181
+ @encodedName("application/json", "next_cursor")
182
+ nextCursor?: Cursor;
183
+
184
+ @encodedName("application/json", "has_more")
185
+ hasMore: boolean;
186
+ }
187
+
188
+ @doc("One page of log records produced by a saved log query.")
189
+ model SavedLogQueryRun {
190
+ signal: "logs";
191
+ items: LogRecord[];
192
+
193
+ @encodedName("application/json", "next_cursor")
194
+ nextCursor?: Cursor;
195
+
196
+ @encodedName("application/json", "has_more")
197
+ hasMore: boolean;
198
+ }
199
+
200
+ @doc("The range-query result produced by a saved metric query.")
201
+ model SavedMetricQueryRun {
202
+ signal: "metrics";
203
+ result: MetricQueryResult;
204
+ }
205
+
206
+ @doc("The result of running a saved query; `signal` matches the query's filter.")
207
+ @oneOf
208
+ union SavedQueryRunResult {
209
+ traces: SavedTraceQueryRun,
210
+ logs: SavedLogQueryRun,
211
+ metrics: SavedMetricQueryRun,
212
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ancplua/qyl-api-schema",
3
- "version": "11.5.0",
3
+ "version": "11.6.0-rc.1",
4
4
  "description": "TypeSpec source of truth for qyl API contracts. Emits OpenAPI, JSON Schema, Qyl.Api.Contracts DTOs, and TypeScript contract types; not an OpenTelemetry package, storage schema, or server implementation.",
5
5
  "license": "Apache-2.0",
6
6
  "workspaces": [
@@ -65,14 +65,19 @@
65
65
  "api/runner.tsp",
66
66
  "api/streaming.tsp",
67
67
  "api/workbench.tsp",
68
+ "common/auth.tsp",
68
69
  "common/errors.tsp",
69
70
  "common/pagination.tsp",
70
71
  "common/types.tsp",
72
+ "common/resource.tsp",
71
73
  "models/health.tsp",
74
+ "models/metrics.tsp",
72
75
  "models/runner.tsp",
73
76
  "models/workbench.tsp",
77
+ "models/annotations.tsp",
74
78
  "models/mcp-tools.tsp",
75
79
  "models/session.tsp",
80
+ "models/saved-queries.tsp",
76
81
  "otel/enums.tsp",
77
82
  "otel/logs.tsp",
78
83
  "otel/otel-conventions.tsp",