diff --git a/data_sources.go b/data_sources.go index a97178d..d870ec0 100644 --- a/data_sources.go +++ b/data_sources.go @@ -9,7 +9,7 @@ type DataSourcesService service // Get datasource detail. // -// Retrieve full details of a single data source by its ID, including the `payload` configuration with its configured connection and authentication settings; treat the response as sensitive and avoid logging or forwarding it. +// Retrieve full details of a single data source by its ID, including the `payload` configuration with its configured connection and authentication settings; treat the response as sensitive and avoid logging or forwarding it. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. // // API: POST /monit/datasource/info (monit-datasource-read-info). func (s *DataSourcesService) ReadInfo(ctx context.Context, req *IDRequest) (*DataSourceItem, *Response, error) { @@ -23,7 +23,7 @@ func (s *DataSourcesService) ReadInfo(ctx context.Context, req *IDRequest) (*Dat // List datasources. // -// Return all data sources for the current account. Optionally filter by `type_ident`. +// Return all data sources for the current account. Optionally filter by `type_ident`. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. // // API: POST /monit/datasource/list (monit-datasource-read-list). func (s *DataSourcesService) ReadList(ctx context.Context, req *DataSourceListRequest) (*DataSourceListResponse, *Response, error) { @@ -63,9 +63,23 @@ func (s *DataSourcesService) ReadSLSProjects(ctx context.Context, req *SLSProjec return out, resp, nil } +// Invoke datasource tool. +// +// Execute one deterministic tool against a configured datasource. Requires all currently online routable Edge sessions in the cluster to support the v0.71.0 base invoke protocol; individual tools may require a newer implementation. No tool catalog, automatic replay, or fallback to Agent/legacy diagnose. Request body limit 128 KiB; complete success response limit 1 MiB; tool timeout at most 25 seconds. +// +// API: POST /monit/datasource/tools/invoke (monit-datasource-tools-invoke). +func (s *DataSourcesService) ToolsInvoke(ctx context.Context, req *DatasourceToolInvokeRequest) (*DatasourceToolResult, *Response, error) { + out := new(DatasourceToolResult) + resp, err := s.client.do(ctx, "/monit/datasource/tools/invoke", req, out) + if err != nil { + return nil, resp, err + } + return out, resp, nil +} + // Create datasource. // -// Create a new monitoring data source. The `payload` must include the type-specific configuration block. +// Create a new monitoring data source. The `payload` must include the type-specific configuration block. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. // // API: POST /monit/datasource/create (monit-datasource-write-create). func (s *DataSourcesService) WriteCreate(ctx context.Context, req *DataSourceUpsertRequest) (*DataSourceItem, *Response, error) { @@ -88,7 +102,7 @@ func (s *DataSourcesService) WriteDelete(ctx context.Context, req *IDRequest) (* // Update datasource. // -// Update an existing data source. Supply `id` plus the fields to change. +// Update an existing data source. Supply `id` plus the fields to change. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. // // API: POST /monit/datasource/update (monit-datasource-write-update). func (s *DataSourcesService) WriteUpdate(ctx context.Context, req *DataSourceUpsertRequest) (*DataSourceItem, *Response, error) { diff --git a/datasource_tools_test.go b/datasource_tools_test.go new file mode 100644 index 0000000..90accf4 --- /dev/null +++ b/datasource_tools_test.go @@ -0,0 +1,137 @@ +package flashduty + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strings" + "testing" +) + +func TestDatasourceToolsInvokePreservesJSON(t *testing.T) { + params := json.RawMessage(`{"cursor":9007199254740993,"threshold":1.000000000000000001,"nested":{"empty":[],"flag":false}}`) + evidence := `{"counter":18446744073709551615,"ratio":0.1234567890123456789,"values":[null,false,0]}` + client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost || r.URL.Path != "/monit/datasource/tools/invoke" { + t.Errorf("unexpected request: %s %s", r.Method, r.URL.Path) + } + var input DatasourceToolInvokeRequest + if err := json.NewDecoder(r.Body).Decode(&input); err != nil { + t.Error(err) + } + if input.DatasourceID != 42 || input.Tool != "mysql.overview" || string(input.Params) != string(params) { + t.Errorf("request changed: %+v", input) + } + w.Header().Set("Content-Type", "application/json") + _, _ = fmt.Fprintf(w, `{"request_id":"trace-tools","data":{"datasource_id":42,"tool":"mysql.overview","data":%s,"summary":"bounded evidence","truncated":{"reason":"row_limit"}}}`, evidence) + }) + result, resp, err := client.DataSources.ToolsInvoke(context.Background(), &DatasourceToolInvokeRequest{DatasourceID: 42, Tool: "mysql.overview", Params: params}) + if err != nil { + t.Fatal(err) + } + if resp.RequestID != "trace-tools" || result.DatasourceID != 42 || result.Tool != "mysql.overview" || string(result.Data) != evidence || result.Summary == nil || result.Truncated == nil || result.Truncated.Reason != "row_limit" { + t.Fatalf("response changed: %+v", result) + } + raw, err := json.Marshal(result) + if err != nil || !strings.Contains(string(raw), evidence) { + t.Fatalf("round trip changed evidence: %s, %v", raw, err) + } +} + +func TestDatasourceToolsInvokeHTTPErrorReason(t *testing.T) { + for _, tc := range []struct { + status int + reason string + }{{400, "tool_not_supported"}, {409, "datasource_disabled"}, {429, "overloaded"}, {503, "edge_upgrade_required"}, {504, "timeout"}} { + t.Run(tc.reason, func(t *testing.T) { + calls := 0 + client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) { + calls++ + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(tc.status) + _, _ = fmt.Fprintf(w, `{"request_id":"trace-error","error":{"code":"InvalidParameter","reason":%q,"message":"tool unavailable"}}`, tc.reason) + }) + result, _, err := client.DataSources.ToolsInvoke(context.Background(), &DatasourceToolInvokeRequest{DatasourceID: 42, Tool: "mysql.overview"}) + var apiErr *ErrorResponse + if result != nil || !errors.As(err, &apiErr) || apiErr.Reason != tc.reason || apiErr.Response.StatusCode != tc.status || apiErr.RequestID != "trace-error" || calls != 1 { + t.Fatalf("error lost or call replayed: result=%+v error=%+v calls=%d", result, err, calls) + } + if !strings.Contains(err.Error(), "reason "+tc.reason) || !strings.Contains(err.Error(), "request_id trace-error") { + t.Fatalf("CLI error text lost reason or request ID: %s", err) + } + }) + } +} + +func TestDatasourceWritePresenceAndDiagnosticSecrets(t *testing.T) { + for _, action := range []string{"create", "update"} { + for _, present := range []bool{false, true} { + t.Run(fmt.Sprintf("%s/present=%v", action, present), func(t *testing.T) { + client := newTestClient(t, func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/monit/datasource/"+action { + t.Errorf("wrong path: %s", r.URL.Path) + } + body, _ := io.ReadAll(r.Body) + var input map[string]json.RawMessage + if err := json.Unmarshal(body, &input); err != nil { + t.Fatal(err) + } + for _, key := range []string{"enabled", "alerting_enabled"} { + value, ok := input[key] + if ok != present || (present && string(value) != "false") { + t.Errorf("%s presence lost: %s", key, body) + } + } + var payload map[string]map[string]json.RawMessage + if err := json.Unmarshal(input["payload"], &payload); err != nil { + t.Fatal(err) + } + password, ok := payload["redis_node"]["password"] + if ok != present || (present && string(password) != `""`) { + t.Errorf("secret presence lost: %s", body) + } + w.Header().Set("Content-Type", "application/json") + _, _ = io.WriteString(w, `{"request_id":"write","data":{"id":42,"enabled":false,"alerting_enabled":false,"type_ident":"redis_node","payload":{"redis_node":{"database":0}}}}`) + }) + var req DataSourceUpsertRequest + raw := `{"id":42,"name":"cache","type_ident":"redis_node","edge_cluster_name":"default","address":"redis.example.com:6379","payload":{"redis_node":{"database":0}}}` + if present { + raw = `{"id":42,"name":"cache","type_ident":"redis_node","edge_cluster_name":"default","address":"redis.example.com:6379","enabled":false,"alerting_enabled":false,"payload":{"redis_node":{"database":0,"password":""}}}` + } + if err := json.Unmarshal([]byte(raw), &req); err != nil { + t.Fatal(err) + } + var result *DataSourceItem + var err error + if action == "create" { + result, _, err = client.DataSources.WriteCreate(context.Background(), &req) + } else { + result, _, err = client.DataSources.WriteUpdate(context.Background(), &req) + } + if err != nil { + t.Fatal(err) + } + encoded, _ := json.Marshal(result) + if !strings.Contains(string(encoded), `"enabled":false`) || !strings.Contains(string(encoded), `"alerting_enabled":false`) { + t.Fatalf("false response fields lost: %s", encoded) + } + }) + } + } +} + +func TestErrorResponseReasonText(t *testing.T) { + for _, tc := range []struct{ code, reason, want string }{ + {"InvalidParameter", "", "flashduty: unavailable (code InvalidParameter, http 503, request_id trace-error)"}, + {"", "", "flashduty: unavailable (http 503, request_id trace-error)"}, + {"", "edge_upgrade_required", "flashduty: unavailable (http 503, reason edge_upgrade_required, request_id trace-error)"}, + } { + err := &ErrorResponse{Response: &http.Response{StatusCode: 503}, Code: tc.code, Reason: tc.reason, Message: "unavailable", RequestID: "trace-error"} + if got := err.Error(); got != tc.want { + t.Errorf("Error() = %q, want %q", got, tc.want) + } + } +} diff --git a/diagnostics.go b/diagnostics.go index 2500069..8ee9966 100644 --- a/diagnostics.go +++ b/diagnostics.go @@ -25,6 +25,8 @@ func (s *DiagnosticsService) QueryData(ctx context.Context, req *QueryDataReques // // Run a synchronous diagnostic query (`log_patterns` for Loki/VictoriaLogs, `metric_trends` for Prometheus). Used by Flashduty AI SRE for log-pattern clustering and time-series trend analysis. Long-running — up to 35 s. // +// Deprecated: migrate to /monit/datasource/tools/invoke with prometheus.metric_trends, loki.log_patterns or victorialogs.log_patterns. Retained for existing consumers; the legacy request and response remain unchanged. +// // API: POST /monit/query/diagnose (monit-read-query-diagnose). func (s *DiagnosticsService) QueryDiagnose(ctx context.Context, req *DiagnoseRequest) (*DiagnoseResponse, *Response, error) { out := new(DiagnoseResponse) @@ -37,7 +39,7 @@ func (s *DiagnosticsService) QueryDiagnose(ctx context.Context, req *DiagnoseReq // List monitored targets. // -// List the targets observed under the current tenant by the monit-agent route projection. Supports `target_locator` prefix search and cursor pagination. Use this to drive `target_locator` selection for `/monit/tools/catalog` and `/monit/tools/invoke`. +// List the targets observed under the current tenant by the monit-agent route projection. Supports `target_locator` prefix search and cursor pagination. Use this to drive `target_locator` selection for `/monit/tools/catalog` and `/monit/tools/invoke`. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id. // // API: POST /monit/targets (monit-read-targets-list). func (s *DiagnosticsService) TargetsList(ctx context.Context, req *TargetsListRequest) (*TargetsListResponse, *Response, error) { @@ -51,7 +53,7 @@ func (s *DiagnosticsService) TargetsList(ctx context.Context, req *TargetsListRe // List target tool catalog. // -// Look up the tools that the per-target monit-agent currently exposes for a given `target_locator` (host, mysql, …). Returns each tool's name, description, and JSON-Schema `input_schema`. Pair with `/monit/tools/invoke` to drive AI-SRE tool calls. +// Look up the tools that the per-target monit-agent currently exposes for a given `target_locator` (host). Returns each tool's name, description, and JSON-Schema `input_schema`. Pair with `/monit/tools/invoke` to drive AI-SRE tool calls. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id. // // API: POST /monit/tools/catalog (monit-read-tools-catalog). func (s *DiagnosticsService) ToolsCatalog(ctx context.Context, req *ToolCatalogRequest) (*ToolCatalogResponse, *Response, error) { @@ -65,7 +67,7 @@ func (s *DiagnosticsService) ToolsCatalog(ctx context.Context, req *ToolCatalogR // Invoke target tools. // -// Invoke up to 8 monit-agent tools concurrently on a single target. Results come back in the order of the input `tools` array. Long-running — individual tools have per-tool timeouts on the agent and the whole request may take tens of seconds. +// Invoke up to 8 monit-agent tools concurrently on a single target. Results come back in the order of the input `tools` array. Long-running — individual tools have per-tool timeouts on the agent and the whole request may take tens of seconds. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id. // // API: POST /monit/tools/invoke (monit-read-tools-invoke). func (s *DiagnosticsService) ToolsInvoke(ctx context.Context, req *ToolInvokeRequest) (*ToolInvokeResponse, *Response, error) { diff --git a/errors.go b/errors.go index 7ecedd2..0b672cf 100644 --- a/errors.go +++ b/errors.go @@ -10,11 +10,19 @@ import ( // envelope's "error" field. type DutyError struct { Code string `json:"code"` + Reason string `json:"reason,omitempty"` Message string `json:"message"` } func (e *DutyError) Error() string { return fmt.Sprintf("%s: %s", e.Code, e.Message) } +func (e *DutyError) reasonOrEmpty() string { + if e == nil { + return "" + } + return e.Reason +} + func (e *DutyError) codeOr(d string) string { if e == nil { return d @@ -36,6 +44,7 @@ func (e *DutyError) errMessageOr(d string) string { type ErrorResponse struct { Response *http.Response `json:"-"` Code string `json:"code"` + Reason string `json:"reason,omitempty"` Message string `json:"message"` RequestID string `json:"request_id"` } @@ -45,10 +54,14 @@ func (e *ErrorResponse) Error() string { if e.Response != nil { status = e.Response.StatusCode } + reason := "" + if e.Reason != "" { + reason = ", reason " + e.Reason + } if e.Code != "" { - return fmt.Sprintf("flashduty: %s (code %s, http %d, request_id %s)", e.Message, e.Code, status, e.RequestID) + return fmt.Sprintf("flashduty: %s (code %s, http %d%s, request_id %s)", e.Message, e.Code, status, reason, e.RequestID) } - return fmt.Sprintf("flashduty: %s (http %d, request_id %s)", e.Message, status, e.RequestID) + return fmt.Sprintf("flashduty: %s (http %d%s, request_id %s)", e.Message, status, reason, e.RequestID) } // RateLimitError is returned when the API responds 429. It embeds the standard diff --git a/flashduty.go b/flashduty.go index 717f19f..6ca934c 100644 --- a/flashduty.go +++ b/flashduty.go @@ -241,11 +241,11 @@ func (c *Client) processResponse(httpResp *http.Response, out any) (*Response, e } if env.Error != nil && isFailureCode(env.Error.Code) { - apiErr := &ErrorResponse{Response: httpResp, Code: env.Error.Code, Message: env.Error.Message, RequestID: resp.RequestID} + apiErr := &ErrorResponse{Response: httpResp, Code: env.Error.Code, Reason: env.Error.Reason, Message: env.Error.Message, RequestID: resp.RequestID} return resp, asAPIError(apiErr, resp.RateLimit) } if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 { - apiErr := &ErrorResponse{Response: httpResp, Code: env.Error.codeOr(""), Message: env.Error.errMessageOr(string(raw)), RequestID: resp.RequestID} + apiErr := &ErrorResponse{Response: httpResp, Code: env.Error.codeOr(""), Reason: env.Error.reasonOrEmpty(), Message: env.Error.errMessageOr(string(raw)), RequestID: resp.RequestID} return resp, asAPIError(apiErr, resp.RateLimit) } diff --git a/internal/cmd/gen/main.go b/internal/cmd/gen/main.go index 7265260..6f5e699 100644 --- a/internal/cmd/gen/main.go +++ b/internal/cmd/gen/main.go @@ -648,6 +648,9 @@ func (g *Gen) emitModels() string { structs.WriteString(g.emitStruct(n, schema)) } + if strings.Contains(structs.String(), "json.RawMessage") { + b.WriteString("import \"encoding/json\"\n\n") + } b.WriteString(enumsAndAliases.String()) b.WriteString(structs.String()) b.WriteString(g.emitGetRequests()) @@ -814,13 +817,14 @@ func (g *Gen) emitStruct(name string, s map[string]any) string { preserveAbsence, _ := pv["x-flashduty-preserve-absence"].(bool) isOptionalResponseField := isOptionalUnionField || (!inReq && preserveAbsence) needsPointer = needsPointer || (isOptionalResponseField && (pointerizableScalar(gt) || isStructField || strings.HasPrefix(gt, "[]") || strings.HasPrefix(gt, "map["))) - // A request object marked x-flashduty-preserve-absence branches + // A request field marked x-flashduty-preserve-absence branches // server-side on the key's presence (e.g. /rum/application/update // leaves an omitted alerting/links container untouched but replaces // the stored config when the object is present). A bare struct with // `,omitzero` cannot put an all-zero object on the wire, so emit a // pointer: nil stays absent, a non-nil pointer always serializes. - needsPointer = needsPointer || (inReq && !required[k] && preserveAbsence && isStructField) + // Scalars use the same rule so false and empty secrets stay explicit. + needsPointer = needsPointer || (inReq && !required[k] && preserveAbsence && (isStructField || pointerizableScalar(gt))) if needsPointer { gt = "*" + gt } @@ -881,6 +885,10 @@ func (g *Gen) emitStruct(name string, s map[string]any) string { // goTypeOf resolves a schema map to a Go type string, synthesizing nested // struct types (queued for emission) as needed. func (g *Gen) goTypeOf(s map[string]any, hint string) string { + // Preserve arbitrary tool JSON, including integer and decimal precision. + if raw, _ := s["x-flashduty-raw-json"].(bool); raw { + return "json.RawMessage" + } if s == nil { return "any" } diff --git a/models_gen.go b/models_gen.go index a5f9368..46c269b 100644 --- a/models_gen.go +++ b/models_gen.go @@ -2,6 +2,8 @@ package flashduty +import "encoding/json" + // AlertFeedType Alert activity feed entry type. Each value identifies one alert lifecycle event; the matching `detail` payload shape is determined by this field. type AlertFeedType string @@ -2389,6 +2391,34 @@ type DsElasticSearchConfig struct { Username string `json:"username,omitempty" toon:"username,omitempty"` } +// DsKafkaConfig is generated from the Flashduty OpenAPI schema. +type DsKafkaConfig struct { + // Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses. + Password *string `json:"password,omitempty" toon:"password,omitempty"` + // SASL mechanism: none (default, no credentials), plain, scram-sha-256, scram-sha-512 (require username and password). + SaslMechanism string `json:"sasl_mechanism,omitempty" toon:"sasl_mechanism,omitempty"` + // Connection timeout in milliseconds; defaults to 5000 when omitted. + TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` + // PEM CA certificates or an ${env:NAME} reference. + TlsCa string `json:"tls_ca,omitempty" toon:"tls_ca,omitempty"` + // PEM client certificate or ${env:NAME}; configure both tls_cert and tls_key. + TlsCert string `json:"tls_cert,omitempty" toon:"tls_cert,omitempty"` + // Whether TLS is enabled; defaults to false. + TlsEnabled bool `json:"tls_enabled,omitempty" toon:"tls_enabled,omitempty"` + // PEM client private key or ${env:NAME}; configure both tls_cert and tls_key. Omit on update to preserve; an empty string clears it. Literal keys are omitted from responses. + TlsKey *string `json:"tls_key,omitempty" toon:"tls_key,omitempty"` + // Maximum TLS version: 1.2 or 1.3; empty means no constraint. Must not be below the minimum. + TlsMaxVersion string `json:"tls_max_version,omitempty" toon:"tls_max_version,omitempty"` + // Minimum TLS version: 1.2 (default) or 1.3. + TlsMinVersion string `json:"tls_min_version,omitempty" toon:"tls_min_version,omitempty"` + // Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty. + TlsServerName string `json:"tls_server_name,omitempty" toon:"tls_server_name,omitempty"` + // Skip server certificate verification when TLS is enabled. + TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` + // Authentication username; an ${env:NAME} reference is supported. + Username string `json:"username,omitempty" toon:"username,omitempty"` +} + // DsLokiConfig is generated from the Flashduty OpenAPI schema. type DsLokiConfig struct { // Whether HTTP Basic Auth is enabled; when `false`, `basic_auth_username`/`basic_auth_password` are ignored. @@ -2417,6 +2447,30 @@ type DsLokiConfig struct { TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` } +// DsMongoDBConfig is generated from the Flashduty OpenAPI schema. +type DsMongoDBConfig struct { + // Authentication database; defaults to admin. Username and password must be configured together. Client certificates are unsupported. + AuthSource string `json:"auth_source,omitempty" toon:"auth_source,omitempty"` + // Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses. + Password *string `json:"password,omitempty" toon:"password,omitempty"` + // Connection timeout in milliseconds; defaults to 3000 when omitted. + TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` + // PEM CA certificates or an ${env:NAME} reference. + TlsCa string `json:"tls_ca,omitempty" toon:"tls_ca,omitempty"` + // Whether TLS is enabled; defaults to false. + TlsEnabled bool `json:"tls_enabled,omitempty" toon:"tls_enabled,omitempty"` + // Maximum TLS version: 1.2 or 1.3; empty means no constraint. Must not be below the minimum. + TlsMaxVersion string `json:"tls_max_version,omitempty" toon:"tls_max_version,omitempty"` + // Minimum TLS version: 1.2 (default) or 1.3. + TlsMinVersion string `json:"tls_min_version,omitempty" toon:"tls_min_version,omitempty"` + // Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty. + TlsServerName string `json:"tls_server_name,omitempty" toon:"tls_server_name,omitempty"` + // Skip server certificate verification when TLS is enabled. + TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` + // Authentication username; an ${env:NAME} reference is supported. + Username string `json:"username,omitempty" toon:"username,omitempty"` +} + // DsMySqlConfig is generated from the Flashduty OpenAPI schema. type DsMySqlConfig struct { // Maximum idle connections. @@ -2469,14 +2523,19 @@ type DsOracleConfig struct { // DsPayload is generated from the Flashduty OpenAPI schema. type DsPayload struct { - Clickhouse DsClickHouseConfig `json:"clickhouse,omitzero" toon:"clickhouse,omitempty"` - Elasticsearch DsElasticSearchConfig `json:"elasticsearch,omitzero" toon:"elasticsearch,omitempty"` - Loki DsLokiConfig `json:"loki,omitzero" toon:"loki,omitempty"` - Mysql DsMySqlConfig `json:"mysql,omitzero" toon:"mysql,omitempty"` - Oracle DsOracleConfig `json:"oracle,omitzero" toon:"oracle,omitempty"` - Postgres DsPostgresConfig `json:"postgres,omitzero" toon:"postgres,omitempty"` - Prometheus DsPrometheusConfig `json:"prometheus,omitzero" toon:"prometheus,omitempty"` - SLS DsslsConfig `json:"sls,omitzero" toon:"sls,omitempty"` + Clickhouse DsClickHouseConfig `json:"clickhouse,omitzero" toon:"clickhouse,omitempty"` + Elasticsearch DsElasticSearchConfig `json:"elasticsearch,omitzero" toon:"elasticsearch,omitempty"` + Kafka *DsKafkaConfig `json:"kafka,omitempty" toon:"kafka,omitempty"` + Loki DsLokiConfig `json:"loki,omitzero" toon:"loki,omitempty"` + MongodbMongod *DsMongoDBConfig `json:"mongodb_mongod,omitempty" toon:"mongodb_mongod,omitempty"` + MongodbMongos *DsMongoDBConfig `json:"mongodb_mongos,omitempty" toon:"mongodb_mongos,omitempty"` + Mysql DsMySqlConfig `json:"mysql,omitzero" toon:"mysql,omitempty"` + Oracle DsOracleConfig `json:"oracle,omitzero" toon:"oracle,omitempty"` + Postgres DsPostgresConfig `json:"postgres,omitzero" toon:"postgres,omitempty"` + Prometheus DsPrometheusConfig `json:"prometheus,omitzero" toon:"prometheus,omitempty"` + RedisNode *DsRedisNodeConfig `json:"redis_node,omitempty" toon:"redis_node,omitempty"` + RedisSentinel *DsRedisSentinelConfig `json:"redis_sentinel,omitempty" toon:"redis_sentinel,omitempty"` + SLS DsslsConfig `json:"sls,omitzero" toon:"sls,omitempty"` // Tencent CLS credentials. Required when `type_ident` is `tencent_cls`. TencentCls DsTencentClsConfig `json:"tencent_cls,omitzero" toon:"tencent_cls,omitempty"` Victorialogs DsVictoriaLogsConfig `json:"victorialogs,omitzero" toon:"victorialogs,omitempty"` @@ -2534,6 +2593,28 @@ type DsPrometheusConfig struct { TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` } +// DsRedisNodeConfig is generated from the Flashduty OpenAPI schema. +type DsRedisNodeConfig struct { + // Redis database number; defaults to 0. + Database int64 `json:"database,omitempty" toon:"database,omitempty"` + // Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses. + Password *string `json:"password,omitempty" toon:"password,omitempty"` + // Connection timeout in milliseconds; defaults to 3000 when omitted. + TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` + // Authentication username; an ${env:NAME} reference is supported. + Username string `json:"username,omitempty" toon:"username,omitempty"` +} + +// DsRedisSentinelConfig is generated from the Flashduty OpenAPI schema. +type DsRedisSentinelConfig struct { + // Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses. + Password *string `json:"password,omitempty" toon:"password,omitempty"` + // Connection timeout in milliseconds; defaults to 3000 when omitted. + TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` + // Authentication username; an ${env:NAME} reference is supported. + Username string `json:"username,omitempty" toon:"username,omitempty"` +} + // DsslsConfig is generated from the Flashduty OpenAPI schema. type DsslsConfig struct { // Alibaba Cloud Access Key ID. @@ -2598,11 +2679,13 @@ type DsVictoriaLogsConfig struct { type DataSourceItem struct { // Account ID. AccountID uint64 `json:"account_id" toon:"account_id"` - // Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. + // Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. Address string `json:"address" toon:"address"` + // Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools. + AlertingEnabled bool `json:"alerting_enabled" toon:"alerting_enabled"` // Monitors edge cluster name responsible for evaluating rules using this datasource. EdgeClusterName string `json:"edge_cluster_name" toon:"edge_cluster_name"` - // Whether the datasource is active. + // Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled. Enabled bool `json:"enabled" toon:"enabled"` // Unique datasource ID. ID uint64 `json:"id" toon:"id"` @@ -2610,9 +2693,9 @@ type DataSourceItem struct { Name string `json:"name" toon:"name"` // Optional description. Note string `json:"note" toon:"note"` - // Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. + // Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior. Payload any `json:"payload" toon:"payload"` - // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`. + // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 TypeIdent string `json:"type_ident" toon:"type_ident"` // Last update timestamp, Unix epoch seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -2620,30 +2703,63 @@ type DataSourceItem struct { // DataSourceListRequest is generated from the Flashduty OpenAPI schema. type DataSourceListRequest struct { - // Filter by datasource type identifier. Omit to return all types. Allowed values: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`. + // Datasource type identifier. Omit to return all types. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 Type string `json:"type,omitempty" toon:"type,omitempty"` } // DataSourceUpsertRequest is generated from the Flashduty OpenAPI schema. type DataSourceUpsertRequest struct { - // Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). + // Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. Address string `json:"address,omitempty" toon:"address,omitempty"` + // Whether this datasource may evaluate alerts. Omitted on create: true for alerting types, false for diagnostic-only types; omitted on update: preserve current value. null is invalid. redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka reject true. Disabling is rejected with conflict when enabled rules reference the datasource. + AlertingEnabled *bool `json:"alerting_enabled,omitempty" toon:"alerting_enabled,omitempty"` // Monitors edge cluster name responsible for evaluating rules using this datasource. EdgeClusterName string `json:"edge_cluster_name" toon:"edge_cluster_name"` - // Whether the datasource is enabled for rule evaluation. When omitted on create, the datasource is created disabled (`false`). - Enabled bool `json:"enabled,omitempty" toon:"enabled,omitempty"` + // Whether business execution is enabled. Omitted on create: true; omitted on update: preserve the current value. Explicit false disables execution; null is invalid. Does not change alerting_enabled. + Enabled *bool `json:"enabled,omitempty" toon:"enabled,omitempty"` // Datasource ID. Required for update; omit for create. ID uint64 `json:"id,omitempty" toon:"id,omitempty"` // Datasource display name. This is the name referenced as `ds_name` in query and diagnose APIs. Name string `json:"name" toon:"name"` // Optional description. Note string `json:"note,omitempty" toon:"note,omitempty"` - // Type-specific configuration block. Must include the key matching `type_ident`. + // Type-specific configuration block. Must include the key matching `type_ident`. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior. Payload DsPayload `json:"payload" toon:"payload"` - // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`. + // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 TypeIdent string `json:"type_ident" toon:"type_ident"` } +// DatasourceToolInvokeRequest is generated from the Flashduty OpenAPI schema. +type DatasourceToolInvokeRequest struct { + // Optional consistency check; must equal the authenticated account. + AccountID uint64 `json:"account_id,omitempty" toon:"account_id,omitempty"` + // Datasource ID from /monit/datasource/list. + DatasourceID uint64 `json:"datasource_id" toon:"datasource_id"` + // Tool-specific JSON parameters; omitted means {}. Explicit null is invalid. + Params json.RawMessage `json:"params,omitempty" toon:"params,omitempty"` + // Single tool name prefixed by the datasource type, e.g. mysql.overview. Free SQL uses /monit/query/data; mysql.query and postgres.query are unsupported. + Tool string `json:"tool" toon:"tool"` +} + +// DatasourceToolResult is generated from the Flashduty OpenAPI schema. +type DatasourceToolResult struct { + // Tool-specific JSON evidence, preserved without conversion; never null. No nested legacy diagnose envelope. + Data json.RawMessage `json:"data" toon:"data"` + // Datasource ID from /monit/datasource/list. + DatasourceID uint64 `json:"datasource_id" toon:"datasource_id"` + // Optional non-empty summary. + Summary *string `json:"summary,omitempty" toon:"summary,omitempty"` + // Executed tool name matching the request. + Tool string `json:"tool" toon:"tool"` + Truncated *DatasourceToolTruncation `json:"truncated,omitempty" toon:"truncated,omitempty"` +} + +// DatasourceToolTruncation is generated from the Flashduty OpenAPI schema. +type DatasourceToolTruncation struct { + // Why the result was truncated. Presence of this object indicates truncation. + Reason string `json:"reason" toon:"reason"` +} + // DeleteFieldRequest is generated from the Flashduty OpenAPI schema. type DeleteFieldRequest struct { // Field ID — 24-character hex ObjectID. @@ -10644,9 +10760,9 @@ type TimeFilter struct { type ToolCatalogRequest struct { // Optional consistency check. Must equal the authenticated account when supplied. AccountID int64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // Optional target kind. When omitted, webapi infers it from current target routing. If the call returns `ambiguous_target_kind`, retry with a value from `target_kinds`. + // Optional target kind; only host is supported. Inferred when omitted. TargetKind string `json:"target_kind,omitempty" toon:"target_kind,omitempty"` - // Target identifier (host name, MySQL address, …). Max 256 bytes; no whitespace, control characters, or `|`. + // Host name. Max 256 bytes; no whitespace, control characters or |. TargetLocator string `json:"target_locator" toon:"target_locator"` } @@ -10664,9 +10780,9 @@ type ToolCatalogResponse struct { type ToolInvokeRequest struct { // Optional consistency check. Must equal the authenticated account when supplied. AccountID int64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // Optional target kind; auto-inferred when omitted. + // Optional target kind; only host is supported. Inferred when omitted. TargetKind string `json:"target_kind,omitempty" toon:"target_kind,omitempty"` - // Target identifier. Same validation rules as `/monit/tools/catalog`. + // Host name. Max 256 bytes; no whitespace, control characters or |. TargetLocator string `json:"target_locator" toon:"target_locator"` // Up to 8 tool calls; webapi executes them concurrently and returns results in input order. Tools []ToolInvokeRequestToolsItem `json:"tools" toon:"tools"` @@ -11848,7 +11964,7 @@ type TargetsListResponseItemsItem struct { HostID string `json:"host_id" toon:"host_id"` // ServiceMap capability and latest status of the target's host. Omitted when the reporting agent has no ServiceMap capability. Servicemap TargetInventoryServiceMapCapability `json:"servicemap" toon:"servicemap"` - // Target kind, e.g. `host`, `mysql`. Filtering by kind is not supported in v1. + // Host target kind. Filtering by kind is not supported in v1. TargetKind string `json:"target_kind" toon:"target_kind"` // Target identifier; the list is sorted by this field ascending. TargetLocator string `json:"target_locator" toon:"target_locator"` @@ -11868,7 +11984,7 @@ type ToolCatalogResponseError struct { // ToolCatalogResponseTarget is generated from the Flashduty OpenAPI schema. type ToolCatalogResponseTarget struct { - // Resolved target kind, e.g. `host` or `mysql`; matches the `target_kind` inferred from or given in the request. + // Resolved host target kind. Kind string `json:"kind" toon:"kind"` // Echo of the target locator from the request. Locator string `json:"locator" toon:"locator"` @@ -11924,7 +12040,7 @@ type ToolInvokeResponseResultsItem struct { // ToolInvokeResponseTarget is generated from the Flashduty OpenAPI schema. type ToolInvokeResponseTarget struct { - // Resolved target kind, e.g. `host` or `mysql`; matches the `target_kind` inferred from or given in the request. + // Resolved host target kind. Kind string `json:"kind" toon:"kind"` // Echo of the target locator from the request. Locator string `json:"locator" toon:"locator"` diff --git a/openapi/openapi.en.json b/openapi/openapi.en.json index 1a90df8..45d0078 100644 --- a/openapi/openapi.en.json +++ b/openapi/openapi.en.json @@ -14714,12 +14714,12 @@ "post": { "operationId": "monit-datasource-read-list", "summary": "List datasources", - "description": "Return all data sources for the current account. Optionally filter by `type_ident`.", + "description": "Return all data sources for the current account. Optionally filter by `type_ident`. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent.", "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 | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Omit `type_ident` to return all types.\n- Sensitive credential fields (passwords, keys) are not returned in the list response.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\n## Usage\n\n- Omit `type_ident` to return all types.\n- Sensitive credential fields (passwords, keys) are not returned in the list response.\n\nSee the request/response schemas for all supported types and credential handling. Diagnostic-only types cannot enable alerting. On create omitted enabled defaults to true; on update omission preserves the current value. Explicit null for enabled or alerting_enabled is invalid. Diagnostic passwords and Kafka private keys are omitted from responses unless they are environment references; omit these secrets on update to preserve them, or send an empty string to clear. Other datasource credentials may be returned and must be handled as sensitive.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-list", "metadata": { "sidebarTitle": "List datasources" @@ -14758,7 +14758,8 @@ "address": "http://prometheus.example.com:9090", "edge_cluster_name": "default", "updated_at": 1712000000, - "payload": null + "payload": null, + "alerting_enabled": true } ] } @@ -14797,12 +14798,12 @@ "post": { "operationId": "monit-datasource-read-info", "summary": "Get datasource detail", - "description": "Retrieve full details of a single data source by its ID, including the `payload` configuration with its configured connection and authentication settings; treat the response as sensitive and avoid logging or forwarding it.", + "description": "Retrieve full details of a single data source by its ID, including the `payload` configuration with its configured connection and authentication settings; treat the response as sensitive and avoid logging or forwarding it. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent.", "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 | **Datasources Read** (`monit`) |\n\n## Credential fields\n\nThe `info` / `create` / `update` responses include the `payload` configuration exactly as stored — `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and similar fields are returned as-is, not masked. The one exception is `payload.tencent_cls.secret_key`, which is always masked to an empty string (an `${env:...}` reference is returned verbatim). Treat these responses as sensitive: avoid logging them or forwarding them to third parties.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Read** (`monit`) |\n\nSee the request/response schemas for all supported types and credential handling. Diagnostic-only types cannot enable alerting. On create omitted enabled defaults to true; on update omission preserves the current value. Explicit null for enabled or alerting_enabled is invalid. Diagnostic passwords and Kafka private keys are omitted from responses unless they are environment references; omit these secrets on update to preserve them, or send an empty string to clear. Other datasource credentials may be returned and must be handled as sensitive.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-read-info", "metadata": { "sidebarTitle": "Get datasource detail" @@ -14847,7 +14848,8 @@ } }, "edge_cluster_name": "default", - "updated_at": 1712000000 + "updated_at": 1712000000, + "alerting_enabled": true } } } @@ -14885,12 +14887,12 @@ "post": { "operationId": "monit-datasource-write-create", "summary": "Create datasource", - "description": "Create a new monitoring data source. The `payload` must include the type-specific configuration block.", + "description": "Create a new monitoring data source. The `payload` must include the type-specific configuration block. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent.", "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 | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`.\n- `edge_cluster_name` specifies which Monitors edge cluster evaluates rules using this datasource.\n- For `elasticsearch`, set `payload.elasticsearch.deployment` to `cloud` or `self-managed`.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.\n\n## Credential fields\n\nThe `info` / `create` / `update` responses include the `payload` configuration exactly as stored — `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and similar fields are returned as-is, not masked. The one exception is `payload.tencent_cls.secret_key`, which is always masked to an empty string (an `${env:...}` reference is returned verbatim). Treat these responses as sensitive: avoid logging them or forwarding them to third parties.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- `type_ident` must be one of: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`.\n- `edge_cluster_name` specifies which Monitors edge cluster evaluates rules using this datasource.\n- For `elasticsearch`, set `payload.elasticsearch.deployment` to `cloud` or `self-managed`.\n- Every call is recorded in the account audit log. Use credential fields only for connection credentials.\n\nSee the request/response schemas for all supported types and credential handling. Diagnostic-only types cannot enable alerting. On create omitted enabled defaults to true; on update omission preserves the current value. Explicit null for enabled or alerting_enabled is invalid. Diagnostic passwords and Kafka private keys are omitted from responses unless they are environment references; omit these secrets on update to preserve them, or send an empty string to clear. Other datasource credentials may be returned and must be handled as sensitive.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-create", "metadata": { "sidebarTitle": "Create datasource" @@ -14924,7 +14926,8 @@ "name": "Prometheus Prod", "enabled": true, "edge_cluster_name": "default", - "updated_at": 1712000000 + "updated_at": 1712000000, + "alerting_enabled": true } } } @@ -14971,12 +14974,12 @@ "post": { "operationId": "monit-datasource-write-update", "summary": "Update datasource", - "description": "Update an existing data source. Supply `id` plus the fields to change.", + "description": "Update an existing data source. Supply `id` plus the fields to change. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent.", "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 | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Every call is recorded in the account audit log. Don't put secrets in request fields.\n\n## Credential fields\n\nThe `info` / `create` / `update` responses include the `payload` configuration exactly as stored — `password`, `basic_auth_password`, `api_key`, `service_token`, `access_key_secret`, `tls_key`, `tls_key_pwd` and similar fields are returned as-is, not masked. The one exception is `payload.tencent_cls.secret_key`, which is always masked to an empty string (an `${env:...}` reference is returned verbatim). Treat these responses as sensitive: avoid logging them or forwarding them to third parties.", + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Datasources Manage** (`monit`) |\n\n## Usage\n\n- Every call is recorded in the account audit log. Use credential fields only for connection credentials.\n\nSee the request/response schemas for all supported types and credential handling. Diagnostic-only types cannot enable alerting. On create omitted enabled defaults to true; on update omission preserves the current value. Explicit null for enabled or alerting_enabled is invalid. Diagnostic passwords and Kafka private keys are omitted from responses unless they are environment references; omit these secrets on update to preserve them, or send an empty string to clear. Other datasource credentials may be returned and must be handled as sensitive.", "href": "/en/api-reference/monitors/data-sources/monit-datasource-write-update", "metadata": { "sidebarTitle": "Update datasource" @@ -15010,7 +15013,8 @@ "name": "Prometheus Prod v2", "enabled": true, "edge_cluster_name": "default", - "updated_at": 1712100000 + "updated_at": 1712100000, + "alerting_enabled": true } } } @@ -20103,7 +20107,7 @@ "post": { "operationId": "monit-read-query-diagnose", "summary": "Diagnose data source", - "description": "Run a synchronous diagnostic query (`log_patterns` for Loki/VictoriaLogs, `metric_trends` for Prometheus). Used by Flashduty AI SRE for log-pattern clustering and time-series trend analysis. Long-running — up to 35 s.", + "description": "Run a synchronous diagnostic query (`log_patterns` for Loki/VictoriaLogs, `metric_trends` for Prometheus). Used by Flashduty AI SRE for log-pattern clustering and time-series trend analysis. Long-running — up to 35 s.\n\nDeprecated: migrate to /monit/datasource/tools/invoke with prometheus.metric_trends, loki.log_patterns or victorialogs.log_patterns. Retained for existing consumers; the legacy request and response remain unchanged.", "tags": [ "Monitors/Diagnostics" ], @@ -20277,14 +20281,15 @@ "500": { "$ref": "#/components/responses/ServerError" } - } + }, + "deprecated": true } }, "/monit/tools/catalog": { "post": { "operationId": "monit-read-tools-catalog", "summary": "List target tool catalog", - "description": "Look up the tools that the per-target monit-agent currently exposes for a given `target_locator` (host, mysql, …). Returns each tool's name, description, and JSON-Schema `input_schema`. Pair with `/monit/tools/invoke` to drive AI-SRE tool calls.", + "description": "Look up the tools that the per-target monit-agent currently exposes for a given `target_locator` (host). Returns each tool's name, description, and JSON-Schema `input_schema`. Pair with `/monit/tools/invoke` to drive AI-SRE tool calls. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id.", "tags": [ "Monitors/Diagnostics" ], @@ -20393,7 +20398,7 @@ "post": { "operationId": "monit-read-tools-invoke", "summary": "Invoke target tools", - "description": "Invoke up to 8 monit-agent tools concurrently on a single target. Results come back in the order of the input `tools` array. Long-running — individual tools have per-tool timeouts on the agent and the whole request may take tens of seconds.", + "description": "Invoke up to 8 monit-agent tools concurrently on a single target. Results come back in the order of the input `tools` array. Long-running — individual tools have per-tool timeouts on the agent and the whole request may take tens of seconds. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id.", "tags": [ "Monitors/Diagnostics" ], @@ -20520,7 +20525,7 @@ "post": { "operationId": "monit-read-targets-list", "summary": "List monitored targets", - "description": "List the targets observed under the current tenant by the monit-agent route projection. Supports `target_locator` prefix search and cursor pagination. Use this to drive `target_locator` selection for `/monit/tools/catalog` and `/monit/tools/invoke`.", + "description": "List the targets observed under the current tenant by the monit-agent route projection. Supports `target_locator` prefix search and cursor pagination. Use this to drive `target_locator` selection for `/monit/tools/catalog` and `/monit/tools/invoke`. Agent targets are host-only. Remote datasource evidence uses /monit/datasource/tools/invoke and datasource_id.", "tags": [ "Monitors/Diagnostics" ], @@ -31773,6 +31778,176 @@ } } } + }, + "/monit/datasource/tools/invoke": { + "post": { + "description": "Execute one deterministic tool against a configured datasource. Requires all currently online routable Edge sessions in the cluster to support the v0.71.0 base invoke protocol; individual tools may require a newer implementation. No tool catalog, automatic replay, or fallback to Agent/legacy diagnose. Request body limit 128 KiB; complete success response limit 1 MiB; tool timeout at most 25 seconds.", + "operationId": "monit-datasource-tools-invoke", + "requestBody": { + "content": { + "application/json": { + "example": { + "datasource_id": 10, + "params": {}, + "tool": "mysql.overview" + }, + "schema": { + "$ref": "#/components/schemas/DatasourceToolInvokeRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": { + "data": { + "version": "8.0.36" + }, + "datasource_id": 10, + "summary": "MySQL overview", + "tool": "mysql.overview" + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "properties": { + "data": { + "$ref": "#/components/schemas/DatasourceToolResult" + } + }, + "type": "object" + } + ] + } + } + }, + "description": "Success" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: invalid_request, tool_not_supported, datasource_error." + }, + "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." + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: datasource_disabled, datasource_in_use." + }, + "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." + }, + "504": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "Standard HTTP error; error.reason: timeout." + } + }, + "summary": "Invoke datasource tool", + "tags": [ + "Monitors/Data sources" + ], + "x-mint": { + "content": "Use datasource IDs from `/monit/datasource/list`. Disabled datasources return `datasource_disabled`; `alerting_enabled=false` does not block tools. Errors use non-2xx HTTP status and `error.code`, `error.message`, `error.reason`. `tool_not_supported` indicates the selected executor does not provide this tool; it is not a vendor permission error. Never retry through another Edge or the legacy diagnose endpoint automatically.", + "href": "/en/api-reference/monitors/data-sources/monit-datasource-tools-invoke", + "metadata": { + "sidebarTitle": "Invoke datasource tool" + } + } + } } }, "components": { @@ -32067,6 +32242,11 @@ "type": "string", "description": "Human-readable error message, localized by the caller's Accept-Language. May contain field names, IDs, or other context from the failing request.", "example": "The specified parameter template_id is not valid." + }, + "reason": { + "description": "Optional machine-readable rejection reason, including datasource tool failures. Inspect alongside HTTP status and code.", + "type": "string", + "x-flashduty-preserve-absence": true } }, "required": [ @@ -45471,7 +45651,7 @@ "properties": { "type": { "type": "string", - "description": "Filter by datasource type identifier. Omit to return all types. Allowed values: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`." + "description": "Datasource type identifier. Omit to return all types. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" } } }, @@ -45509,6 +45689,26 @@ "tencent_cls": { "$ref": "#/components/schemas/DSTencentCLSConfig", "description": "Tencent CLS credentials. Required when `type_ident` is `tencent_cls`." + }, + "kafka": { + "$ref": "#/components/schemas/DSKafkaConfig", + "x-flashduty-preserve-absence": true + }, + "mongodb_mongod": { + "$ref": "#/components/schemas/DSMongoDBConfig", + "x-flashduty-preserve-absence": true + }, + "mongodb_mongos": { + "$ref": "#/components/schemas/DSMongoDBConfig", + "x-flashduty-preserve-absence": true + }, + "redis_node": { + "$ref": "#/components/schemas/DSRedisNodeConfig", + "x-flashduty-preserve-absence": true + }, + "redis_sentinel": { + "$ref": "#/components/schemas/DSRedisSentinelConfig", + "x-flashduty-preserve-absence": true } } }, @@ -46020,7 +46220,8 @@ "address", "edge_cluster_name", "updated_at", - "payload" + "payload", + "alerting_enabled" ], "properties": { "id": { @@ -46035,7 +46236,7 @@ }, "type_ident": { "type": "string", - "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`." + "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" }, "name": { "type": "string", @@ -46043,7 +46244,7 @@ }, "enabled": { "type": "boolean", - "description": "Whether the datasource is active." + "description": "Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled." }, "note": { "type": "string", @@ -46051,7 +46252,8 @@ }, "address": { "type": "string", - "description": "Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix." + "description": "Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization.", + "maxLength": 4096 }, "payload": { "anyOf": [ @@ -46062,7 +46264,7 @@ "type": "null" } ], - "description": "Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference." + "description": "Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior." }, "edge_cluster_name": { "type": "string", @@ -46072,6 +46274,10 @@ "type": "integer", "format": "int64", "description": "Last update timestamp, Unix epoch seconds." + }, + "alerting_enabled": { + "description": "Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools.", + "type": "boolean" } } }, @@ -46092,7 +46298,7 @@ }, "type_ident": { "type": "string", - "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`." + "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" }, "name": { "type": "string", @@ -46104,11 +46310,12 @@ }, "address": { "type": "string", - "description": "Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0)." + "description": "Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization.", + "maxLength": 4096 }, "payload": { "$ref": "#/components/schemas/DSPayload", - "description": "Type-specific configuration block. Must include the key matching `type_ident`." + "description": "Type-specific configuration block. Must include the key matching `type_ident`. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior." }, "edge_cluster_name": { "type": "string", @@ -46116,7 +46323,13 @@ }, "enabled": { "type": "boolean", - "description": "Whether the datasource is enabled for rule evaluation. When omitted on create, the datasource is created disabled (`false`)." + "description": "Whether business execution is enabled. Omitted on create: true; omitted on update: preserve the current value. Explicit false disables execution; null is invalid. Does not change alerting_enabled.", + "x-flashduty-preserve-absence": true + }, + "alerting_enabled": { + "description": "Whether this datasource may evaluate alerts. Omitted on create: true for alerting types, false for diagnostic-only types; omitted on update: preserve current value. null is invalid. redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka reject true. Disabling is rejected with conflict when enabled rules reference the datasource.", + "type": "boolean", + "x-flashduty-preserve-absence": true } } }, @@ -50121,11 +50334,14 @@ }, "target_locator": { "type": "string", - "description": "Target identifier (host name, MySQL address, …). Max 256 bytes; no whitespace, control characters, or `|`." + "description": "Host name. Max 256 bytes; no whitespace, control characters or |." }, "target_kind": { "type": "string", - "description": "Optional target kind. When omitted, webapi infers it from current target routing. If the call returns `ambiguous_target_kind`, retry with a value from `target_kinds`." + "description": "Optional target kind; only host is supported. Inferred when omitted.", + "enum": [ + "host" + ] } } }, @@ -50138,7 +50354,7 @@ "properties": { "kind": { "type": "string", - "description": "Resolved target kind, e.g. `host` or `mysql`; matches the `target_kind` inferred from or given in the request." + "description": "Resolved host target kind." }, "locator": { "type": "string", @@ -50218,11 +50434,14 @@ }, "target_locator": { "type": "string", - "description": "Target identifier. Same validation rules as `/monit/tools/catalog`." + "description": "Host name. Max 256 bytes; no whitespace, control characters or |." }, "target_kind": { "type": "string", - "description": "Optional target kind; auto-inferred when omitted." + "description": "Optional target kind; only host is supported. Inferred when omitted.", + "enum": [ + "host" + ] }, "tools": { "type": "array", @@ -50258,7 +50477,7 @@ "properties": { "kind": { "type": "string", - "description": "Resolved target kind, e.g. `host` or `mysql`; matches the `target_kind` inferred from or given in the request." + "description": "Resolved host target kind." }, "locator": { "type": "string", @@ -50389,7 +50608,7 @@ "properties": { "target_kind": { "type": "string", - "description": "Target kind, e.g. `host`, `mysql`. Filtering by kind is not supported in v1." + "description": "Host target kind. Filtering by kind is not supported in v1." }, "target_locator": { "type": "string", @@ -61997,6 +62216,255 @@ "size", "content_type" ] + }, + "DSKafkaConfig": { + "description": "Diagnostic datasource connection configuration.", + "properties": { + "password": { + "description": "Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "sasl_mechanism": { + "default": "none", + "description": "SASL mechanism: none (default, no credentials), plain, scram-sha-256, scram-sha-512 (require username and password).", + "enum": [ + "none", + "plain", + "scram-sha-256", + "scram-sha-512" + ], + "type": "string" + }, + "timeout_ms": { + "default": 5000, + "description": "Connection timeout in milliseconds; defaults to 5000 when omitted.", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "tls_ca": { + "description": "PEM CA certificates or an ${env:NAME} reference.", + "type": "string" + }, + "tls_cert": { + "description": "PEM client certificate or ${env:NAME}; configure both tls_cert and tls_key.", + "type": "string" + }, + "tls_enabled": { + "default": false, + "description": "Whether TLS is enabled; defaults to false.", + "type": "boolean" + }, + "tls_key": { + "description": "PEM client private key or ${env:NAME}; configure both tls_cert and tls_key. Omit on update to preserve; an empty string clears it. Literal keys are omitted from responses.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "tls_max_version": { + "description": "Maximum TLS version: 1.2 or 1.3; empty means no constraint. Must not be below the minimum.", + "type": "string" + }, + "tls_min_version": { + "description": "Minimum TLS version: 1.2 (default) or 1.3.", + "type": "string" + }, + "tls_server_name": { + "description": "Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty.", + "type": "string" + }, + "tls_skip_verify": { + "description": "Skip server certificate verification when TLS is enabled.", + "type": "boolean" + }, + "username": { + "description": "Authentication username; an ${env:NAME} reference is supported.", + "type": "string" + } + }, + "type": "object" + }, + "DSMongoDBConfig": { + "description": "Diagnostic datasource connection configuration.", + "properties": { + "auth_source": { + "default": "admin", + "description": "Authentication database; defaults to admin. Username and password must be configured together. Client certificates are unsupported.", + "type": "string" + }, + "password": { + "description": "Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "Connection timeout in milliseconds; defaults to 3000 when omitted.", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "tls_ca": { + "description": "PEM CA certificates or an ${env:NAME} reference.", + "type": "string" + }, + "tls_enabled": { + "default": false, + "description": "Whether TLS is enabled; defaults to false.", + "type": "boolean" + }, + "tls_max_version": { + "description": "Maximum TLS version: 1.2 or 1.3; empty means no constraint. Must not be below the minimum.", + "type": "string" + }, + "tls_min_version": { + "description": "Minimum TLS version: 1.2 (default) or 1.3.", + "type": "string" + }, + "tls_server_name": { + "description": "Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty.", + "type": "string" + }, + "tls_skip_verify": { + "description": "Skip server certificate verification when TLS is enabled.", + "type": "boolean" + }, + "username": { + "description": "Authentication username; an ${env:NAME} reference is supported.", + "type": "string" + } + }, + "type": "object" + }, + "DSRedisNodeConfig": { + "description": "Diagnostic datasource connection configuration.", + "properties": { + "database": { + "default": 0, + "description": "Redis database number; defaults to 0.", + "minimum": 0, + "type": "integer" + }, + "password": { + "description": "Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "Connection timeout in milliseconds; defaults to 3000 when omitted.", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "username": { + "description": "Authentication username; an ${env:NAME} reference is supported.", + "type": "string" + } + }, + "type": "object" + }, + "DSRedisSentinelConfig": { + "description": "Diagnostic datasource connection configuration.", + "properties": { + "password": { + "description": "Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "Connection timeout in milliseconds; defaults to 3000 when omitted.", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "username": { + "description": "Authentication username; an ${env:NAME} reference is supported.", + "type": "string" + } + }, + "type": "object" + }, + "DatasourceToolInvokeRequest": { + "properties": { + "account_id": { + "description": "Optional consistency check; must equal the authenticated account.", + "format": "uint64", + "type": "integer" + }, + "datasource_id": { + "description": "Datasource ID from /monit/datasource/list.", + "format": "uint64", + "minimum": 1, + "type": "integer" + }, + "params": { + "additionalProperties": true, + "description": "Tool-specific JSON parameters; omitted means {}. Explicit null is invalid.", + "type": "object", + "x-flashduty-raw-json": true + }, + "tool": { + "description": "Single tool name prefixed by the datasource type, e.g. mysql.overview. Free SQL uses /monit/query/data; mysql.query and postgres.query are unsupported.", + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "datasource_id", + "tool" + ], + "type": "object" + }, + "DatasourceToolResult": { + "properties": { + "data": { + "description": "Tool-specific JSON evidence, preserved without conversion; never null. No nested legacy diagnose envelope.", + "not": { + "type": "null" + }, + "x-flashduty-raw-json": true + }, + "datasource_id": { + "description": "Datasource ID from /monit/datasource/list.", + "format": "uint64", + "minimum": 1, + "type": "integer" + }, + "summary": { + "description": "Optional non-empty summary.", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "tool": { + "description": "Executed tool name matching the request.", + "type": "string" + }, + "truncated": { + "$ref": "#/components/schemas/DatasourceToolTruncation", + "x-flashduty-preserve-absence": true + } + }, + "required": [ + "datasource_id", + "tool", + "data" + ], + "type": "object" + }, + "DatasourceToolTruncation": { + "properties": { + "reason": { + "description": "Why the result was truncated. Presence of this object indicates truncation.", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" } } } diff --git a/openapi/openapi.zh.json b/openapi/openapi.zh.json index 43e8ac4..b811b92 100644 --- a/openapi/openapi.zh.json +++ b/openapi/openapi.zh.json @@ -14714,12 +14714,12 @@ "post": { "operationId": "monit-datasource-read-list", "summary": "查询数据源列表", - "description": "返回当前账户下的所有数据源,可通过 `type_ident` 过滤类型。", + "description": "返回当前账户下的所有数据源,可通过 `type_ident` 过滤类型。 支持诊断类型 redis_node、redis_sentinel、mongodb_mongod、mongodb_mongos 和 kafka;enabled 与 alerting_enabled 相互独立。", "tags": [ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n\n## 使用说明\n\n- 省略 `type_ident` 可返回所有类型的数据源。\n- 列表响应中不返回敏感凭证字段(密码、密钥)。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n\n## 使用说明\n\n- 省略 `type_ident` 可返回所有类型的数据源。\n- 列表响应中不返回敏感凭证字段(密码、密钥)。\n\n完整支持类型与凭据行为见请求/响应 Schema。仅诊断类型不能启用告警。创建时省略 enabled 默认为 true,更新时省略保留当前值;enabled 或 alerting_enabled 的显式 null 非法。诊断密码及 Kafka 私钥在响应中省略,环境变量引用除外;更新时省略秘密字段保留原值,空字符串清除。其他数据源凭据可能返回,应作为敏感数据处理。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-read-list", "metadata": { "sidebarTitle": "查询数据源列表" @@ -14758,7 +14758,8 @@ "address": "http://prometheus.example.com:9090", "edge_cluster_name": "default", "updated_at": 1712000000, - "payload": null + "payload": null, + "alerting_enabled": true } ] } @@ -14797,12 +14798,12 @@ "post": { "operationId": "monit-datasource-read-info", "summary": "查看数据源详情", - "description": "通过 ID 获取单个数据源的完整信息,包括 `payload` 配置及其中配置的连接与鉴权信息;请将该响应视为敏感信息,避免记录或转发。", + "description": "通过 ID 获取单个数据源的完整信息,包括 `payload` 配置及其中配置的连接与鉴权信息;请将该响应视为敏感信息,避免记录或转发。 支持诊断类型 redis_node、redis_sentinel、mongodb_mongod、mongodb_mongos 和 kafka;enabled 与 alerting_enabled 相互独立。", "tags": [ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应会按原样返回 `payload` 配置——`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段均如实返回,不做脱敏。唯一例外是 `payload.tencent_cls.secret_key`:始终掩码为空字符串(`${env:...}` 引用则原样返回)。请将这些响应视为敏感信息:避免记录日志或转发给第三方。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源查看**(`monit`) |\n\n完整支持类型与凭据行为见请求/响应 Schema。仅诊断类型不能启用告警。创建时省略 enabled 默认为 true,更新时省略保留当前值;enabled 或 alerting_enabled 的显式 null 非法。诊断密码及 Kafka 私钥在响应中省略,环境变量引用除外;更新时省略秘密字段保留原值,空字符串清除。其他数据源凭据可能返回,应作为敏感数据处理。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-read-info", "metadata": { "sidebarTitle": "查看数据源详情" @@ -14847,7 +14848,8 @@ } }, "edge_cluster_name": "default", - "updated_at": 1712000000 + "updated_at": 1712000000, + "alerting_enabled": true } } } @@ -14885,12 +14887,12 @@ "post": { "operationId": "monit-datasource-write-create", "summary": "创建数据源", - "description": "创建新的监控数据源,`payload` 中须包含对应类型的配置块。", + "description": "创建新的监控数据源,`payload` 中须包含对应类型的配置块。 支持诊断类型 redis_node、redis_sentinel、mongodb_mongod、mongodb_mongos 和 kafka;enabled 与 alerting_enabled 相互独立。", "tags": [ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- `type_ident` 必须为以下之一:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`。\n- `edge_cluster_name` 指定使用该数据源进行规则评估的 Monitors Edge 集群。\n- 对于 `elasticsearch`,`payload.elasticsearch.deployment` 须设为 `cloud` 或 `self-managed`。\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应会按原样返回 `payload` 配置——`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段均如实返回,不做脱敏。唯一例外是 `payload.tencent_cls.secret_key`:始终掩码为空字符串(`${env:...}` 引用则原样返回)。请将这些响应视为敏感信息:避免记录日志或转发给第三方。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- `type_ident` 必须为以下之一:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`、`redis_node`、`redis_sentinel`、`mongodb_mongod`、`mongodb_mongos`、`kafka`。\n- `edge_cluster_name` 指定使用该数据源进行规则评估的 Monitors Edge 集群。\n- 对于 `elasticsearch`,`payload.elasticsearch.deployment` 须设为 `cloud` 或 `self-managed`。\n- 每次调用都会记录到账户审计日志,仅通过凭据字段配置连接凭据。\n\n完整支持类型与凭据行为见请求/响应 Schema。仅诊断类型不能启用告警。创建时省略 enabled 默认为 true,更新时省略保留当前值;enabled 或 alerting_enabled 的显式 null 非法。诊断密码及 Kafka 私钥在响应中省略,环境变量引用除外;更新时省略秘密字段保留原值,空字符串清除。其他数据源凭据可能返回,应作为敏感数据处理。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-write-create", "metadata": { "sidebarTitle": "创建数据源" @@ -14924,7 +14926,8 @@ "name": "Prometheus Prod", "enabled": true, "edge_cluster_name": "default", - "updated_at": 1712000000 + "updated_at": 1712000000, + "alerting_enabled": true } } } @@ -14971,12 +14974,12 @@ "post": { "operationId": "monit-datasource-write-update", "summary": "更新数据源", - "description": "更新已有数据源,需提供 `id` 及待修改的字段。", + "description": "更新已有数据源,需提供 `id` 及待修改的字段。 支持诊断类型 redis_node、redis_sentinel、mongodb_mongod、mongodb_mongos 和 kafka;enabled 与 alerting_enabled 相互独立。", "tags": [ "Monitors/告警数据源" ], "x-mint": { - "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- 每次调用都会记录到账户审计日志,请不要把敏感信息放在请求字段中。\n\n## 凭据字段\n\n`info` / `create` / `update` 的响应会按原样返回 `payload` 配置——`password`、`basic_auth_password`、`api_key`、`service_token`、`access_key_secret`、`tls_key`、`tls_key_pwd` 等字段均如实返回,不做脱敏。唯一例外是 `payload.tencent_cls.secret_key`:始终掩码为空字符串(`${env:...}` 引用则原样返回)。请将这些响应视为敏感信息:避免记录日志或转发给第三方。", + "content": "## 限制说明\n\n| 项目 | 说明 |\n| ---- | ---- |\n| 速率限制 | 每个账户 **1,000 次/分钟**;**50 次/秒** |\n| 权限要求 | **数据源管理**(`monit`) |\n\n## 使用说明\n\n- 每次调用都会记录到账户审计日志,仅通过凭据字段配置连接凭据。\n\n完整支持类型与凭据行为见请求/响应 Schema。仅诊断类型不能启用告警。创建时省略 enabled 默认为 true,更新时省略保留当前值;enabled 或 alerting_enabled 的显式 null 非法。诊断密码及 Kafka 私钥在响应中省略,环境变量引用除外;更新时省略秘密字段保留原值,空字符串清除。其他数据源凭据可能返回,应作为敏感数据处理。", "href": "/zh/api-reference/monitors/data-sources/monit-datasource-write-update", "metadata": { "sidebarTitle": "更新数据源" @@ -15010,7 +15013,8 @@ "name": "Prometheus Prod v2", "enabled": true, "edge_cluster_name": "default", - "updated_at": 1712100000 + "updated_at": 1712100000, + "alerting_enabled": true } } } @@ -20103,7 +20107,7 @@ "post": { "operationId": "monit-read-query-diagnose", "summary": "数据源诊断", - "description": "执行同步诊断查询(Loki/VictoriaLogs 使用 `log_patterns`,Prometheus 使用 `metric_trends`)。Flashduty AI SRE 用于日志模式聚类与时间序列趋势分析。长耗时——最长可达 35 秒。", + "description": "执行同步诊断查询(Loki/VictoriaLogs 使用 `log_patterns`,Prometheus 使用 `metric_trends`)。Flashduty AI SRE 用于日志模式聚类与时间序列趋势分析。长耗时——最长可达 35 秒。 已弃用:迁移到 /monit/datasource/tools/invoke 的 prometheus.metric_trends、loki.log_patterns 或 victorialogs.log_patterns。为现有消费者保留,旧请求与响应保持不变。", "tags": [ "Monitors/诊断分析" ], @@ -20277,14 +20281,15 @@ "500": { "$ref": "#/components/responses/ServerError" } - } + }, + "deprecated": true } }, "/monit/tools/catalog": { "post": { "operationId": "monit-read-tools-catalog", "summary": "查询监控对象工具能力清单", - "description": "根据 `target_locator`(host、mysql 等)查询该监控对象上 monit-agent 当前暴露的工具能力。返回每个工具的名称、描述以及 JSON-Schema `input_schema`。配合 `/monit/tools/invoke` 驱动 AI-SRE 的工具调用。", + "description": "根据 `target_locator`(host)查询该监控对象上 monit-agent 当前暴露的工具能力。返回每个工具的名称、描述以及 JSON-Schema `input_schema`。配合 `/monit/tools/invoke` 驱动 AI-SRE 的工具调用。 Agent 目标仅支持 host。远端数据源取证使用 /monit/datasource/tools/invoke 和 datasource_id。", "tags": [ "Monitors/诊断分析" ], @@ -20393,7 +20398,7 @@ "post": { "operationId": "monit-read-tools-invoke", "summary": "调用监控对象工具", - "description": "在单个监控对象上并发调用至多 8 个 monit-agent 工具。结果按入参 `tools` 数组顺序返回。长耗时——单个工具在 Agent 上有自己的超时,整体请求可能耗时数十秒。", + "description": "在单个监控对象上并发调用至多 8 个 monit-agent 工具。结果按入参 `tools` 数组顺序返回。长耗时——单个工具在 Agent 上有自己的超时,整体请求可能耗时数十秒。 Agent 目标仅支持 host。远端数据源取证使用 /monit/datasource/tools/invoke 和 datasource_id。", "tags": [ "Monitors/诊断分析" ], @@ -20520,7 +20525,7 @@ "post": { "operationId": "monit-read-targets-list", "summary": "监控对象列表", - "description": "列出当前租户下被 monit-agent 路由投影所观测到的监控对象。支持 `target_locator` 前缀搜索与游标分页。用于为 `/monit/tools/catalog` 与 `/monit/tools/invoke` 选择 `target_locator`。", + "description": "列出当前租户下被 monit-agent 路由投影所观测到的监控对象。支持 `target_locator` 前缀搜索与游标分页。用于为 `/monit/tools/catalog` 与 `/monit/tools/invoke` 选择 `target_locator`。 Agent 目标仅支持 host。远端数据源取证使用 /monit/datasource/tools/invoke 和 datasource_id。", "tags": [ "Monitors/诊断分析" ], @@ -31773,6 +31778,176 @@ } } } + }, + "/monit/datasource/tools/invoke": { + "post": { + "description": "对已配置的数据源执行单个确定性工具。要求集群所有当前在线可路由 Edge 会话支持 v0.71.0 基础 invoke 协议;具体工具可能需要更新实现。不提供工具目录、自动重放或 Agent/旧 diagnose 回退。请求体上限 128 KiB,完整成功响应上限 1 MiB,工具超时最多 25 秒。", + "operationId": "monit-datasource-tools-invoke", + "requestBody": { + "content": { + "application/json": { + "example": { + "datasource_id": 10, + "params": {}, + "tool": "mysql.overview" + }, + "schema": { + "$ref": "#/components/schemas/DatasourceToolInvokeRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "data": { + "data": { + "version": "8.0.36" + }, + "datasource_id": 10, + "summary": "MySQL overview", + "tool": "mysql.overview" + }, + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "properties": { + "data": { + "$ref": "#/components/schemas/DatasourceToolResult" + } + }, + "type": "object" + } + ] + } + } + }, + "description": "成功" + }, + "400": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:invalid_request, tool_not_supported, datasource_error." + }, + "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." + }, + "409": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:datasource_disabled, datasource_in_use." + }, + "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." + }, + "504": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + }, + "description": "标准 HTTP 错误;error.reason:timeout." + } + }, + "summary": "调用数据源工具", + "tags": [ + "Monitors/Data sources" + ], + "x-mint": { + "content": "通过 `/monit/datasource/list` 获取数据源 ID。停用数据源返回 `datasource_disabled`,`alerting_enabled=false` 不阻断工具。错误使用非 2xx HTTP 状态和 `error.code`、`error.message`、`error.reason`。`tool_not_supported` 表示选中的执行端未提供该工具,不表示厂商权限不足。禁止自动切换 Edge 或回退旧 diagnose 重试。", + "href": "/zh/api-reference/monitors/data-sources/monit-datasource-tools-invoke", + "metadata": { + "sidebarTitle": "调用数据源工具" + } + } + } } }, "components": { @@ -32067,6 +32242,11 @@ "type": "string", "description": "用户可读的错误描述,语言会跟随调用方的 Accept-Language。可能包含字段名、ID 等请求上下文。", "example": "The specified parameter template_id is not valid." + }, + "reason": { + "description": "可选的机器可读拒绝原因,包含数据源工具错误;结合 HTTP 状态及 code 判断。", + "type": "string", + "x-flashduty-preserve-absence": true } }, "required": [ @@ -45471,7 +45651,7 @@ "properties": { "type": { "type": "string", - "description": "按数据源类型标识过滤,省略则返回所有类型。可选值:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`。" + "description": "数据源类型标识。省略时返回全部类型。支持:`prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" } } }, @@ -45509,6 +45689,26 @@ "tencent_cls": { "$ref": "#/components/schemas/DSTencentCLSConfig", "description": "腾讯云 CLS 凭证。`type_ident` 为 `tencent_cls` 时必填。" + }, + "kafka": { + "$ref": "#/components/schemas/DSKafkaConfig", + "x-flashduty-preserve-absence": true + }, + "mongodb_mongod": { + "$ref": "#/components/schemas/DSMongoDBConfig", + "x-flashduty-preserve-absence": true + }, + "mongodb_mongos": { + "$ref": "#/components/schemas/DSMongoDBConfig", + "x-flashduty-preserve-absence": true + }, + "redis_node": { + "$ref": "#/components/schemas/DSRedisNodeConfig", + "x-flashduty-preserve-absence": true + }, + "redis_sentinel": { + "$ref": "#/components/schemas/DSRedisSentinelConfig", + "x-flashduty-preserve-absence": true } } }, @@ -46020,7 +46220,8 @@ "address", "edge_cluster_name", "updated_at", - "payload" + "payload", + "alerting_enabled" ], "properties": { "id": { @@ -46035,7 +46236,7 @@ }, "type_ident": { "type": "string", - "description": "数据源类型标识,可选值:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`。" + "description": "数据源类型标识。支持:`prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" }, "name": { "type": "string", @@ -46043,7 +46244,7 @@ }, "enabled": { "type": "boolean", - "description": "数据源是否启用。" + "description": "是否启用业务执行。停用时拒绝业务查询和工具调用;重新启用不改变 alerting_enabled。" }, "note": { "type": "string", @@ -46051,7 +46252,8 @@ }, "address": { "type": "string", - "description": "连接地址。Prometheus/Loki/VictoriaLogs 为 HTTP URL;MySQL/Oracle/Postgres/ClickHouse 为 `host:port`;SLS 为不含 http/https 前缀的 endpoint。" + "description": "连接地址。Prometheus/Loki/VictoriaLogs 为 HTTP URL;MySQL/Oracle/Postgres/ClickHouse 为 `host:port`;SLS 为不含 http/https 前缀的 endpoint。 Redis/MongoDB 诊断类型使用单个 host:port(IPv6 加方括号),不接受 URI、userinfo 或查询参数。Kafka 使用 1–32 个不重复、逗号分隔的 host:port 引导地址;payload 不含 broker 列表。规范化后最多 4096 个字符。", + "maxLength": 4096 }, "payload": { "anyOf": [ @@ -46062,7 +46264,7 @@ "type": "null" } ], - "description": "类型相关配置块,必须包含与 `type_ident` 匹配的键。`/monit/datasource/list` 响应中恒为 `null`(列表查询不读取 payload 列);创建/更新/详情响应中会返回。对于 `tencent_cls`,`secret_key` 会被掩码为空字符串,除非其值为 `${env:...}` 引用。" + "description": "类型相关配置块,必须包含与 `type_ident` 匹配的键。`/monit/datasource/list` 响应中恒为 `null`(列表查询不读取 payload 列);创建/更新/详情响应中会返回。对于 `tencent_cls`,`secret_key` 会被掩码为空字符串,除非其值为 `${env:...}` 引用。 诊断类型的 password 和 Kafka tls_key 在响应中省略,${env:...} 引用除外;更新时省略保留已保存的秘密,显式空字符串清除。其他配置字段保持原有行为。" }, "edge_cluster_name": { "type": "string", @@ -46072,6 +46274,10 @@ "type": "integer", "format": "int64", "description": "最后更新时间,Unix 时间戳(秒)。" + }, + "alerting_enabled": { + "description": "是否允许告警评估。告警同时要求 enabled=true 且类型支持告警。仅诊断类型固定为 false;false 不阻断非告警查询或工具。", + "type": "boolean" } } }, @@ -46092,7 +46298,7 @@ }, "type_ident": { "type": "string", - "description": "数据源类型标识,可选值:`prometheus`、`loki`、`mysql`、`oracle`、`postgres`、`clickhouse`、`elasticsearch`、`sls`、`tencent_cls`、`victorialogs`。" + "description": "数据源类型标识。支持:`prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。" }, "name": { "type": "string", @@ -46104,11 +46310,12 @@ }, "address": { "type": "string", - "description": "连接地址。除 `elasticsearch` 的 `deployment: cloud` 部署外均为必填。Prometheus/Loki/VictoriaLogs 为 HTTP URL;MySQL/Oracle/Postgres/ClickHouse 为 `host:port`;SLS 为不含 `http(s)://` 前缀的 endpoint;`tencent_cls` 必须为 `cls.tencentcloudapi.com` 或 `cls.internal.tencentcloudapi.com`(要求 Monitors edge >= v0.66.0)。" + "description": "连接地址。除 `elasticsearch` 的 `deployment: cloud` 部署外均为必填。Prometheus/Loki/VictoriaLogs 为 HTTP URL;MySQL/Oracle/Postgres/ClickHouse 为 `host:port`;SLS 为不含 `http(s)://` 前缀的 endpoint;`tencent_cls` 必须为 `cls.tencentcloudapi.com` 或 `cls.internal.tencentcloudapi.com`(要求 Monitors edge >= v0.66.0)。 Redis/MongoDB 诊断类型使用单个 host:port(IPv6 加方括号),不接受 URI、userinfo 或查询参数。Kafka 使用 1–32 个不重复、逗号分隔的 host:port 引导地址;payload 不含 broker 列表。规范化后最多 4096 个字符。", + "maxLength": 4096 }, "payload": { "$ref": "#/components/schemas/DSPayload", - "description": "类型相关配置块,必须包含与 `type_ident` 匹配的键。" + "description": "类型相关配置块,必须包含与 `type_ident` 匹配的键。 诊断类型的 password 和 Kafka tls_key 在响应中省略,${env:...} 引用除外;更新时省略保留已保存的秘密,显式空字符串清除。其他配置字段保持原有行为。" }, "edge_cluster_name": { "type": "string", @@ -46116,7 +46323,13 @@ }, "enabled": { "type": "boolean", - "description": "数据源是否启用(参与规则评估)。创建时省略则默认禁用(`false`)。" + "description": "是否启用业务执行。创建时省略默认为 true;更新时省略保留当前值。显式 false 停用执行;null 非法。不改变 alerting_enabled。", + "x-flashduty-preserve-absence": true + }, + "alerting_enabled": { + "description": "是否允许数据源用于告警。创建时省略:支持告警的类型默认为 true,仅诊断类型默认为 false;更新时省略保留当前值。null 非法。redis_node、redis_sentinel、mongodb_mongod、mongodb_mongos 和 kafka 不允许 true。有启用规则引用时,关闭用途返回冲突。", + "type": "boolean", + "x-flashduty-preserve-absence": true } } }, @@ -50121,11 +50334,14 @@ }, "target_locator": { "type": "string", - "description": "监控对象标识(主机名、MySQL 地址等)。最长 256 字节;不允许空白、控制字符或 `|`。" + "description": "主机名,最多 256 字节,不允许空白、控制字符或 |。" }, "target_kind": { "type": "string", - "description": "可选的 target kind。省略时 webapi 会按当前监控对象路由自动推断。若返回 `ambiguous_target_kind`,请从 `target_kinds` 中选择一个值重试。" + "description": "可选目标类型,仅支持 host,省略时推断。", + "enum": [ + "host" + ] } } }, @@ -50138,7 +50354,7 @@ "properties": { "kind": { "type": "string", - "description": "解析出的目标类型(target kind),如 `host`、`mysql`;与请求推断或指定的 `target_kind` 一致。" + "description": "解析后的 host 目标类型。" }, "locator": { "type": "string", @@ -50218,11 +50434,14 @@ }, "target_locator": { "type": "string", - "description": "监控对象标识。校验规则与 `/monit/tools/catalog` 相同。" + "description": "主机名,最多 256 字节,不允许空白、控制字符或 |。" }, "target_kind": { "type": "string", - "description": "可选的 target kind;省略时自动推断。" + "description": "可选目标类型,仅支持 host,省略时推断。", + "enum": [ + "host" + ] }, "tools": { "type": "array", @@ -50258,7 +50477,7 @@ "properties": { "kind": { "type": "string", - "description": "解析出的目标类型(target kind),如 `host`、`mysql`;与请求推断或指定的 `target_kind` 一致。" + "description": "解析后的 host 目标类型。" }, "locator": { "type": "string", @@ -50389,7 +50608,7 @@ "properties": { "target_kind": { "type": "string", - "description": "Target kind,如 `host`、`mysql`。v1 不支持按 kind 过滤。" + "description": "主机目标类型 host。v1 不支持按 kind 过滤。" }, "target_locator": { "type": "string", @@ -61997,6 +62216,255 @@ "size", "content_type" ] + }, + "DSKafkaConfig": { + "description": "诊断数据源连接配置。", + "properties": { + "password": { + "description": "认证密码,支持 ${env:NAME}。更新时省略保留;显式空字符串清除。响应中省略字面密码。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "sasl_mechanism": { + "default": "none", + "description": "SASL 机制:none(默认,不接受凭据)、plain、scram-sha-256、scram-sha-512(需要用户名与密码)。", + "enum": [ + "none", + "plain", + "scram-sha-256", + "scram-sha-512" + ], + "type": "string" + }, + "timeout_ms": { + "default": 5000, + "description": "连接超时,单位毫秒;省略默认为 5000。", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "tls_ca": { + "description": "PEM CA 证书或 ${env:NAME} 引用。", + "type": "string" + }, + "tls_cert": { + "description": "PEM 客户端证书或 ${env:NAME},须配对配置 tls_cert 与 tls_key。", + "type": "string" + }, + "tls_enabled": { + "default": false, + "description": "是否启用 TLS,默认为 false。", + "type": "boolean" + }, + "tls_key": { + "description": "PEM 客户端私钥或 ${env:NAME},须配对配置 tls_cert 与 tls_key。 更新时省略保留,空字符串清除;响应中省略字面私钥。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "tls_max_version": { + "description": "最高 TLS 版本:1.2 或 1.3;空值表示不限制,不能低于最低版本。", + "type": "string" + }, + "tls_min_version": { + "description": "最低 TLS 版本:1.2(默认)或 1.3。", + "type": "string" + }, + "tls_server_name": { + "description": "TLS 握手使用的 SNI / 证书校验主机名;留空时取连接地址中的主机名。", + "type": "string" + }, + "tls_skip_verify": { + "description": "启用 TLS 时是否跳过服务端证书验证。", + "type": "boolean" + }, + "username": { + "description": "认证用户名,支持 ${env:NAME} 引用。", + "type": "string" + } + }, + "type": "object" + }, + "DSMongoDBConfig": { + "description": "诊断数据源连接配置。", + "properties": { + "auth_source": { + "default": "admin", + "description": "认证数据库,默认为 admin。用户名与密码必须同时配置。不支持客户端证书。", + "type": "string" + }, + "password": { + "description": "认证密码,支持 ${env:NAME}。更新时省略保留;显式空字符串清除。响应中省略字面密码。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "连接超时,单位毫秒;省略默认为 3000。", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "tls_ca": { + "description": "PEM CA 证书或 ${env:NAME} 引用。", + "type": "string" + }, + "tls_enabled": { + "default": false, + "description": "是否启用 TLS,默认为 false。", + "type": "boolean" + }, + "tls_max_version": { + "description": "最高 TLS 版本:1.2 或 1.3;空值表示不限制,不能低于最低版本。", + "type": "string" + }, + "tls_min_version": { + "description": "最低 TLS 版本:1.2(默认)或 1.3。", + "type": "string" + }, + "tls_server_name": { + "description": "TLS 握手使用的 SNI / 证书校验主机名;留空时取连接地址中的主机名。", + "type": "string" + }, + "tls_skip_verify": { + "description": "启用 TLS 时是否跳过服务端证书验证。", + "type": "boolean" + }, + "username": { + "description": "认证用户名,支持 ${env:NAME} 引用。", + "type": "string" + } + }, + "type": "object" + }, + "DSRedisNodeConfig": { + "description": "诊断数据源连接配置。", + "properties": { + "database": { + "default": 0, + "description": "Redis 数据库编号,默认为 0。", + "minimum": 0, + "type": "integer" + }, + "password": { + "description": "认证密码,支持 ${env:NAME}。更新时省略保留;显式空字符串清除。响应中省略字面密码。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "连接超时,单位毫秒;省略默认为 3000。", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "username": { + "description": "认证用户名,支持 ${env:NAME} 引用。", + "type": "string" + } + }, + "type": "object" + }, + "DSRedisSentinelConfig": { + "description": "诊断数据源连接配置。", + "properties": { + "password": { + "description": "认证密码,支持 ${env:NAME}。更新时省略保留;显式空字符串清除。响应中省略字面密码。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "timeout_ms": { + "default": 3000, + "description": "连接超时,单位毫秒;省略默认为 3000。", + "maximum": 10000, + "minimum": 1000, + "type": "integer" + }, + "username": { + "description": "认证用户名,支持 ${env:NAME} 引用。", + "type": "string" + } + }, + "type": "object" + }, + "DatasourceToolInvokeRequest": { + "properties": { + "account_id": { + "description": "可选一致性检查,必须等于认证账户。", + "format": "uint64", + "type": "integer" + }, + "datasource_id": { + "description": "通过 /monit/datasource/list 获取的数据源 ID。", + "format": "uint64", + "minimum": 1, + "type": "integer" + }, + "params": { + "additionalProperties": true, + "description": "工具专属 JSON 参数,省略时为 {},显式 null 非法。", + "type": "object", + "x-flashduty-raw-json": true + }, + "tool": { + "description": "以数据源类型为前缀的单个工具名,如 mysql.overview。自由 SQL 使用 /monit/query/data;不支持 mysql.query 和 postgres.query。", + "maxLength": 128, + "minLength": 1, + "type": "string" + } + }, + "required": [ + "datasource_id", + "tool" + ], + "type": "object" + }, + "DatasourceToolResult": { + "properties": { + "data": { + "description": "工具专属 JSON 证据,原样保留,不为 null,不包含旧 diagnose 额外信封。", + "not": { + "type": "null" + }, + "x-flashduty-raw-json": true + }, + "datasource_id": { + "description": "通过 /monit/datasource/list 获取的数据源 ID。", + "format": "uint64", + "minimum": 1, + "type": "integer" + }, + "summary": { + "description": "可选非空摘要。", + "type": "string", + "x-flashduty-preserve-absence": true + }, + "tool": { + "description": "执行的工具名,与请求一致。", + "type": "string" + }, + "truncated": { + "$ref": "#/components/schemas/DatasourceToolTruncation", + "x-flashduty-preserve-absence": true + } + }, + "required": [ + "datasource_id", + "tool", + "data" + ], + "type": "object" + }, + "DatasourceToolTruncation": { + "properties": { + "reason": { + "description": "结果截断原因;该对象存在即表示发生截断。", + "type": "string" + } + }, + "required": [ + "reason" + ], + "type": "object" } } } diff --git a/roundtrip_gen_test.go b/roundtrip_gen_test.go index b7bfc5e..64428ac 100644 --- a/roundtrip_gen_test.go +++ b/roundtrip_gen_test.go @@ -107,6 +107,7 @@ var exampleDataDecoders = map[string]func(json.RawMessage) error{ "POST /monit/datasource/list": func(d json.RawMessage) error { var v DataSourceListResponse; return json.Unmarshal(d, &v) }, "POST /monit/datasource/sls/logstores": func(d json.RawMessage) error { var v SLSLogstoresResponse; return json.Unmarshal(d, &v) }, "POST /monit/datasource/sls/projects": func(d json.RawMessage) error { var v SLSProjectsResponse; return json.Unmarshal(d, &v) }, + "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/diagnose": func(d json.RawMessage) error { var v DiagnoseResponse; return json.Unmarshal(d, &v) },