From c588fd2338a76579facf0cc0f8fe8efa238bbb25 Mon Sep 17 00:00:00 2001 From: Charles Korn Date: Mon, 16 Mar 2026 16:47:37 +1100 Subject: [PATCH 1/2] 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 From 8763eef66622a3742586af19e6c175f60a55c8d7 Mon Sep 17 00:00:00 2001 From: Charles Korn Date: Tue, 17 Mar 2026 10:40:56 +1100 Subject: [PATCH 2/2] Address PR feedback: fix typo, move examples, clarify supported duration format Signed-off-by: Charles Korn --- web/api/v1/openapi_helpers.go | 6 +-- web/api/v1/openapi_paths.go | 10 ++-- web/api/v1/testdata/openapi_3.1_golden.yaml | 54 ++++++++++++--------- web/api/v1/testdata/openapi_3.2_golden.yaml | 54 ++++++++++++--------- 4 files changed, 72 insertions(+), 52 deletions(-) diff --git a/web/api/v1/openapi_helpers.go b/web/api/v1/openapi_helpers.go index fd00567194..666310bf0c 100644 --- a/web/api/v1/openapi_helpers.go +++ b/web/api/v1/openapi_helpers.go @@ -174,15 +174,15 @@ func durationSchema() *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.", + Description: "Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years).", }), base.CreateSchemaProxy(&base.Schema{ Type: []string{"number"}, Format: "float", - Description: "Fractional number of seconds, such as 2 or 4.5.", + Description: "Fractional number of seconds.", }), }, - Description: "Duration in humand-readable or numeric format.", + Description: "Duration in human-readable or numeric format.", }) } diff --git a/web/api/v1/openapi_paths.go b/web/api/v1/openapi_paths.go index 45db56912c..55d4c1aa59 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, durationSchema(), []example{{"example", "30s"}}), - queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"example", "5m"}}), + queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, durationSchema(), []example{{"duration", "1m30s"}, {"number", "90"}}), + queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"duration", "5m"}, {"number", "300"}}), 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, durationSchema(), []example{{"example", "15s"}}), + queryParamWithExample("step", "The step size of the query.", true, durationSchema(), []example{{"duration", "15s"}, {"number", "15"}}), 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, durationSchema(), []example{{"example", "30s"}}), - queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"example", "5m"}}), + queryParamWithExample("timeout", "Evaluation timeout. Optional. Defaults to and is capped by the value of the -query.timeout flag.", false, durationSchema(), []example{{"duration", "1m30s"}, {"number", "90"}}), + queryParamWithExample("lookback_delta", "Override the lookback period for this query. Optional.", false, durationSchema(), []example{{"duration", "5m"}, {"number", "300"}}), 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 8c5d028ae5..dce85a7373 100644 --- a/web/api/v1/testdata/openapi_3.1_golden.yaml +++ b/web/api/v1/testdata/openapi_3.1_golden.yaml @@ -65,14 +65,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: - value: 30s + duration: + value: 1m30s + number: + value: "90" - name: lookback_delta in: query description: Override the lookback period for this query. Optional. @@ -82,14 +84,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 5m + number: + value: "300" - name: stats in: query description: When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics. @@ -265,14 +269,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 15s + number: + value: "15" - name: query in: query description: The query to execute. @@ -292,14 +298,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: - value: 30s + duration: + value: 1m30s + number: + value: "90" - name: lookback_delta in: query description: Override the lookback period for this query. Optional. @@ -309,14 +317,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 5m + number: + value: "300" - name: stats in: query description: When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics. diff --git a/web/api/v1/testdata/openapi_3.2_golden.yaml b/web/api/v1/testdata/openapi_3.2_golden.yaml index 944ad1a476..3581576735 100644 --- a/web/api/v1/testdata/openapi_3.2_golden.yaml +++ b/web/api/v1/testdata/openapi_3.2_golden.yaml @@ -65,14 +65,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: - value: 30s + duration: + value: 1m30s + number: + value: "90" - name: lookback_delta in: query description: Override the lookback period for this query. Optional. @@ -82,14 +84,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 5m + number: + value: "300" - name: stats in: query description: When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics. @@ -265,14 +269,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 15s + number: + value: "15" - name: query in: query description: The query to execute. @@ -292,14 +298,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: - value: 30s + duration: + value: 1m30s + number: + value: "90" - name: lookback_delta in: query description: Override the lookback period for this query. Optional. @@ -309,14 +317,16 @@ paths: oneOf: - type: string format: duration - description: Human-readable form accepted by Go's time.Duration.ParseDuration(), such as 15s or 2m30s. + description: Human-readable form such as 15s or 2m30s. Supported units are ms (milliseconds), s (seconds), m (minutes), h (hours), d (days), w (weeks) and y (years). - type: number format: float - description: Fractional number of seconds, such as 2 or 4.5. - description: Duration in humand-readable or numeric format. + description: Fractional number of seconds. + description: Duration in human-readable or numeric format. examples: - example: + duration: value: 5m + number: + value: "300" - name: stats in: query description: When provided, include query statistics in the response. The special value 'all' enables more comprehensive statistics.