diff --git a/diagnostics.go b/diagnostics.go index e6da984..29a9cb4 100644 --- a/diagnostics.go +++ b/diagnostics.go @@ -20,3 +20,17 @@ func (s *DiagnosticsService) QueryData(ctx context.Context, req *QueryDataReques } return out, resp, nil } + +// Run Explore query. +// +// Run an Explore query against a configured data source and return frames, samples, or logs. +// +// API: POST /monit/query/explore (monit-read-query-explore). +func (s *DiagnosticsService) QueryExplore(ctx context.Context, req *QueryExploreRequest) (*ExploreData, *Response, error) { + out := new(ExploreData) + resp, err := s.client.do(ctx, "/monit/query/explore", req, out) + if err != nil { + return nil, resp, err + } + return out, resp, nil +} diff --git a/models_gen.go b/models_gen.go index 900864b..b6bc5fd 100644 --- a/models_gen.go +++ b/models_gen.go @@ -3252,6 +3252,74 @@ type EventItem struct { UsageMetadata map[string]any `json:"usage_metadata" toon:"usage_metadata"` } +// ExploreData is generated from the Flashduty OpenAPI schema. +type ExploreData struct { + Execution ExploreResponseExecution `json:"execution" toon:"execution"` + // Result contract version; always `explore_result.v1`. + Format string `json:"format" toon:"format"` + Result ExploreResult `json:"result" toon:"result"` +} + +// ExploreField is generated from the Flashduty OpenAPI schema. +type ExploreField struct { + // Label set of this column. Only `time_series` value fields may carry labels; a `table` field must not. + Labels map[string]string `json:"labels" toon:"labels"` + // Column name, at most 1 MiB of UTF-8. + Name string `json:"name" toon:"name"` + // Column type. `string` is rejected inside a `time_series` frame; `float` holds numbers and `time` holds UTC RFC3339Nano strings. + Type string `json:"type" toon:"type"` + // Column values in row order. + Values []any `json:"values" toon:"values"` +} + +// ExploreFrame is generated from the Flashduty OpenAPI schema. +type ExploreFrame struct { + // Columns of the frame. + Fields []ExploreField `json:"fields" toon:"fields"` + // Frame shape. `table` is an unlabeled table, while `time_series` carries exactly one time field and one float field. + Kind string `json:"kind" toon:"kind"` +} + +// ExploreLogEntry is generated from the Flashduty OpenAPI schema. +type ExploreLogEntry struct { + // Log fields as raw JSON values. Integer literals outside JavaScript's safe integer range are returned as decimal strings. + Fields map[string]any `json:"fields" toon:"fields"` + // Entry time as a canonical unsigned decimal string of Unix epoch nanoseconds, at most 20 digits. + TimestampNs string `json:"timestamp_ns" toon:"timestamp_ns"` +} + +// ExploreResponseExecution is generated from the Flashduty OpenAPI schema. +type ExploreResponseExecution struct { + // Step, in seconds, the query was executed with after applying `max_data_points` and `min_step_seconds`. + EffectiveStepSeconds int64 `json:"effective_step_seconds" toon:"effective_step_seconds"` + // Execution kind; always `range` when this object is present. + Kind string `json:"kind" toon:"kind"` +} + +// ExploreResult is generated from the Flashduty OpenAPI schema. +type ExploreResult struct { + // Entry limit applied to a logs result; at most 1000. + AppliedLimit int64 `json:"applied_limit" toon:"applied_limit"` + // Log entries. Present when `kind` is `logs`; never longer than `applied_limit`. + Entries []ExploreLogEntry `json:"entries" toon:"entries"` + // Columnar frames. Present when `kind` is `frames`; at most 1,000 frames. + Frames []ExploreFrame `json:"frames" toon:"frames"` + // Whether a logs result was truncated by `applied_limit`. + HasMore bool `json:"has_more" toon:"has_more"` + // Result shape. `frames` returns columnar tables or time series, `samples` returns instant values with labels, and `logs` returns log entries. + Kind string `json:"kind" toon:"kind"` + // Instant samples. Present when `kind` is `samples`; at most 1,000 samples. + Samples []ExploreSample `json:"samples" toon:"samples"` +} + +// ExploreSample is generated from the Flashduty OpenAPI schema. +type ExploreSample struct { + // Label set of the sample. May be empty but never null. + Labels map[string]string `json:"labels" toon:"labels"` + // Sample value: a number, or one of the strings `NaN`, `+Inf`, and `-Inf`. Never null. + Value any `json:"value" toon:"value"` +} + // ExportStatusPageSubscribersRequest is generated from the Flashduty OpenAPI schema. type ExportStatusPageSubscribersRequest struct { // Optional component IDs to filter subscribers by. @@ -6314,6 +6382,18 @@ type PreviewTemplateResponse struct { Success bool `json:"success" toon:"success"` } +// PrometheusLabelValuesResponse is generated from the Flashduty OpenAPI schema. +type PrometheusLabelValuesResponse struct { + // Label values, present when `status` is `success`. + Data []string `json:"data" toon:"data"` + // Human-readable Prometheus error message, present when `status` is `error`. + Error string `json:"error" toon:"error"` + // Prometheus error class, present when `status` is `error`. + ErrorType string `json:"errorType" toon:"errorType"` + // Prometheus result status. `success` carries `data`; `error` carries `errorType` and `error`. + Status string `json:"status" toon:"status"` +} + // PublishedArtifactItem is generated from the Flashduty OpenAPI schema. type PublishedArtifactItem struct { // Artifact ID (`art_` prefix). Also the key of the public-share link. @@ -6383,6 +6463,31 @@ type QueryDataResponse struct { Result QueryResult `json:"result" toon:"result"` } +// QueryExploreExecution is generated from the Flashduty OpenAPI schema. +type QueryExploreExecution struct { + // Unix timestamp in milliseconds for the start of the range. Required for `range` and `window`; optional for `instant`. + FromMs int64 `json:"from_ms,omitempty" toon:"from_ms,omitempty"` + // Execution kind. `instant` evaluates at a single point in time, `range` evaluates a series over a range, and `window` returns raw rows inside a time window. + Kind string `json:"kind" toon:"kind"` + // Maximum number of points to return. Required for `range` and rejected for `instant` and `window`. + MaxDataPoints int64 `json:"max_data_points,omitempty" toon:"max_data_points,omitempty"` + // Lower bound, in seconds, for the step derived from `max_data_points`. Optional and only accepted for `range`. + MinStepSeconds int64 `json:"min_step_seconds,omitempty" toon:"min_step_seconds,omitempty"` + // Unix timestamp in milliseconds for the end of the range. Required for every execution kind. + ToMs int64 `json:"to_ms,omitempty" toon:"to_ms,omitempty"` +} + +// QueryExploreRequest is generated from the Flashduty OpenAPI schema. +type QueryExploreRequest struct { + // Macro substitutions keyed by variable name, used for Grafana-style variables. Keys are at most 256 bytes, values at most 64 KiB, with a 128 KiB total budget. + Args map[string]string `json:"args" toon:"args"` + // Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer and belong to the authenticated account. + DatasourceID int64 `json:"datasource_id" toon:"datasource_id"` + Execution QueryExploreExecution `json:"execution" toon:"execution"` + // Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; some data source types enforce a lower limit. + Expr string `json:"expr" toon:"expr"` +} + // QueryField is generated from the Flashduty OpenAPI schema. type QueryField struct { // Series labels. Present on the float field of a time-series frame. diff --git a/openapi/openapi.en.json b/openapi/openapi.en.json index fde38c6..98a543d 100644 --- a/openapi/openapi.en.json +++ b/openapi/openapi.en.json @@ -9151,6 +9151,309 @@ ], "type": "object" }, + "ExploreData": { + "description": "Explore query result payload.", + "properties": { + "execution": { + "$ref": "#/components/schemas/ExploreResponseExecution" + }, + "format": { + "description": "Result contract version; always `explore_result.v1`.", + "enum": [ + "explore_result.v1" + ], + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/ExploreResult" + } + }, + "required": [ + "format", + "result" + ], + "type": "object" + }, + "ExploreField": { + "description": "One column of a frame. Values are columnar and may contain nulls.", + "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Label set of this column. Only `time_series` value fields may carry labels; a `table` field must not.", + "type": "object" + }, + "name": { + "description": "Column name, at most 1 MiB of UTF-8.", + "type": "string" + }, + "type": { + "description": "Column type. `string` is rejected inside a `time_series` frame; `float` holds numbers and `time` holds UTC RFC3339Nano strings.", + "enum": [ + "string", + "float", + "time" + ], + "type": "string" + }, + "values": { + "description": "Column values in row order.", + "items": { + "description": "One cell. `time` cells are UTC RFC3339Nano strings; `float` cells may be the strings `NaN`, `+Inf`, and `-Inf`; any cell may be null except a time value inside a `time_series` frame." + }, + "type": "array" + } + }, + "required": [ + "name", + "type", + "values" + ], + "type": "object" + }, + "ExploreFrame": { + "description": "One columnar frame. Every field in the frame has the same number of values.", + "properties": { + "fields": { + "description": "Columns of the frame.", + "items": { + "$ref": "#/components/schemas/ExploreField" + }, + "type": "array" + }, + "kind": { + "description": "Frame shape. `table` is an unlabeled table, while `time_series` carries exactly one time field and one float field.", + "enum": [ + "table", + "time_series" + ], + "type": "string" + } + }, + "required": [ + "kind", + "fields" + ], + "type": "object" + }, + "ExploreLogEntry": { + "description": "One log entry.", + "properties": { + "fields": { + "additionalProperties": true, + "description": "Log fields as raw JSON values. Integer literals outside JavaScript's safe integer range are returned as decimal strings.", + "type": "object" + }, + "timestamp_ns": { + "description": "Entry time as a canonical unsigned decimal string of Unix epoch nanoseconds, at most 20 digits.", + "type": "string" + } + }, + "required": [ + "timestamp_ns", + "fields" + ], + "type": "object" + }, + "ExploreResponseExecution": { + "description": "Execution actually used, present when the data source returned a stepped result.", + "properties": { + "effective_step_seconds": { + "description": "Step, in seconds, the query was executed with after applying `max_data_points` and `min_step_seconds`.", + "format": "int64", + "type": "integer" + }, + "kind": { + "description": "Execution kind; always `range` when this object is present.", + "enum": [ + "range" + ], + "type": "string" + } + }, + "required": [ + "kind", + "effective_step_seconds" + ], + "type": "object" + }, + "ExploreResult": { + "description": "Result body. Exactly one of `frames`, `samples`, or `entries` is present and matches `kind`.", + "properties": { + "applied_limit": { + "description": "Entry limit applied to a logs result; at most 1000.", + "type": "integer" + }, + "entries": { + "description": "Log entries. Present when `kind` is `logs`; never longer than `applied_limit`.", + "items": { + "$ref": "#/components/schemas/ExploreLogEntry" + }, + "type": "array" + }, + "frames": { + "description": "Columnar frames. Present when `kind` is `frames`; at most 1,000 frames.", + "items": { + "$ref": "#/components/schemas/ExploreFrame" + }, + "type": "array" + }, + "has_more": { + "description": "Whether a logs result was truncated by `applied_limit`.", + "type": "boolean" + }, + "kind": { + "description": "Result shape. `frames` returns columnar tables or time series, `samples` returns instant values with labels, and `logs` returns log entries.", + "enum": [ + "frames", + "samples", + "logs" + ], + "type": "string" + }, + "samples": { + "description": "Instant samples. Present when `kind` is `samples`; at most 1,000 samples.", + "items": { + "$ref": "#/components/schemas/ExploreSample" + }, + "type": "array" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "ExploreSample": { + "description": "One instant sample.", + "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "Label set of the sample. May be empty but never null.", + "type": "object" + }, + "value": { + "description": "Sample value: a number, or one of the strings `NaN`, `+Inf`, and `-Inf`. Never null." + } + }, + "required": [ + "labels", + "value" + ], + "type": "object" + }, + "PrometheusLabelValuesResponse": { + "description": "Native Prometheus HTTP API response returned by the queried data source. This endpoint does not wrap the payload in the Flashduty response envelope.", + "properties": { + "data": { + "description": "Label values, present when `status` is `success`.", + "items": { + "description": "One label value.", + "type": "string" + }, + "type": "array" + }, + "error": { + "description": "Human-readable Prometheus error message, present when `status` is `error`.", + "type": "string" + }, + "errorType": { + "description": "Prometheus error class, present when `status` is `error`.", + "type": "string" + }, + "status": { + "description": "Prometheus result status. `success` carries `data`; `error` carries `errorType` and `error`.", + "enum": [ + "success", + "error" + ], + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "QueryExploreExecution": { + "description": "Time semantics of the query. The accepted companion fields depend on `kind`: `instant` takes only `to_ms` (plus optional `from_ms`), `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` takes only `from_ms` and `to_ms`. `step_seconds` is never accepted over HTTP.", + "properties": { + "from_ms": { + "description": "Unix timestamp in milliseconds for the start of the range. Required for `range` and `window`; optional for `instant`.", + "format": "int64", + "type": "integer" + }, + "kind": { + "description": "Execution kind. `instant` evaluates at a single point in time, `range` evaluates a series over a range, and `window` returns raw rows inside a time window.", + "enum": [ + "instant", + "range", + "window" + ], + "type": "string" + }, + "max_data_points": { + "description": "Maximum number of points to return. Required for `range` and rejected for `instant` and `window`.", + "format": "int64", + "maximum": 5000, + "minimum": 2, + "type": "integer" + }, + "min_step_seconds": { + "description": "Lower bound, in seconds, for the step derived from `max_data_points`. Optional and only accepted for `range`.", + "format": "int64", + "minimum": 1, + "type": "integer" + }, + "to_ms": { + "description": "Unix timestamp in milliseconds for the end of the range. Required for every execution kind.", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "QueryExploreRequest": { + "description": "Explore query request. All four top-level fields are required and unknown fields are rejected.", + "properties": { + "args": { + "additionalProperties": { + "type": "string" + }, + "description": "Macro substitutions keyed by variable name, used for Grafana-style variables. Keys are at most 256 bytes, values at most 64 KiB, with a 128 KiB total budget.", + "maxProperties": 128, + "type": "object" + }, + "datasource_id": { + "description": "Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer and belong to the authenticated account.", + "format": "int64", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "execution": { + "$ref": "#/components/schemas/QueryExploreExecution" + }, + "expr": { + "description": "Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; some data source types enforce a lower limit.", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "datasource_id", + "expr", + "args", + "execution" + ], + "type": "object" + }, "ExportStatusPageSubscribersRequest": { "description": "Parameters for exporting a status page subscriber list.", "properties": { @@ -42686,6 +42989,291 @@ } } }, + "/monit/prometheus/api/v1/label/{label_name}/values": { + "get": { + "description": "Read label values from a Prometheus-compatible data source through the Monitors proxy.", + "operationId": "monit-prometheus-read-label-values", + "parameters": [ + { + "description": "Label name to enumerate values for, for example `job`.", + "in": "path", + "name": "label_name", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Data source ID to query. Must reference a Prometheus-compatible data source owned by the authenticated account.", + "in": "header", + "name": "X-DSID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": [ + "api", + "db", + "worker" + ], + "status": "success" + }, + "schema": { + "$ref": "#/components/schemas/PrometheusLabelValuesResponse" + } + } + }, + "description": "Native Prometheus label-values response returned by the data source." + }, + "400": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "The `X-DSID` header is missing or invalid, the data source does not exist, or it is not a Prometheus data source. Returned as `text/plain`." + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "The data source lookup or the proxied request failed. Returned as `text/plain`." + }, + "503": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "No monit-edge in the data source's cluster supports the data source resource proxy. Returned as `text/plain`; upgrade monit-edge." + } + }, + "summary": "List Prometheus label values", + "tags": [ + "Monitors/Data sources" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | Any valid `app_key` (read-only; not gated by a specific permission class) |\n| Edge requirement | Supported deployments require **monit-edge v0.35.0 or later** |\n\n## Usage\n\n- Pass the target data source in the `X-DSID` header. It must be a Prometheus-compatible data source owned by the authenticated account; use `/monit/datasource/list` to obtain its ID.\n- The 200 body is the data source's native Prometheus HTTP API payload, **not** the standard `{ request_id, data }` envelope. Failures raised before the data source is reached are returned as `text/plain` with the matching 4xx or 5xx status.\n- When `X-DSID` is omitted, the request falls back to the platform's own Prometheus proxy. Send the header to query a specific data source.", + "href": "/en/api-reference/monitors/data-sources/monit-prometheus-read-label-values", + "metadata": { + "sidebarTitle": "List Prometheus label values" + } + } + } + }, + "/monit/query/explore": { + "post": { + "description": "Run an Explore query against a configured data source and return frames, samples, or logs.", + "operationId": "monit-read-query-explore", + "requestBody": { + "content": { + "application/json": { + "example": { + "args": {}, + "datasource_id": 101, + "execution": { + "from_ms": 1787187600000, + "kind": "range", + "max_data_points": 1200, + "min_step_seconds": 15, + "to_ms": 1787191200000 + }, + "expr": "rate(http_requests_total[5m])" + }, + "schema": { + "$ref": "#/components/schemas/QueryExploreRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": { + "execution": { + "effective_step_seconds": 60, + "kind": "range" + }, + "format": "explore_result.v1", + "result": { + "frames": [ + { + "fields": [ + { + "name": "time", + "type": "time", + "values": [ + "2026-08-20T10:00:00Z", + "2026-08-20T10:01:00Z" + ] + }, + { + "labels": { + "job": "api" + }, + "name": "value", + "type": "float", + "values": [ + 1.25, + null + ] + } + ], + "kind": "time_series" + } + ], + "kind": "frames" + } + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "properties": { + "data": { + "$ref": "#/components/schemas/ExploreData" + } + }, + "type": "object" + } + ] + } + } + }, + "description": "Success" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: invalid_request." + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: access_denied." + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: datasource_not_found." + }, + "413": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: source_too_large, result_too_large." + }, + "429": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: overloaded." + }, + "499": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: canceled." + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: internal." + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: no_active_edge, edge_upgrade_required, mixed_edge_versions, edge_unavailable." + }, + "504": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: timeout." + } + }, + "summary": "Run Explore query", + "tags": [ + "Monitors/Diagnostics" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **100 requests/minute**; **16 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n| Edge requirement | Supported deployments require **monit-edge v0.68.0 or later** |\n\n## Usage\n\n- Use this endpoint when you need the data source's native result shape; `/monit/query/data` returns the stable `query_result.v1` contract instead. Dispatch on `data.result.kind` (`frames`, `samples`, or `logs`) here.\n- `execution.kind` decides which companion fields are accepted: `instant` needs only `to_ms`, `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` takes `from_ms` and `to_ms`. `step_seconds` is not accepted; the step is derived from `max_data_points` and `min_step_seconds`.\n- `args` carries macro substitutions such as Grafana-style variables; every value is a string.\n- A `logs` result is capped at 1,000 entries and reports `applied_limit` plus `has_more`. Time-series and sample results are capped at 1,000 items each and the whole success response at 8 MiB.\n- Query execution may take up to 35 seconds across WebAPI forwarding and Edge execution. Configure client timeouts to at least 40 seconds.", + "href": "/en/api-reference/monitors/diagnostics/monit-read-query-explore", + "metadata": { + "sidebarTitle": "Run Explore query" + } + } + } + }, "/monit/query/data": { "post": { "description": "Run a synchronous ad-hoc query against a configured data source and return a stable `query_result.v1` result whose natural shape is frames, records, or samples. This public API requires monit-edge v0.65.0 or later.", diff --git a/openapi/openapi.zh.json b/openapi/openapi.zh.json index 90bc053..7fd2fe0 100644 --- a/openapi/openapi.zh.json +++ b/openapi/openapi.zh.json @@ -9151,6 +9151,309 @@ ], "type": "object" }, + "ExploreData": { + "description": "探索查询结果载荷。", + "properties": { + "execution": { + "$ref": "#/components/schemas/ExploreResponseExecution" + }, + "format": { + "description": "结果契约版本,固定为 `explore_result.v1`。", + "enum": [ + "explore_result.v1" + ], + "type": "string" + }, + "result": { + "$ref": "#/components/schemas/ExploreResult" + } + }, + "required": [ + "format", + "result" + ], + "type": "object" + }, + "ExploreField": { + "description": "Frame 的一列。取值按列组织,可以包含 null。", + "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "该列的标签集合。仅 `time_series` 的取值字段可以携带标签,`table` 字段不允许。", + "type": "object" + }, + "name": { + "description": "列名,最长 1 MiB 的 UTF-8 字符串。", + "type": "string" + }, + "type": { + "description": "列类型。`time_series` 内不接受 `string`;`float` 存放数值,`time` 取值为 UTC RFC3339Nano 字符串。", + "enum": [ + "string", + "float", + "time" + ], + "type": "string" + }, + "values": { + "description": "按行顺序排列的列取值。", + "items": { + "description": "单个单元格。`time` 为 UTC RFC3339Nano 字符串,`float` 可以是字符串 `NaN`、`+Inf`、`-Inf`,除 `time_series` 中的时间值外均可以为 null。" + }, + "type": "array" + } + }, + "required": [ + "name", + "type", + "values" + ], + "type": "object" + }, + "ExploreFrame": { + "description": "单个列式 Frame,Frame 内所有字段的取值数量一致。", + "properties": { + "fields": { + "description": "Frame 的列。", + "items": { + "$ref": "#/components/schemas/ExploreField" + }, + "type": "array" + }, + "kind": { + "description": "Frame 形态。`table` 为无标签表格,`time_series` 恰好包含一个时间字段和一个 float 字段。", + "enum": [ + "table", + "time_series" + ], + "type": "string" + } + }, + "required": [ + "kind", + "fields" + ], + "type": "object" + }, + "ExploreLogEntry": { + "description": "单条日志。", + "properties": { + "fields": { + "additionalProperties": true, + "description": "日志字段的原始 JSON 取值。超出 JavaScript 安全整数范围的整数字面量会以十进制字符串返回。", + "type": "object" + }, + "timestamp_ns": { + "description": "条目时间,使用 Unix 纪元纳秒的规范无符号十进制字符串表示,最长 20 位。", + "type": "string" + } + }, + "required": [ + "timestamp_ns", + "fields" + ], + "type": "object" + }, + "ExploreResponseExecution": { + "description": "实际使用的执行信息,数据源返回带步长结果时出现。", + "properties": { + "effective_step_seconds": { + "description": "应用 `max_data_points` 与 `min_step_seconds` 后实际执行的步长(秒)。", + "format": "int64", + "type": "integer" + }, + "kind": { + "description": "执行类型;该对象出现时固定为 `range`。", + "enum": [ + "range" + ], + "type": "string" + } + }, + "required": [ + "kind", + "effective_step_seconds" + ], + "type": "object" + }, + "ExploreResult": { + "description": "结果主体。`frames`、`samples`、`entries` 三者中只有与 `kind` 匹配的一个会出现。", + "properties": { + "applied_limit": { + "description": "日志结果实际生效的条数上限,最大 1000。", + "type": "integer" + }, + "entries": { + "description": "日志条目列表,`kind` 为 `logs` 时出现,长度不超过 `applied_limit`。", + "items": { + "$ref": "#/components/schemas/ExploreLogEntry" + }, + "type": "array" + }, + "frames": { + "description": "列式 Frame 列表,`kind` 为 `frames` 时出现,最多 1,000 个。", + "items": { + "$ref": "#/components/schemas/ExploreFrame" + }, + "type": "array" + }, + "has_more": { + "description": "日志结果是否因 `applied_limit` 被截断。", + "type": "boolean" + }, + "kind": { + "description": "结果形态。`frames` 返回列式表格或时序,`samples` 返回带标签的瞬时值,`logs` 返回日志条目。", + "enum": [ + "frames", + "samples", + "logs" + ], + "type": "string" + }, + "samples": { + "description": "瞬时采样列表,`kind` 为 `samples` 时出现,最多 1,000 条。", + "items": { + "$ref": "#/components/schemas/ExploreSample" + }, + "type": "array" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "ExploreSample": { + "description": "单个瞬时采样。", + "properties": { + "labels": { + "additionalProperties": { + "type": "string" + }, + "description": "采样的标签集合。可以为空,但不能为 null。", + "type": "object" + }, + "value": { + "description": "采样值:数字,或字符串 `NaN`、`+Inf`、`-Inf`。不能为 null。" + } + }, + "required": [ + "labels", + "value" + ], + "type": "object" + }, + "PrometheusLabelValuesResponse": { + "description": "所查询数据源返回的原生 Prometheus HTTP API 响应。本接口不会把结果包装进 Flashduty 统一响应 envelope。", + "properties": { + "data": { + "description": "标签值列表,`status` 为 `success` 时出现。", + "items": { + "description": "一个标签值。", + "type": "string" + }, + "type": "array" + }, + "error": { + "description": "Prometheus 错误信息,`status` 为 `error` 时出现。", + "type": "string" + }, + "errorType": { + "description": "Prometheus 错误类别,`status` 为 `error` 时出现。", + "type": "string" + }, + "status": { + "description": "Prometheus 结果状态。`success` 携带 `data`,`error` 携带 `errorType` 与 `error`。", + "enum": [ + "success", + "error" + ], + "type": "string" + } + }, + "required": [ + "status" + ], + "type": "object" + }, + "QueryExploreExecution": { + "description": "查询的时间语义。可接受的配套字段取决于 `kind`:`instant` 只需 `to_ms`(`from_ms` 可选),`range` 需要 `from_ms`、`to_ms` 和 `max_data_points`,`window` 需要 `from_ms` 和 `to_ms`。HTTP 接口不接受 `step_seconds`。", + "properties": { + "from_ms": { + "description": "范围起点的 Unix 毫秒时间戳。`range` 和 `window` 必填,`instant` 可选。", + "format": "int64", + "type": "integer" + }, + "kind": { + "description": "执行类型。`instant` 在单个时间点取值,`range` 在时间范围内取序列,`window` 返回时间窗口内的原始行。", + "enum": [ + "instant", + "range", + "window" + ], + "type": "string" + }, + "max_data_points": { + "description": "返回的数据点数量上限。`range` 必填,`instant` 与 `window` 不接受该字段。", + "format": "int64", + "maximum": 5000, + "minimum": 2, + "type": "integer" + }, + "min_step_seconds": { + "description": "由 `max_data_points` 推导出的步长下限(秒)。可选,仅在 `range` 下接受。", + "format": "int64", + "minimum": 1, + "type": "integer" + }, + "to_ms": { + "description": "范围终点的 Unix 毫秒时间戳。所有执行类型均必填。", + "format": "int64", + "type": "integer" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "QueryExploreRequest": { + "description": "探索查询请求。四个顶层字段均为必填,未知字段会被拒绝。", + "properties": { + "args": { + "additionalProperties": { + "type": "string" + }, + "description": "宏替换参数,按变量名索引,用于 Grafana 风格变量。键最长 256 字节,值最长 64 KiB,总预算 128 KiB。", + "maxProperties": 128, + "type": "object" + }, + "datasource_id": { + "description": "数据源 ID,来自 `/monit/datasource/list`。必须是正数且不超过 JavaScript 安全整数范围,且属于当前账户。", + "format": "int64", + "maximum": 9007199254740991, + "minimum": 1, + "type": "integer" + }, + "execution": { + "$ref": "#/components/schemas/QueryExploreExecution" + }, + "expr": { + "description": "使用数据源原生语言的查询表达式(如 PromQL、LogsQL、SQL 等)。非空 UTF-8 字符串,最长 64 KiB;部分数据源类型限制更小。", + "minLength": 1, + "type": "string" + } + }, + "required": [ + "datasource_id", + "expr", + "args", + "execution" + ], + "type": "object" + }, "ExportStatusPageSubscribersRequest": { "description": "导出状态页订阅者列表所需的参数。", "properties": { @@ -42686,6 +42989,291 @@ } } }, + "/monit/prometheus/api/v1/label/{label_name}/values": { + "get": { + "description": "通过监控代理从 Prometheus 兼容数据源读取标签值列表。", + "operationId": "monit-prometheus-read-label-values", + "parameters": [ + { + "description": "要枚举取值的标签名,例如 `job`。", + "in": "path", + "name": "label_name", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "要查询的数据源 ID,必须是当前账户下 Prometheus 兼容类型的数据源。", + "in": "header", + "name": "X-DSID", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": [ + "api", + "db", + "worker" + ], + "status": "success" + }, + "schema": { + "$ref": "#/components/schemas/PrometheusLabelValuesResponse" + } + } + }, + "description": "数据源返回的原生 Prometheus 标签值响应。" + }, + "400": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "`X-DSID` 请求头缺失或非法、数据源不存在,或该数据源不是 Prometheus 类型。以 `text/plain` 返回。" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "500": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "数据源查询或代理请求失败。以 `text/plain` 返回。" + }, + "503": { + "content": { + "text/plain": { + "schema": { + "type": "string" + } + } + }, + "description": "数据源所在集群中没有支持数据源资源代理的 monit-edge。以 `text/plain` 返回,请升级 monit-edge。" + } + }, + "summary": "查询 Prometheus 标签值列表", + "tags": [ + "Monitors/告警数据源" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | 任意有效的 `app_key`(只读,不受特定权限分类限制) |\n| Edge 版本要求 | 受支持的部署要求 **monit-edge v0.35.0 或更高版本** |\n\n## 使用说明\n\n- 通过 `X-DSID` 请求头指定目标数据源,必须是当前账户下 Prometheus 兼容类型的数据源;可用 `/monit/datasource/list` 获取 ID。\n- 200 响应体是数据源原生的 Prometheus HTTP API 结构,**不是**统一的 `{ request_id, data }` envelope。未到达数据源前发生的失败以 `text/plain` 返回,并携带对应的 4xx/5xx 状态码。\n- 省略 `X-DSID` 时会回退到平台自有的 Prometheus 代理;需要查询指定数据源时必须携带该请求头。", + "href": "/zh/api-reference/monitors/data-sources/monit-prometheus-read-label-values", + "metadata": { + "sidebarTitle": "查询 Prometheus 标签值列表" + } + } + } + }, + "/monit/query/explore": { + "post": { + "description": "对已配置的数据源执行探索查询,返回 frames、samples 或 logs 形态的结果。", + "operationId": "monit-read-query-explore", + "requestBody": { + "content": { + "application/json": { + "example": { + "args": {}, + "datasource_id": 101, + "execution": { + "from_ms": 1787187600000, + "kind": "range", + "max_data_points": 1200, + "min_step_seconds": 15, + "to_ms": 1787191200000 + }, + "expr": "rate(http_requests_total[5m])" + }, + "schema": { + "$ref": "#/components/schemas/QueryExploreRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": { + "execution": { + "effective_step_seconds": 60, + "kind": "range" + }, + "format": "explore_result.v1", + "result": { + "frames": [ + { + "fields": [ + { + "name": "time", + "type": "time", + "values": [ + "2026-08-20T10:00:00Z", + "2026-08-20T10:01:00Z" + ] + }, + { + "labels": { + "job": "api" + }, + "name": "value", + "type": "float", + "values": [ + 1.25, + null + ] + } + ], + "kind": "time_series" + } + ], + "kind": "frames" + } + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "properties": { + "data": { + "$ref": "#/components/schemas/ExploreData" + } + }, + "type": "object" + } + ] + } + } + }, + "description": "成功" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:invalid_request。" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:access_denied。" + }, + "404": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:datasource_not_found。" + }, + "413": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:source_too_large、result_too_large。" + }, + "429": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:overloaded。" + }, + "499": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:canceled。" + }, + "500": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:internal。" + }, + "503": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:no_active_edge、edge_upgrade_required、mixed_edge_versions、edge_unavailable。" + }, + "504": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:timeout。" + } + }, + "summary": "执行探索查询", + "tags": [ + "Monitors/诊断分析" + ], + "x-mint": { + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **100 次/分钟**;**16 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n| Edge 版本要求 | 受支持的部署要求 **monit-edge v0.68.0 或更高版本** |\n\n## 使用说明\n\n- 需要数据源原生结果形态时使用本接口;`/monit/query/data` 返回稳定的 `query_result.v1` 契约。本接口根据 `data.result.kind`(`frames`、`samples` 或 `logs`)分发结果。\n- `execution.kind` 决定可接受的配套字段:`instant` 只需 `to_ms`,`range` 需要 `from_ms`、`to_ms` 和 `max_data_points`,`window` 需要 `from_ms` 和 `to_ms`。不接受 `step_seconds`,步长由 `max_data_points` 与 `min_step_seconds` 推导。\n- `args` 用于宏替换(例如 Grafana 风格变量),取值均为字符串。\n- `logs` 结果最多返回 1,000 条,并通过 `applied_limit` 与 `has_more` 说明截断情况。时序与采样结果各最多 1,000 条,成功响应整体上限 8 MiB。\n- WebAPI 跨实例转发与 Edge 执行合计可能耗时 35 秒,客户端超时建议至少 40 秒。", + "href": "/zh/api-reference/monitors/diagnostics/monit-read-query-explore", + "metadata": { + "sidebarTitle": "执行探索查询" + } + } + } + }, "/monit/query/data": { "post": { "description": "对已配置的数据源执行同步即席查询,并返回稳定的 `query_result.v1` 结果;结果会按自然语义呈现为 frames、records 或 samples。此公开接口要求 monit-edge v0.65.0 或更高版本。", diff --git a/roundtrip_gen_test.go b/roundtrip_gen_test.go index ec6a560..e24b66e 100644 --- a/roundtrip_gen_test.go +++ b/roundtrip_gen_test.go @@ -110,6 +110,7 @@ var exampleDataDecoders = map[string]func(json.RawMessage) error{ "POST /monit/datasource/tools/invoke": func(d json.RawMessage) error { var v DatasourceToolResult; return json.Unmarshal(d, &v) }, "POST /monit/datasource/update": func(d json.RawMessage) error { var v DataSourceItem; return json.Unmarshal(d, &v) }, "POST /monit/query/data": func(d json.RawMessage) error { var v QueryDataResponse; return json.Unmarshal(d, &v) }, + "POST /monit/query/explore": func(d json.RawMessage) error { var v ExploreData; return json.Unmarshal(d, &v) }, "POST /monit/rule/audit/detail": func(d json.RawMessage) error { var v AlertRuleAudit; return json.Unmarshal(d, &v) }, "POST /monit/rule/audits": func(d json.RawMessage) error { var v RuleAuditListResponse; return json.Unmarshal(d, &v) }, "POST /monit/rule/counter/channel": func(d json.RawMessage) error { var v RuleCounterChannelResponse; return json.Unmarshal(d, &v) },