duron 0.3.0-beta.9 → 0.3.0

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 (91) hide show
  1. package/dist/action-job.d.ts +33 -2
  2. package/dist/action-job.d.ts.map +1 -1
  3. package/dist/action-job.js +88 -23
  4. package/dist/action-manager.d.ts +44 -2
  5. package/dist/action-manager.d.ts.map +1 -1
  6. package/dist/action-manager.js +64 -3
  7. package/dist/action.d.ts +388 -7
  8. package/dist/action.d.ts.map +1 -1
  9. package/dist/action.js +44 -23
  10. package/dist/adapters/adapter.d.ts +365 -8
  11. package/dist/adapters/adapter.d.ts.map +1 -1
  12. package/dist/adapters/adapter.js +221 -15
  13. package/dist/adapters/postgres/base.d.ts +184 -6
  14. package/dist/adapters/postgres/base.d.ts.map +1 -1
  15. package/dist/adapters/postgres/base.js +436 -75
  16. package/dist/adapters/postgres/pglite.d.ts +37 -0
  17. package/dist/adapters/postgres/pglite.d.ts.map +1 -1
  18. package/dist/adapters/postgres/pglite.js +38 -0
  19. package/dist/adapters/postgres/postgres.d.ts +35 -0
  20. package/dist/adapters/postgres/postgres.d.ts.map +1 -1
  21. package/dist/adapters/postgres/postgres.js +42 -0
  22. package/dist/adapters/postgres/schema.d.ts +150 -37
  23. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  24. package/dist/adapters/postgres/schema.default.d.ts +151 -38
  25. package/dist/adapters/postgres/schema.default.d.ts.map +1 -1
  26. package/dist/adapters/postgres/schema.default.js +2 -2
  27. package/dist/adapters/postgres/schema.js +60 -23
  28. package/dist/adapters/schemas.d.ts +124 -80
  29. package/dist/adapters/schemas.d.ts.map +1 -1
  30. package/dist/adapters/schemas.js +139 -26
  31. package/dist/client.d.ts +426 -22
  32. package/dist/client.d.ts.map +1 -1
  33. package/dist/client.js +370 -20
  34. package/dist/constants.js +6 -0
  35. package/dist/errors.d.ts +140 -3
  36. package/dist/errors.d.ts.map +1 -1
  37. package/dist/errors.js +152 -9
  38. package/dist/index.d.ts +2 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/server.d.ts +99 -37
  41. package/dist/server.d.ts.map +1 -1
  42. package/dist/server.js +84 -25
  43. package/dist/step-manager.d.ts +111 -4
  44. package/dist/step-manager.d.ts.map +1 -1
  45. package/dist/step-manager.js +403 -75
  46. package/dist/telemetry/index.d.ts +1 -4
  47. package/dist/telemetry/index.d.ts.map +1 -1
  48. package/dist/telemetry/index.js +2 -4
  49. package/dist/telemetry/local-span-exporter.d.ts +56 -0
  50. package/dist/telemetry/local-span-exporter.d.ts.map +1 -0
  51. package/dist/telemetry/local-span-exporter.js +118 -0
  52. package/dist/utils/p-retry.d.ts +5 -0
  53. package/dist/utils/p-retry.d.ts.map +1 -1
  54. package/dist/utils/p-retry.js +8 -0
  55. package/dist/utils/wait-for-abort.d.ts +1 -0
  56. package/dist/utils/wait-for-abort.d.ts.map +1 -1
  57. package/dist/utils/wait-for-abort.js +1 -0
  58. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/migration.sql +32 -20
  59. package/migrations/postgres/{20260119153838_flimsy_thor_girl → 20260121160012_normal_bloodstrike}/snapshot.json +241 -66
  60. package/package.json +42 -26
  61. package/src/action-job.ts +33 -29
  62. package/src/action-manager.ts +5 -5
  63. package/src/action.ts +317 -149
  64. package/src/adapters/adapter.ts +54 -54
  65. package/src/adapters/postgres/base.ts +266 -86
  66. package/src/adapters/postgres/schema.default.ts +2 -2
  67. package/src/adapters/postgres/schema.ts +52 -24
  68. package/src/adapters/schemas.ts +91 -36
  69. package/src/client.ts +322 -68
  70. package/src/errors.ts +84 -12
  71. package/src/index.ts +2 -0
  72. package/src/server.ts +39 -37
  73. package/src/step-manager.ts +246 -95
  74. package/src/telemetry/index.ts +2 -20
  75. package/src/telemetry/local-span-exporter.ts +148 -0
  76. package/dist/telemetry/adapter.d.ts +0 -107
  77. package/dist/telemetry/adapter.d.ts.map +0 -1
  78. package/dist/telemetry/adapter.js +0 -134
  79. package/dist/telemetry/local.d.ts +0 -22
  80. package/dist/telemetry/local.d.ts.map +0 -1
  81. package/dist/telemetry/local.js +0 -243
  82. package/dist/telemetry/noop.d.ts +0 -17
  83. package/dist/telemetry/noop.d.ts.map +0 -1
  84. package/dist/telemetry/noop.js +0 -66
  85. package/dist/telemetry/opentelemetry.d.ts +0 -25
  86. package/dist/telemetry/opentelemetry.d.ts.map +0 -1
  87. package/dist/telemetry/opentelemetry.js +0 -312
  88. package/src/telemetry/adapter.ts +0 -642
  89. package/src/telemetry/local.ts +0 -429
  90. package/src/telemetry/noop.ts +0 -141
  91. package/src/telemetry/opentelemetry.ts +0 -453
package/src/errors.ts CHANGED
@@ -11,6 +11,17 @@ export const ERROR_CODES = {
11
11
 
12
12
  export type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES]
13
13
 
14
+ /**
15
+ * Metadata about the context where an error occurred.
16
+ */
17
+ export interface ErrorMetadata {
18
+ jobId?: string
19
+ stepId?: string
20
+ parentStepId?: string | null
21
+ actionName?: string
22
+ stepName?: string
23
+ }
24
+
14
25
  /**
15
26
  * Base class for all built-in errors in Duron.
16
27
  * All errors include a cause property that can be serialized.
@@ -33,6 +44,11 @@ export abstract class DuronError extends Error {
33
44
  */
34
45
  public override readonly cause?: unknown
35
46
 
47
+ /**
48
+ * Metadata about the context where the error occurred.
49
+ */
50
+ public metadata: ErrorMetadata
51
+
36
52
  constructor(
37
53
  message: string,
38
54
  options?: {
@@ -42,10 +58,15 @@ export abstract class DuronError extends Error {
42
58
  * This will be serialized and stored in the database.
43
59
  */
44
60
  cause?: unknown
61
+ /**
62
+ * Metadata about the context where the error occurred.
63
+ */
64
+ metadata?: ErrorMetadata
45
65
  },
46
66
  ) {
47
67
  super(message)
48
68
  this.cause = options?.cause
69
+ this.metadata = options?.metadata ?? {}
49
70
  // Set the name to the class name
50
71
  this.name = this.constructor.name
51
72
  // Ensure stack trace points to the error location
@@ -53,6 +74,18 @@ export abstract class DuronError extends Error {
53
74
  Error.captureStackTrace(this, this.constructor)
54
75
  }
55
76
  }
77
+
78
+ /**
79
+ * Set or update metadata about the context where the error occurred.
80
+ * Merges with existing metadata (new values override existing ones).
81
+ *
82
+ * @param metadata - The metadata to set or merge
83
+ * @returns this - Returns the error instance for chaining
84
+ */
85
+ setMetadata(metadata: ErrorMetadata): this {
86
+ this.metadata = { ...this.metadata, ...metadata }
87
+ return this
88
+ }
56
89
  }
57
90
 
58
91
  /**
@@ -70,7 +103,9 @@ export class StepAlreadyExecutedError extends DuronError {
70
103
  * @param actionName - The name of the action containing the step
71
104
  */
72
105
  constructor(stepName: string, jobId: string, actionName: string) {
73
- super(`Step "${stepName}" has already been executed for job "${jobId}" and action "${actionName}"`)
106
+ super(`Step "${stepName}" has already been executed for job "${jobId}" and action "${actionName}"`, {
107
+ metadata: { stepName, jobId, actionName },
108
+ })
74
109
  }
75
110
  }
76
111
 
@@ -96,17 +131,22 @@ export class ActionTimeoutError extends DuronError {
96
131
  * Create a new ActionTimeoutError.
97
132
  *
98
133
  * @param actionName - The name of the action that timed out
134
+ * @param jobId - The ID of the job containing the action
99
135
  * @param timeoutMs - The timeout value in milliseconds
100
136
  * @param options - Optional error options including cause
101
137
  */
102
138
  constructor(
103
139
  actionName: string,
140
+ jobId: string,
104
141
  timeoutMs: number,
105
142
  options?: {
106
143
  cause?: unknown
107
144
  },
108
145
  ) {
109
- super(`Action "${actionName}" timed out after ${timeoutMs}ms`, options)
146
+ super(`Action "${actionName}" in job "${jobId}" timed out after ${timeoutMs}ms`, {
147
+ cause: options?.cause,
148
+ metadata: { actionName, jobId },
149
+ })
110
150
  }
111
151
  }
112
152
 
@@ -123,7 +163,7 @@ export class StepTimeoutError extends DuronError {
123
163
  * @param stepName - The name of the step that timed out
124
164
  * @param jobId - The ID of the job containing the step
125
165
  * @param timeoutMs - The timeout value in milliseconds
126
- * @param options - Optional error options including cause
166
+ * @param options - Optional error options including cause and additional metadata
127
167
  */
128
168
  constructor(
129
169
  stepName: string,
@@ -131,9 +171,21 @@ export class StepTimeoutError extends DuronError {
131
171
  timeoutMs: number,
132
172
  options?: {
133
173
  cause?: unknown
174
+ stepId?: string
175
+ parentStepId?: string | null
176
+ actionName?: string
134
177
  },
135
178
  ) {
136
- super(`Step "${stepName}" in job "${jobId}" timed out after ${timeoutMs}ms`, options)
179
+ super(`Step "${stepName}" in job "${jobId}" timed out after ${timeoutMs}ms`, {
180
+ cause: options?.cause,
181
+ metadata: {
182
+ stepName,
183
+ jobId,
184
+ stepId: options?.stepId,
185
+ parentStepId: options?.parentStepId,
186
+ actionName: options?.actionName,
187
+ },
188
+ })
137
189
  }
138
190
  }
139
191
 
@@ -158,7 +210,10 @@ export class ActionCancelError extends DuronError {
158
210
  cause?: unknown
159
211
  },
160
212
  ) {
161
- super(`Action "${actionName}" in job "${jobId}" was cancelled`, options)
213
+ super(`Action "${actionName}" in job "${jobId}" was cancelled`, {
214
+ cause: options?.cause,
215
+ metadata: { actionName, jobId },
216
+ })
162
217
  }
163
218
  }
164
219
 
@@ -171,11 +226,6 @@ export class ActionCancelError extends DuronError {
171
226
  export class UnhandledChildStepsError extends NonRetriableError {
172
227
  public override readonly code = ERROR_CODES.UNHANDLED_CHILD_STEPS
173
228
 
174
- /**
175
- * The name of the parent step that completed with unhandled children.
176
- */
177
- public readonly stepName: string
178
-
179
229
  /**
180
230
  * The number of unhandled child steps.
181
231
  */
@@ -186,12 +236,30 @@ export class UnhandledChildStepsError extends NonRetriableError {
186
236
  *
187
237
  * @param stepName - The name of the parent step
188
238
  * @param pendingCount - The number of unhandled child steps
239
+ * @param options - Optional metadata
189
240
  */
190
- constructor(stepName: string, pendingCount: number) {
241
+ constructor(
242
+ stepName: string,
243
+ pendingCount: number,
244
+ options?: {
245
+ stepId?: string
246
+ parentStepId?: string | null
247
+ jobId?: string
248
+ actionName?: string
249
+ },
250
+ ) {
191
251
  super(
192
252
  `Parent step "${stepName}" completed with ${pendingCount} unhandled child step(s). All child steps must be awaited before the parent returns.`,
253
+ {
254
+ metadata: {
255
+ stepName,
256
+ stepId: options?.stepId,
257
+ parentStepId: options?.parentStepId,
258
+ jobId: options?.jobId,
259
+ actionName: options?.actionName,
260
+ },
261
+ },
193
262
  )
194
- this.stepName = stepName
195
263
  this.pendingCount = pendingCount
196
264
  }
197
265
  }
@@ -238,6 +306,7 @@ export type SerializableError = {
238
306
  message: string
239
307
  code?: ErrorCode
240
308
  nonRetriable?: boolean
309
+ metadata?: ErrorMetadata
241
310
  cause?: unknown
242
311
  stack?: string
243
312
  }
@@ -249,6 +318,7 @@ export type SerializableError = {
249
318
  export function serializeError(error: unknown): SerializableError {
250
319
  const code = (error as any)?.code
251
320
  const nonRetriable = (error as any)?.nonRetriable
321
+ const metadata = (error as any)?.metadata
252
322
 
253
323
  if (isTimeoutError(error)) {
254
324
  return {
@@ -256,6 +326,7 @@ export function serializeError(error: unknown): SerializableError {
256
326
  message: error.message,
257
327
  code,
258
328
  nonRetriable,
329
+ metadata,
259
330
  cause: error.cause,
260
331
  stack: undefined,
261
332
  }
@@ -267,6 +338,7 @@ export function serializeError(error: unknown): SerializableError {
267
338
  message: error.message,
268
339
  code,
269
340
  nonRetriable,
341
+ metadata,
270
342
  cause: error.cause,
271
343
  stack: error.stack,
272
344
  }
package/src/index.ts CHANGED
@@ -7,11 +7,13 @@ export {
7
7
  type StepDefinition,
8
8
  type StepDefinitionHandlerContext,
9
9
  type StepDefinitionInput,
10
+ type StepNameContext,
10
11
  } from './action.js'
11
12
  export * from './client.js'
12
13
  export * from './constants.js'
13
14
  export { NonRetriableError, UnhandledChildStepsError } from './errors.js'
14
15
  export * from './server.js'
16
+ export type { TelemetryContext } from './step-manager.js'
15
17
  export * from './telemetry/index.js'
16
18
 
17
19
  export const duron = <
package/src/server.ts CHANGED
@@ -2,21 +2,21 @@ import { Elysia } from 'elysia'
2
2
  import { jwtVerify, SignJWT } from 'jose'
3
3
  import { z } from 'zod'
4
4
 
5
- import type { GetJobStepsOptions, GetJobsOptions, GetMetricsOptions } from './adapters/adapter.js'
5
+ import type { GetJobStepsOptions, GetJobsOptions, GetSpansOptions } from './adapters/adapter.js'
6
6
  import {
7
7
  GetActionsResultSchema,
8
8
  GetJobStepsResultSchema,
9
9
  GetJobsResultSchema,
10
- GetMetricsResultSchema,
10
+ GetSpansResultSchema,
11
11
  JobSchema,
12
12
  JobSortFieldSchema,
13
13
  JobStatusResultSchema,
14
14
  JobStatusSchema,
15
15
  JobStepSchema,
16
16
  JobStepStatusResultSchema,
17
- MetricSortFieldSchema,
18
- MetricTypeSchema,
19
17
  SortOrderSchema,
18
+ SpanKindSchema,
19
+ SpanSortFieldSchema,
20
20
  } from './adapters/schemas.js'
21
21
  import type { Client } from './client.js'
22
22
 
@@ -86,6 +86,7 @@ export const GetJobsQuerySchema = z
86
86
  fActionName: z.union([z.string(), z.array(z.string())]).optional(),
87
87
  fGroupKey: z.union([z.string(), z.array(z.string())]).optional(),
88
88
  fClientId: z.union([z.string(), z.array(z.string())]).optional(),
89
+ fDescription: z.string().optional(),
89
90
  // Date filters: can be a single ISO string or JSON array [start, end] - both coerced to Date objects
90
91
  fCreatedAt: z.union([z.coerce.date(), z.array(z.coerce.date())]).optional(),
91
92
  fStartedAt: z.union([z.coerce.date(), z.array(z.coerce.date())]).optional(),
@@ -107,6 +108,7 @@ export const GetJobsQuerySchema = z
107
108
  if (data.fActionName) filters.actionName = data.fActionName
108
109
  if (data.fGroupKey) filters.groupKey = data.fGroupKey
109
110
  if (data.fClientId) filters.clientId = data.fClientId
111
+ if (data.fDescription) filters.description = data.fDescription
110
112
  if (data.fCreatedAt) filters.createdAt = data.fCreatedAt
111
113
  if (data.fStartedAt) filters.startedAt = data.fStartedAt
112
114
  if (data.fFinishedAt) filters.finishedAt = data.fFinishedAt
@@ -176,13 +178,13 @@ export const GetActionsMetadataResponseSchema = z.array(
176
178
  export type GetJobsQueryInput = z.input<typeof GetJobsQuerySchema>
177
179
  export type GetJobStepsQueryInput = z.input<typeof GetJobStepsQuerySchema>
178
180
 
179
- // Metrics query schema
180
- export const GetMetricsQuerySchema = z
181
+ // Spans query schema
182
+ export const GetSpansQuerySchema = z
181
183
  .object({
182
184
  // Filters
183
185
  fName: z.union([z.string(), z.array(z.string())]).optional(),
184
- fType: z.union([MetricTypeSchema, z.array(MetricTypeSchema)]).optional(),
185
- fTimestampRange: z.array(z.coerce.date()).length(2).optional(),
186
+ fKind: z.union([SpanKindSchema, z.array(SpanKindSchema)]).optional(),
187
+ fTraceId: z.string().optional(),
186
188
  fAttributesFilter: z.record(z.string(), z.any()).optional(),
187
189
 
188
190
  // Sort - format: "field:asc" or "field:desc"
@@ -192,16 +194,16 @@ export const GetMetricsQuerySchema = z
192
194
  const filters: any = {}
193
195
 
194
196
  if (data.fName) filters.name = data.fName
195
- if (data.fType) filters.type = data.fType
196
- if (data.fTimestampRange) filters.timestampRange = data.fTimestampRange
197
+ if (data.fKind) filters.kind = data.fKind
198
+ if (data.fTraceId) filters.traceId = data.fTraceId
197
199
  if (data.fAttributesFilter) filters.attributesFilter = data.fAttributesFilter
198
200
 
199
201
  // Parse sort string: "field:asc" -> { field: 'field', order: 'asc' }
200
- let sort: { field: z.infer<typeof MetricSortFieldSchema>; order: z.infer<typeof SortOrderSchema> } | undefined
202
+ let sort: { field: z.infer<typeof SpanSortFieldSchema>; order: z.infer<typeof SortOrderSchema> } | undefined
201
203
  if (data.sort) {
202
204
  const [field, order] = data.sort.split(':').map((s) => s.trim())
203
205
  if (field && order) {
204
- const fieldResult = MetricSortFieldSchema.safeParse(field)
206
+ const fieldResult = SpanSortFieldSchema.safeParse(field)
205
207
  const orderResult = SortOrderSchema.safeParse(order.toLowerCase())
206
208
  if (fieldResult.success && orderResult.success) {
207
209
  sort = {
@@ -218,7 +220,7 @@ export const GetMetricsQuerySchema = z
218
220
  }
219
221
  })
220
222
 
221
- export type GetMetricsQueryInput = z.input<typeof GetMetricsQuerySchema>
223
+ export type GetSpansQueryInput = z.input<typeof GetSpansQuerySchema>
222
224
 
223
225
  export const ErrorResponseSchema = z.object({
224
226
  error: z.string(),
@@ -269,12 +271,12 @@ export interface CreateServerOptions<P extends string> {
269
271
  prefix?: P
270
272
 
271
273
  /**
272
- * Enable metrics endpoints (/jobs/:id/metrics, /steps/:id/metrics).
273
- * Only works when client is configured with LocalTelemetryAdapter.
274
- * When true, enables the dashboard to show metrics buttons.
275
- * @default auto-detected from client.metricsEnabled
274
+ * Enable spans endpoints (/jobs/:id/spans, /steps/:id/spans).
275
+ * Only works when client is configured with telemetry.local enabled.
276
+ * When true, enables the dashboard to show spans buttons.
277
+ * @default auto-detected from client.spansEnabled
276
278
  */
277
- metricsEnabled?: boolean
279
+ spansEnabled?: boolean
278
280
 
279
281
  login?: {
280
282
  onLogin: (body: { email: string; password: string }) => Promise<boolean>
@@ -297,14 +299,14 @@ export interface CreateServerOptions<P extends string> {
297
299
  * @param options - Configuration options
298
300
  * @returns Elysia server instance
299
301
  */
300
- export function createServer<P extends string>({ client, prefix, login, metricsEnabled }: CreateServerOptions<P>) {
302
+ export function createServer<P extends string>({ client, prefix, login, spansEnabled }: CreateServerOptions<P>) {
301
303
  // Convert string secret to Uint8Array if needed
302
304
  const secretKey = typeof login?.jwtSecret === 'string' ? new TextEncoder().encode(login?.jwtSecret) : login?.jwtSecret
303
305
 
304
306
  const routePrefix = (prefix ?? '/api') as P
305
307
 
306
- // Auto-detect metricsEnabled from client if not explicitly set
307
- const isMetricsEnabled = metricsEnabled ?? client.metricsEnabled
308
+ // Auto-detect spansEnabled from client if not explicitly set
309
+ const isSpansEnabled = spansEnabled ?? client.spansEnabled
308
310
 
309
311
  return new Elysia({
310
312
  prefix: routePrefix,
@@ -670,14 +672,14 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
670
672
  '/config',
671
673
  async () => {
672
674
  return {
673
- metricsEnabled: isMetricsEnabled,
675
+ spansEnabled: isSpansEnabled,
674
676
  authEnabled: !!login,
675
677
  }
676
678
  },
677
679
  {
678
680
  response: {
679
681
  200: z.object({
680
- metricsEnabled: z.boolean(),
682
+ spansEnabled: z.boolean(),
681
683
  authEnabled: z.boolean(),
682
684
  }),
683
685
  500: ErrorResponseSchema,
@@ -685,23 +687,23 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
685
687
  },
686
688
  )
687
689
  .get(
688
- '/jobs/:id/metrics',
690
+ '/jobs/:id/spans',
689
691
  async ({ params, query }) => {
690
- if (!isMetricsEnabled) {
691
- throw new Error('Metrics are not enabled. Use LocalTelemetryAdapter to enable metrics.')
692
+ if (!isSpansEnabled) {
693
+ throw new Error('Spans are not enabled. Enable telemetry.local to enable spans.')
692
694
  }
693
- const options: GetMetricsOptions = {
695
+ const options: GetSpansOptions = {
694
696
  jobId: params.id,
695
697
  filters: query.filters,
696
698
  sort: query.sort,
697
699
  }
698
- return client.getMetrics(options)
700
+ return client.getSpans(options)
699
701
  },
700
702
  {
701
703
  params: JobIdParamsSchema,
702
- query: GetMetricsQuerySchema,
704
+ query: GetSpansQuerySchema,
703
705
  response: {
704
- 200: GetMetricsResultSchema,
706
+ 200: GetSpansResultSchema,
705
707
  400: ErrorResponseSchema,
706
708
  500: ErrorResponseSchema,
707
709
  401: ErrorResponseSchema,
@@ -710,23 +712,23 @@ export function createServer<P extends string>({ client, prefix, login, metricsE
710
712
  },
711
713
  )
712
714
  .get(
713
- '/steps/:id/metrics',
715
+ '/steps/:id/spans',
714
716
  async ({ params, query }) => {
715
- if (!isMetricsEnabled) {
716
- throw new Error('Metrics are not enabled. Use LocalTelemetryAdapter to enable metrics.')
717
+ if (!isSpansEnabled) {
718
+ throw new Error('Spans are not enabled. Enable telemetry.local to enable spans.')
717
719
  }
718
- const options: GetMetricsOptions = {
720
+ const options: GetSpansOptions = {
719
721
  stepId: params.id,
720
722
  filters: query.filters,
721
723
  sort: query.sort,
722
724
  }
723
- return client.getMetrics(options)
725
+ return client.getSpans(options)
724
726
  },
725
727
  {
726
728
  params: StepIdParamsSchema,
727
- query: GetMetricsQuerySchema,
729
+ query: GetSpansQuerySchema,
728
730
  response: {
729
- 200: GetMetricsResultSchema,
731
+ 200: GetSpansResultSchema,
730
732
  400: ErrorResponseSchema,
731
733
  500: ErrorResponseSchema,
732
734
  401: ErrorResponseSchema,