From c588fd2338a76579facf0cc0f8fe8efa238bbb25 Mon Sep 17 00:00:00 2001 From: Charles Korn Date: Mon, 16 Mar 2026 16:47:37 +1100 Subject: [PATCH] chore: document supported formats for duration query request parameters in OpenAPI spec Signed-off-by: Charles Korn --- web/api/v1/openapi_helpers.go | 18 +++++++++ web/api/v1/openapi_paths.go | 10 ++--- web/api/v1/testdata/openapi_3.1_golden.yaml | 45 ++++++++++++++++++--- web/api/v1/testdata/openapi_3.2_golden.yaml | 45 ++++++++++++++++++--- 4 files changed, 103 insertions(+), 15 deletions(-) diff --git a/web/api/v1/openapi_helpers.go b/web/api/v1/openapi_helpers.go index 76f6001693..fd00567194 100644 --- a/web/api/v1/openapi_helpers.go +++ b/web/api/v1/openapi_helpers.go @@ -168,6 +168,24 @@ func timestampSchema() *base.SchemaProxy { }) } +func durationSchema() *base.SchemaProxy { + return base.CreateSchemaProxy(&base.Schema{ + OneOf: []*base.SchemaProxy{ + base.CreateSchemaProxy(&base.Schema{ + Type: []string{"string"}, + Format: "duration", + Description: "Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s.", + }), + base.CreateSchemaProxy(&base.Schema{ + Type: []string{"number"}, + Format: "float", + Description: "Fractional number of seconds, such as 2 or 4.5.", + }), + }, + Description: "Duration in humand-readable or numeric format.", + }) +} + func stringSchemaWithConstValue(value string) *base.SchemaProxy { node := &yaml.Node{Kind: yaml.ScalarNode, Value: value} return base.CreateSchemaProxy(&base.Schema{ diff --git a/web/api/v1/openapi_paths.go b/web/api/v1/openapi_paths.go index 2f5ab592f7..45db56912c 100644 --- a/web/api/v1/openapi_paths.go +++ b/web/api/v1/openapi_paths.go @@ -30,8 +30,8 @@ func (*OpenAPIBuilder) queryPath() *v3.PathItem { queryParamWithExample("limit", "The maximum number of metrics to return.", false, integerSchema(), []example{{"example", 100}}), queryParamWithExample("time", "The evaluation timestamp (optional, defaults to current time).", false, timestampSchema(), timestampExamples(exampleTime)), queryParamWithExample("query", "The PromQL query to execute.", true, stringSchema(), []example{{"example", "up"}}), - queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, stringSchema(), []example{{"example", "30s"}}), - queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, stringSchema(), []example{{"example", "5m"}}), + queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, durationSchema(), []example{{"example", "30s"}}), + queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"example", "5m"}}), queryParamWithExample("stats", "When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics.", false, stringSchema(), []example{{"example", "all"}}), } return &v3.PathItem{ @@ -57,10 +57,10 @@ func (*OpenAPIBuilder) queryRangePath() *v3.PathItem { queryParamWithExample("limit", "The maximum number of metrics to return.", false, integerSchema(), []example{{"example", 100}}), queryParamWithExample("start", "The start time of the query.", true, timestampSchema(), timestampExamples(exampleTime.Add(-1*time.Hour))), queryParamWithExample("end", "The end time of the query.", true, timestampSchema(), timestampExamples(exampleTime)), - queryParamWithExample("step", "The step size of the query.", true, stringSchema(), []example{{"example", "15s"}}), + queryParamWithExample("step", "The step size of the query.", true, durationSchema(), []example{{"example", "15s"}}), queryParamWithExample("query", "The query to execute.", true, stringSchema(), []example{{"example", "rate(prometheus_http_requests_total{handler=\"/api/v1/query\"}[5m])"}}), - queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, stringSchema(), []example{{"example", "30s"}}), - queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, stringSchema(), []example{{"example", "5m"}}), + queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, durationSchema(), []example{{"example", "30s"}}), + queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"example", "5m"}}), queryParamWithExample("stats", "When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics.", false, stringSchema(), []example{{"example", "all"}}), } return &v3.PathItem{ diff --git a/web/api/v1/testdata/openapi_3.1_golden.yaml b/web/api/v1/testdata/openapi_3.1_golden.yaml index b1514f209d..8c5d028ae5 100644 --- a/web/api/v1/testdata/openapi_3.1_golden.yaml +++ b/web/api/v1/testdata/openapi_3.1_golden.yaml @@ -62,7 +62,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 30s @@ -72,7 +79,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 5m @@ -248,7 +262,14 @@ paths: required: true explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 15s @@ -268,7 +289,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 30s @@ -278,7 +306,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 5m diff --git a/web/api/v1/testdata/openapi_3.2_golden.yaml b/web/api/v1/testdata/openapi_3.2_golden.yaml index fa79fffecc..944ad1a476 100644 --- a/web/api/v1/testdata/openapi_3.2_golden.yaml +++ b/web/api/v1/testdata/openapi_3.2_golden.yaml @@ -62,7 +62,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 30s @@ -72,7 +79,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 5m @@ -248,7 +262,14 @@ paths: required: true explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 15s @@ -268,7 +289,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 30s @@ -278,7 +306,14 @@ paths: required: false explode: false schema: - type: string + oneOf: + - type: string + format: duration + description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + - type: number + format: float + description: Fractional number of seconds, such as 2 or 4.5. + description: Duration in humand-readable or numeric format. examples: example: value: 5m