From a1866a2462177945c85f479df2d491c4672c7ad9 Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Thu, 20 Nov 2025 17:42:09 +0000 Subject: [PATCH] Regenerate client from commit 2aab4b8 of spec repo --- .generator/schemas/v1/openapi.yaml | 62 +++++- .../model_service_level_objective.go | 4 +- .../model_service_level_objective_query.go | 2 +- .../model_service_level_objective_request.go | 4 +- api/datadogV1/model_slo_count_condition.go | 178 ++++++++++++++++++ api/datadogV1/model_slo_count_spec.go | 96 ++++++++++ api/datadogV1/model_slo_response_data.go | 45 +---- api/datadogV1/model_slo_sli_spec.go | 34 +++- .../CreateSLO_512760759.go | 75 ++++++++ .../v1/service_level_objectives.feature | 26 +++ 10 files changed, 473 insertions(+), 53 deletions(-) create mode 100644 api/datadogV1/model_slo_count_condition.go create mode 100644 api/datadogV1/model_slo_count_spec.go create mode 100644 examples/v1/service-level-objectives/CreateSLO_512760759.go diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index e4c94965900..c132893290d 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -11409,6 +11409,60 @@ components: example: UTC type: string type: object + SLOCountCondition: + description: 'A count-based SLI specification, composed of three parts: the + good events formula, the total events formula, + + and the involved queries.' + example: + good_events_formula: query1 - query2 + queries: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.success{*} by {env}.as_count() + - data_source: metrics + name: query2 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + total_events_formula: query2 + properties: + good_events_formula: + $ref: '#/components/schemas/SLOFormula' + queries: + example: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + items: + $ref: '#/components/schemas/SLODataSourceQueryDefinition' + minItems: 1 + type: array + total_events_formula: + $ref: '#/components/schemas/SLOFormula' + required: + - good_events_formula + - total_events_formula + - queries + type: object + SLOCountSpec: + additionalProperties: false + description: A count-based SLI specification. + example: + count: + good_events_formula: query1 - query2 + queries: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.success{*} by {env}.as_count() + - data_source: metrics + name: query2 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + total_events_formula: query2 + properties: + count: + $ref: '#/components/schemas/SLOCountCondition' + required: + - count + type: object SLOCreator: description: The creator of the SLO nullable: true @@ -12295,8 +12349,6 @@ components: type: array timeframe: $ref: '#/components/schemas/SLOTimeframe' - type: - $ref: '#/components/schemas/SLOType' warning_threshold: description: 'The optional warning threshold such that when the service level indicator is @@ -12314,9 +12366,10 @@ components: type: object SLOSliSpec: description: A generic SLI specification. This is currently used for time-slice - SLOs only. + and count-based SLOs only. oneOf: - $ref: '#/components/schemas/SLOTimeSliceSpec' + - $ref: '#/components/schemas/SLOCountSpec' SLOState: description: State of the SLO. enum: @@ -13468,8 +13521,7 @@ components: - type type: object ServiceLevelObjectiveQuery: - description: 'A metric-based SLO. **Required if type is `metric`**. Note that - Datadog only allows the sum by aggregator + description: 'A metric-based SLO. Note that Datadog only allows the sum by aggregator to be used because this will sum up all request counts instead of averaging them, or taking the max or diff --git a/api/datadogV1/model_service_level_objective.go b/api/datadogV1/model_service_level_objective.go index cd037ba0aed..cb07604877b 100644 --- a/api/datadogV1/model_service_level_objective.go +++ b/api/datadogV1/model_service_level_objective.go @@ -50,11 +50,11 @@ type ServiceLevelObjective struct { MonitorTags []string `json:"monitor_tags,omitempty"` // The name of the service level objective object. Name string `json:"name"` - // A metric-based SLO. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator + // A metric-based SLO. Note that Datadog only allows the sum by aggregator // to be used because this will sum up all request counts instead of averaging them, or taking the max or // min of all of those requests. Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` - // A generic SLI specification. This is currently used for time-slice SLOs only. + // A generic SLI specification. This is currently used for time-slice and count-based SLOs only. SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` // A list of tags associated with this service level objective. // Always included in service level objective responses (but may be empty). diff --git a/api/datadogV1/model_service_level_objective_query.go b/api/datadogV1/model_service_level_objective_query.go index b236bfbd803..a99db3b581a 100644 --- a/api/datadogV1/model_service_level_objective_query.go +++ b/api/datadogV1/model_service_level_objective_query.go @@ -10,7 +10,7 @@ import ( "github.com/DataDog/datadog-api-client-go/v2/api/datadog" ) -// ServiceLevelObjectiveQuery A metric-based SLO. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator +// ServiceLevelObjectiveQuery A metric-based SLO. Note that Datadog only allows the sum by aggregator // to be used because this will sum up all request counts instead of averaging them, or taking the max or // min of all of those requests. type ServiceLevelObjectiveQuery struct { diff --git a/api/datadogV1/model_service_level_objective_request.go b/api/datadogV1/model_service_level_objective_request.go index ef52a9eca8b..2d8e190a9c0 100644 --- a/api/datadogV1/model_service_level_objective_request.go +++ b/api/datadogV1/model_service_level_objective_request.go @@ -29,11 +29,11 @@ type ServiceLevelObjectiveRequest struct { MonitorIds []int64 `json:"monitor_ids,omitempty"` // The name of the service level objective object. Name string `json:"name"` - // A metric-based SLO. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator + // A metric-based SLO. Note that Datadog only allows the sum by aggregator // to be used because this will sum up all request counts instead of averaging them, or taking the max or // min of all of those requests. Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` - // A generic SLI specification. This is currently used for time-slice SLOs only. + // A generic SLI specification. This is currently used for time-slice and count-based SLOs only. SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` // A list of tags associated with this service level objective. // Always included in service level objective responses (but may be empty). diff --git a/api/datadogV1/model_slo_count_condition.go b/api/datadogV1/model_slo_count_condition.go new file mode 100644 index 00000000000..c1b309b0999 --- /dev/null +++ b/api/datadogV1/model_slo_count_condition.go @@ -0,0 +1,178 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV1 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// SLOCountCondition A count-based SLI specification, composed of three parts: the good events formula, the total events formula, +// and the involved queries. +type SLOCountCondition struct { + // A formula that specifies how to combine the results of multiple queries. + GoodEventsFormula SLOFormula `json:"good_events_formula"` + // + Queries []SLODataSourceQueryDefinition `json:"queries"` + // A formula that specifies how to combine the results of multiple queries. + TotalEventsFormula SLOFormula `json:"total_events_formula"` + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject map[string]interface{} `json:"-"` + AdditionalProperties map[string]interface{} `json:"-"` +} + +// NewSLOCountCondition instantiates a new SLOCountCondition object. +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed. +func NewSLOCountCondition(goodEventsFormula SLOFormula, queries []SLODataSourceQueryDefinition, totalEventsFormula SLOFormula) *SLOCountCondition { + this := SLOCountCondition{} + this.GoodEventsFormula = goodEventsFormula + this.Queries = queries + this.TotalEventsFormula = totalEventsFormula + return &this +} + +// NewSLOCountConditionWithDefaults instantiates a new SLOCountCondition object. +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set. +func NewSLOCountConditionWithDefaults() *SLOCountCondition { + this := SLOCountCondition{} + return &this +} + +// GetGoodEventsFormula returns the GoodEventsFormula field value. +func (o *SLOCountCondition) GetGoodEventsFormula() SLOFormula { + if o == nil { + var ret SLOFormula + return ret + } + return o.GoodEventsFormula +} + +// GetGoodEventsFormulaOk returns a tuple with the GoodEventsFormula field value +// and a boolean to check if the value has been set. +func (o *SLOCountCondition) GetGoodEventsFormulaOk() (*SLOFormula, bool) { + if o == nil { + return nil, false + } + return &o.GoodEventsFormula, true +} + +// SetGoodEventsFormula sets field value. +func (o *SLOCountCondition) SetGoodEventsFormula(v SLOFormula) { + o.GoodEventsFormula = v +} + +// GetQueries returns the Queries field value. +func (o *SLOCountCondition) GetQueries() []SLODataSourceQueryDefinition { + if o == nil { + var ret []SLODataSourceQueryDefinition + return ret + } + return o.Queries +} + +// GetQueriesOk returns a tuple with the Queries field value +// and a boolean to check if the value has been set. +func (o *SLOCountCondition) GetQueriesOk() (*[]SLODataSourceQueryDefinition, bool) { + if o == nil { + return nil, false + } + return &o.Queries, true +} + +// SetQueries sets field value. +func (o *SLOCountCondition) SetQueries(v []SLODataSourceQueryDefinition) { + o.Queries = v +} + +// GetTotalEventsFormula returns the TotalEventsFormula field value. +func (o *SLOCountCondition) GetTotalEventsFormula() SLOFormula { + if o == nil { + var ret SLOFormula + return ret + } + return o.TotalEventsFormula +} + +// GetTotalEventsFormulaOk returns a tuple with the TotalEventsFormula field value +// and a boolean to check if the value has been set. +func (o *SLOCountCondition) GetTotalEventsFormulaOk() (*SLOFormula, bool) { + if o == nil { + return nil, false + } + return &o.TotalEventsFormula, true +} + +// SetTotalEventsFormula sets field value. +func (o *SLOCountCondition) SetTotalEventsFormula(v SLOFormula) { + o.TotalEventsFormula = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOCountCondition) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["good_events_formula"] = o.GoodEventsFormula + toSerialize["queries"] = o.Queries + toSerialize["total_events_formula"] = o.TotalEventsFormula + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOCountCondition) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + GoodEventsFormula *SLOFormula `json:"good_events_formula"` + Queries *[]SLODataSourceQueryDefinition `json:"queries"` + TotalEventsFormula *SLOFormula `json:"total_events_formula"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.GoodEventsFormula == nil { + return fmt.Errorf("required field good_events_formula missing") + } + if all.Queries == nil { + return fmt.Errorf("required field queries missing") + } + if all.TotalEventsFormula == nil { + return fmt.Errorf("required field total_events_formula missing") + } + additionalProperties := make(map[string]interface{}) + if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { + datadog.DeleteKeys(additionalProperties, &[]string{"good_events_formula", "queries", "total_events_formula"}) + } else { + return err + } + + hasInvalidField := false + if all.GoodEventsFormula.UnparsedObject != nil && o.UnparsedObject == nil { + hasInvalidField = true + } + o.GoodEventsFormula = *all.GoodEventsFormula + o.Queries = *all.Queries + if all.TotalEventsFormula.UnparsedObject != nil && o.UnparsedObject == nil { + hasInvalidField = true + } + o.TotalEventsFormula = *all.TotalEventsFormula + + if len(additionalProperties) > 0 { + o.AdditionalProperties = additionalProperties + } + + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + + return nil +} diff --git a/api/datadogV1/model_slo_count_spec.go b/api/datadogV1/model_slo_count_spec.go new file mode 100644 index 00000000000..f72c6da1e5d --- /dev/null +++ b/api/datadogV1/model_slo_count_spec.go @@ -0,0 +1,96 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV1 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// SLOCountSpec A count-based SLI specification. +type SLOCountSpec struct { + // A count-based SLI specification, composed of three parts: the good events formula, the total events formula, + // and the involved queries. + Count SLOCountCondition `json:"count"` + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject map[string]interface{} `json:"-"` +} + +// NewSLOCountSpec instantiates a new SLOCountSpec object. +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed. +func NewSLOCountSpec(count SLOCountCondition) *SLOCountSpec { + this := SLOCountSpec{} + this.Count = count + return &this +} + +// NewSLOCountSpecWithDefaults instantiates a new SLOCountSpec object. +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set. +func NewSLOCountSpecWithDefaults() *SLOCountSpec { + this := SLOCountSpec{} + return &this +} + +// GetCount returns the Count field value. +func (o *SLOCountSpec) GetCount() SLOCountCondition { + if o == nil { + var ret SLOCountCondition + return ret + } + return o.Count +} + +// GetCountOk returns a tuple with the Count field value +// and a boolean to check if the value has been set. +func (o *SLOCountSpec) GetCountOk() (*SLOCountCondition, bool) { + if o == nil { + return nil, false + } + return &o.Count, true +} + +// SetCount sets field value. +func (o *SLOCountSpec) SetCount(v SLOCountCondition) { + o.Count = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOCountSpec) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["count"] = o.Count + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOCountSpec) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + Count *SLOCountCondition `json:"count"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.Count == nil { + return fmt.Errorf("required field count missing") + } + + hasInvalidField := false + if all.Count.UnparsedObject != nil && o.UnparsedObject == nil { + hasInvalidField = true + } + o.Count = *all.Count + + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + + return nil +} diff --git a/api/datadogV1/model_slo_response_data.go b/api/datadogV1/model_slo_response_data.go index 5225687d346..0f5bd43f723 100644 --- a/api/datadogV1/model_slo_response_data.go +++ b/api/datadogV1/model_slo_response_data.go @@ -50,11 +50,11 @@ type SLOResponseData struct { MonitorTags []string `json:"monitor_tags,omitempty"` // The name of the service level objective object. Name *string `json:"name,omitempty"` - // A metric-based SLO. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator + // A metric-based SLO. Note that Datadog only allows the sum by aggregator // to be used because this will sum up all request counts instead of averaging them, or taking the max or // min of all of those requests. Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` - // A generic SLI specification. This is currently used for time-slice SLOs only. + // A generic SLI specification. This is currently used for time-slice and count-based SLOs only. SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` // A list of tags associated with this service level objective. // Always included in service level objective responses (but may be empty). @@ -69,8 +69,6 @@ type SLOResponseData struct { // The SLO time window options. Note that "custom" is not a valid option for creating // or updating SLOs. It is only used when querying SLO history over custom timeframes. Timeframe *SLOTimeframe `json:"timeframe,omitempty"` - // The type of the service level objective. - Type *SLOType `json:"type,omitempty"` // The optional warning threshold such that when the service level indicator is // below this value for the given threshold, but above the target threshold, the // objective appears in a "warning" state. This value must be greater than the target @@ -557,34 +555,6 @@ func (o *SLOResponseData) SetTimeframe(v SLOTimeframe) { o.Timeframe = &v } -// GetType returns the Type field value if set, zero value otherwise. -func (o *SLOResponseData) GetType() SLOType { - if o == nil || o.Type == nil { - var ret SLOType - return ret - } - return *o.Type -} - -// GetTypeOk returns a tuple with the Type field value if set, nil otherwise -// and a boolean to check if the value has been set. -func (o *SLOResponseData) GetTypeOk() (*SLOType, bool) { - if o == nil || o.Type == nil { - return nil, false - } - return o.Type, true -} - -// HasType returns a boolean if a field has been set. -func (o *SLOResponseData) HasType() bool { - return o != nil && o.Type != nil -} - -// SetType gets a reference to the given SLOType and assigns it to the Type field. -func (o *SLOResponseData) SetType(v SLOType) { - o.Type = &v -} - // GetWarningThreshold returns the WarningThreshold field value if set, zero value otherwise. func (o *SLOResponseData) GetWarningThreshold() float64 { if o == nil || o.WarningThreshold == nil { @@ -667,9 +637,6 @@ func (o SLOResponseData) MarshalJSON() ([]byte, error) { if o.Timeframe != nil { toSerialize["timeframe"] = o.Timeframe } - if o.Type != nil { - toSerialize["type"] = o.Type - } if o.WarningThreshold != nil { toSerialize["warning_threshold"] = o.WarningThreshold } @@ -699,7 +666,6 @@ func (o *SLOResponseData) UnmarshalJSON(bytes []byte) (err error) { TargetThreshold *float64 `json:"target_threshold,omitempty"` Thresholds []SLOThreshold `json:"thresholds,omitempty"` Timeframe *SLOTimeframe `json:"timeframe,omitempty"` - Type *SLOType `json:"type,omitempty"` WarningThreshold *float64 `json:"warning_threshold,omitempty"` }{} if err = datadog.Unmarshal(bytes, &all); err != nil { @@ -707,7 +673,7 @@ func (o *SLOResponseData) UnmarshalJSON(bytes []byte) (err error) { } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"configured_alert_ids", "created_at", "creator", "description", "groups", "id", "modified_at", "monitor_ids", "monitor_tags", "name", "query", "sli_specification", "tags", "target_threshold", "thresholds", "timeframe", "type", "warning_threshold"}) + datadog.DeleteKeys(additionalProperties, &[]string{"configured_alert_ids", "created_at", "creator", "description", "groups", "id", "modified_at", "monitor_ids", "monitor_tags", "name", "query", "sli_specification", "tags", "target_threshold", "thresholds", "timeframe", "warning_threshold"}) } else { return err } @@ -739,11 +705,6 @@ func (o *SLOResponseData) UnmarshalJSON(bytes []byte) (err error) { } else { o.Timeframe = all.Timeframe } - if all.Type != nil && !all.Type.IsValid() { - hasInvalidField = true - } else { - o.Type = all.Type - } o.WarningThreshold = all.WarningThreshold if len(additionalProperties) > 0 { diff --git a/api/datadogV1/model_slo_sli_spec.go b/api/datadogV1/model_slo_sli_spec.go index 17873580fc8..bf936ca71d9 100644 --- a/api/datadogV1/model_slo_sli_spec.go +++ b/api/datadogV1/model_slo_sli_spec.go @@ -8,9 +8,10 @@ import ( "github.com/DataDog/datadog-api-client-go/v2/api/datadog" ) -// SLOSliSpec - A generic SLI specification. This is currently used for time-slice SLOs only. +// SLOSliSpec - A generic SLI specification. This is currently used for time-slice and count-based SLOs only. type SLOSliSpec struct { SLOTimeSliceSpec *SLOTimeSliceSpec + SLOCountSpec *SLOCountSpec // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct UnparsedObject interface{} @@ -21,6 +22,11 @@ func SLOTimeSliceSpecAsSLOSliSpec(v *SLOTimeSliceSpec) SLOSliSpec { return SLOSliSpec{SLOTimeSliceSpec: v} } +// SLOCountSpecAsSLOSliSpec is a convenience function that returns SLOCountSpec wrapped in SLOSliSpec. +func SLOCountSpecAsSLOSliSpec(v *SLOCountSpec) SLOSliSpec { + return SLOSliSpec{SLOCountSpec: v} +} + // UnmarshalJSON turns data into one of the pointers in the struct. func (obj *SLOSliSpec) UnmarshalJSON(data []byte) error { var err error @@ -42,9 +48,27 @@ func (obj *SLOSliSpec) UnmarshalJSON(data []byte) error { obj.SLOTimeSliceSpec = nil } + // try to unmarshal data into SLOCountSpec + err = datadog.Unmarshal(data, &obj.SLOCountSpec) + if err == nil { + if obj.SLOCountSpec != nil && obj.SLOCountSpec.UnparsedObject == nil { + jsonSLOCountSpec, _ := datadog.Marshal(obj.SLOCountSpec) + if string(jsonSLOCountSpec) == "{}" { // empty struct + obj.SLOCountSpec = nil + } else { + match++ + } + } else { + obj.SLOCountSpec = nil + } + } else { + obj.SLOCountSpec = nil + } + if match != 1 { // more than 1 match // reset to nil obj.SLOTimeSliceSpec = nil + obj.SLOCountSpec = nil return datadog.Unmarshal(data, &obj.UnparsedObject) } return nil // exactly one match @@ -56,6 +80,10 @@ func (obj SLOSliSpec) MarshalJSON() ([]byte, error) { return datadog.Marshal(&obj.SLOTimeSliceSpec) } + if obj.SLOCountSpec != nil { + return datadog.Marshal(&obj.SLOCountSpec) + } + if obj.UnparsedObject != nil { return datadog.Marshal(obj.UnparsedObject) } @@ -68,6 +96,10 @@ func (obj *SLOSliSpec) GetActualInstance() interface{} { return obj.SLOTimeSliceSpec } + if obj.SLOCountSpec != nil { + return obj.SLOCountSpec + } + // all schemas are nil return nil } diff --git a/examples/v1/service-level-objectives/CreateSLO_512760759.go b/examples/v1/service-level-objectives/CreateSLO_512760759.go new file mode 100644 index 00000000000..7f7b0671d83 --- /dev/null +++ b/examples/v1/service-level-objectives/CreateSLO_512760759.go @@ -0,0 +1,75 @@ +// Create a new metric SLO object using sli_specification returns "OK" response + +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" + "github.com/DataDog/datadog-api-client-go/v2/api/datadogV1" +) + +func main() { + body := datadogV1.ServiceLevelObjectiveRequest{ + Type: datadogV1.SLOTYPE_METRIC, + Description: *datadog.NewNullableString(datadog.PtrString("Metric SLO using sli_specification")), + Name: "Example-Service-Level-Objective", + SliSpecification: &datadogV1.SLOSliSpec{ + SLOCountSpec: &datadogV1.SLOCountSpec{ + Count: datadogV1.SLOCountCondition{ + GoodEventsFormula: datadogV1.SLOFormula{ + Formula: "query1", + }, + TotalEventsFormula: datadogV1.SLOFormula{ + Formula: "query2", + }, + Queries: []datadogV1.SLODataSourceQueryDefinition{ + datadogV1.SLODataSourceQueryDefinition{ + FormulaAndFunctionMetricQueryDefinition: &datadogV1.FormulaAndFunctionMetricQueryDefinition{ + DataSource: datadogV1.FORMULAANDFUNCTIONMETRICDATASOURCE_METRICS, + Name: "query1", + Query: "sum:httpservice.success{*}.as_count()", + }}, + datadogV1.SLODataSourceQueryDefinition{ + FormulaAndFunctionMetricQueryDefinition: &datadogV1.FormulaAndFunctionMetricQueryDefinition{ + DataSource: datadogV1.FORMULAANDFUNCTIONMETRICDATASOURCE_METRICS, + Name: "query2", + Query: "sum:httpservice.hits{*}.as_count()", + }}, + }, + }, + }}, + Tags: []string{ + "env:prod", + "type:count", + }, + Thresholds: []datadogV1.SLOThreshold{ + { + Target: 99.0, + TargetDisplay: datadog.PtrString("99.0"), + Timeframe: datadogV1.SLOTIMEFRAME_SEVEN_DAYS, + Warning: datadog.PtrFloat64(98), + WarningDisplay: datadog.PtrString("98.0"), + }, + }, + Timeframe: datadogV1.SLOTIMEFRAME_SEVEN_DAYS.Ptr(), + TargetThreshold: datadog.PtrFloat64(99.0), + WarningThreshold: datadog.PtrFloat64(98), + } + ctx := datadog.NewDefaultContext(context.Background()) + configuration := datadog.NewConfiguration() + apiClient := datadog.NewAPIClient(configuration) + api := datadogV1.NewServiceLevelObjectivesApi(apiClient) + resp, r, err := api.CreateSLO(ctx, body) + + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `ServiceLevelObjectivesApi.CreateSLO`: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + + responseContent, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "Response from `ServiceLevelObjectivesApi.CreateSLO`:\n%s\n", responseContent) +} diff --git a/tests/scenarios/features/v1/service_level_objectives.feature b/tests/scenarios/features/v1/service_level_objectives.feature index c5534618a73..3fba149b2d3 100644 --- a/tests/scenarios/features/v1/service_level_objectives.feature +++ b/tests/scenarios/features/v1/service_level_objectives.feature @@ -48,6 +48,30 @@ Feature: Service Level Objectives When the request is sent Then the response status is 200 OK + @team:DataDog/slo-app + Scenario: Create a metric SLO with both sli_specification and query returns "Bad Request" response + Given new "CreateSLO" request + And body with value {"type":"metric","description":"Invalid SLO with both sli_specification and query","name":"{{ unique }}","sli_specification":{"count":{"good_events_formula":{"formula":"query1"},"total_events_formula":{"formula":"query2"},"queries":[{"data_source":"metrics","name":"query1","query":"sum:httpservice.success{*}.as_count()"},{"data_source":"metrics","name":"query2","query":"sum:httpservice.hits{*}.as_count()"}]}},"query":{"numerator":"sum:httpservice.success{*}.as_count()","denominator":"sum:httpservice.hits{*}.as_count()"},"tags":["env:prod"],"thresholds":[{"target":99.0,"target_display":"99.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","target_threshold":99.0,"warning_threshold":98} + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/slo-app + Scenario: Create a new metric SLO object using sli_specification returns "OK" response + Given new "CreateSLO" request + And body with value {"type":"metric","description":"Metric SLO using sli_specification","name":"{{ unique }}","sli_specification":{"count":{"good_events_formula":{"formula":"query1"},"total_events_formula":{"formula":"query2"},"queries":[{"data_source":"metrics","name":"query1","query":"sum:httpservice.success{*}.as_count()"},{"data_source":"metrics","name":"query2","query":"sum:httpservice.hits{*}.as_count()"}]}},"tags":["env:prod","type:count"],"thresholds":[{"target":99.0,"target_display":"99.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","target_threshold":99.0,"warning_threshold":98} + When the request is sent + Then the response status is 200 OK + And the response "data[0].timeframe" is equal to "7d" + And the response "data[0].target_threshold" is equal to 99.0 + And the response "data[0].warning_threshold" is equal to 98.0 + And the response "data[0]" has field "sli_specification" + And the response "data[0].sli_specification" has field "count" + And the response "data[0].sli_specification.count" has field "good_events_formula" + And the response "data[0].sli_specification.count" has field "total_events_formula" + And the response "data[0].sli_specification.count" has field "queries" + And the response "data[0].sli_specification.count.queries" has length 2 + And the response "data[0]" does not have field "query" + @team:DataDog/slo-app Scenario: Create a time-slice SLO object returns "OK" response Given new "CreateSLO" request @@ -74,6 +98,8 @@ Feature: Service Level Objectives And the response "data[0].timeframe" is equal to "7d" And the response "data[0].target_threshold" is equal to 97.0 And the response "data[0].warning_threshold" is equal to 98.0 + And the response "data[0]" has field "query" + And the response "data[0]" does not have field "sli_specification" @generated @skip @team:DataDog/slo-app Scenario: Delete an SLO returns "Conflict" response