diff --git a/.apigentools-info b/.apigentools-info index 4670b775284..4125202bb85 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.6.6", - "regenerated": "2024-01-04 15:18:00.927828", - "spec_repo_commit": "e7cfa56f" + "regenerated": "2024-01-05 15:09:39.104630", + "spec_repo_commit": "9cbf6566" }, "v2": { "apigentools_version": "1.6.6", - "regenerated": "2024-01-04 15:18:00.942781", - "spec_repo_commit": "e7cfa56f" + "regenerated": "2024-01-05 15:09:39.125252", + "spec_repo_commit": "9cbf6566" } } } \ No newline at end of file diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index e35aca86357..d0eb91e2ecb 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -10244,6 +10244,13 @@ components: nullable: true type: string type: object + SLODataSourceQueryDefinition: + description: A formula and function query. + example: + data_source: metrics + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + oneOf: + - $ref: '#/components/schemas/FormulaAndFunctionMetricQueryDefinition' SLODeleteResponse: description: A response list of all service level objective deleted. properties: @@ -10287,6 +10294,20 @@ components: - THIRTY_DAYS - NINETY_DAYS - ALL + SLOFormula: + description: A formula that specifies how to combine the results of multiple + queries. + example: + formula: query1 - default_zero(query2) + properties: + formula: + description: The formula string, which is an expression involving named + queries. + example: query1 - default_zero(query2) + type: string + required: + - formula + type: object SLOHistoryMetrics: description: 'A `metric` based SLO history response. @@ -11016,6 +11037,8 @@ components: type: string query: $ref: '#/components/schemas/ServiceLevelObjectiveQuery' + sli_specification: + $ref: '#/components/schemas/SLOSliSpec' tags: description: 'A list of tags associated with this service level objective. @@ -11070,6 +11093,11 @@ components: format: double type: number type: object + SLOSliSpec: + description: A generic SLI specification. This is currently used for time-slice + SLOs only. + oneOf: + - $ref: '#/components/schemas/SLOTimeSliceSpec' SLOState: description: State of the SLO. enum: @@ -11170,6 +11198,106 @@ components: - timeframe - target type: object + SLOTimeSliceComparator: + description: The comparator used to compare the SLI value to the threshold. + enum: + - '>' + - '>=' + - < + - <= + example: '>' + type: string + x-enum-varnames: + - GREATER + - GREATER_EQUAL + - LESS + - LESS_EQUAL + SLOTimeSliceCondition: + description: 'The time-slice condition, composed of 3 parts: 1. the metric timeseries + query, 2. the comparator, + + and 3. the threshold.' + example: + comparator: < + query: + formulas: + - formula: query2/query1 + queries: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.errors{*} by {env}.as_count() + threshold: 5 + properties: + comparator: + $ref: '#/components/schemas/SLOTimeSliceComparator' + query: + $ref: '#/components/schemas/SLOTimeSliceQuery' + threshold: + description: The threshold value to which each SLI value will be compared. + example: 5 + format: double + type: number + required: + - comparator + - threshold + - query + type: object + SLOTimeSliceQuery: + description: The queries and formula used to calculate the SLI value. + example: + formulas: + - formula: query2/query1 + queries: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.errors{*} by {env}.as_count() + properties: + formulas: + description: A list that contains exactly one formula, as only a single + formula may be used in a time-slice SLO. + items: + $ref: '#/components/schemas/SLOFormula' + maxItems: 1 + minItems: 1 + type: array + queries: + description: A list of queries that are used to calculate the SLI value. + items: + $ref: '#/components/schemas/SLODataSourceQueryDefinition' + type: array + required: + - formulas + - queries + type: object + SLOTimeSliceSpec: + additionalProperties: false + description: A time-slice SLI specification. + example: + time_slice: + comparator: < + query: + formulas: + - formula: query2/query1 + queries: + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.hits{*} by {env}.as_count() + - data_source: metrics + name: query1 + query: sum:trace.servlet.request.errors{*} by {env}.as_count() + threshold: 5 + properties: + time_slice: + $ref: '#/components/schemas/SLOTimeSliceCondition' + required: + - time_slice + type: object SLOTimeframe: description: The SLO time window options. enum: @@ -11189,11 +11317,13 @@ components: enum: - metric - monitor + - time_slice example: metric type: string x-enum-varnames: - METRIC - MONITOR + - TIME_SLICE SLOTypeNumeric: description: 'A numeric representation of the type of the service level objective (`0` for @@ -11204,12 +11334,14 @@ components: enum: - 0 - 1 + - 2 example: 0 format: int32 type: integer x-enum-varnames: - MONITOR - METRIC + - TIME_SLICE SLOWidgetDefinition: description: Use the SLO and uptime widget to track your SLOs (Service Level Objectives) and uptime on screenboards and timeboards. @@ -12019,6 +12151,8 @@ components: type: string query: $ref: '#/components/schemas/ServiceLevelObjectiveQuery' + sli_specification: + $ref: '#/components/schemas/SLOSliSpec' tags: description: 'A list of tags associated with this service level objective. @@ -12148,6 +12282,8 @@ components: type: string query: $ref: '#/components/schemas/ServiceLevelObjectiveQuery' + sli_specification: + $ref: '#/components/schemas/SLOSliSpec' tags: description: 'A list of tags associated with this service level objective. diff --git a/api/datadogV1/model_service_level_objective.go b/api/datadogV1/model_service_level_objective.go index 74ef37ba4b9..af60fd447e9 100644 --- a/api/datadogV1/model_service_level_objective.go +++ b/api/datadogV1/model_service_level_objective.go @@ -54,6 +54,8 @@ type ServiceLevelObjective struct { // 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. + 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). // Optional in create/update requests. @@ -384,6 +386,34 @@ func (o *ServiceLevelObjective) SetQuery(v ServiceLevelObjectiveQuery) { o.Query = &v } +// GetSliSpecification returns the SliSpecification field value if set, zero value otherwise. +func (o *ServiceLevelObjective) GetSliSpecification() SLOSliSpec { + if o == nil || o.SliSpecification == nil { + var ret SLOSliSpec + return ret + } + return *o.SliSpecification +} + +// GetSliSpecificationOk returns a tuple with the SliSpecification field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ServiceLevelObjective) GetSliSpecificationOk() (*SLOSliSpec, bool) { + if o == nil || o.SliSpecification == nil { + return nil, false + } + return o.SliSpecification, true +} + +// HasSliSpecification returns a boolean if a field has been set. +func (o *ServiceLevelObjective) HasSliSpecification() bool { + return o != nil && o.SliSpecification != nil +} + +// SetSliSpecification gets a reference to the given SLOSliSpec and assigns it to the SliSpecification field. +func (o *ServiceLevelObjective) SetSliSpecification(v SLOSliSpec) { + o.SliSpecification = &v +} + // GetTags returns the Tags field value if set, zero value otherwise. func (o *ServiceLevelObjective) GetTags() []string { if o == nil || o.Tags == nil { @@ -576,6 +606,9 @@ func (o ServiceLevelObjective) MarshalJSON() ([]byte, error) { if o.Query != nil { toSerialize["query"] = o.Query } + if o.SliSpecification != nil { + toSerialize["sli_specification"] = o.SliSpecification + } if o.Tags != nil { toSerialize["tags"] = o.Tags } @@ -610,6 +643,7 @@ func (o *ServiceLevelObjective) UnmarshalJSON(bytes []byte) (err error) { MonitorTags []string `json:"monitor_tags,omitempty"` Name *string `json:"name"` Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` + SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` Tags []string `json:"tags,omitempty"` TargetThreshold *float64 `json:"target_threshold,omitempty"` Thresholds *[]SLOThreshold `json:"thresholds"` @@ -631,7 +665,7 @@ func (o *ServiceLevelObjective) UnmarshalJSON(bytes []byte) (err error) { } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"created_at", "creator", "description", "groups", "id", "modified_at", "monitor_ids", "monitor_tags", "name", "query", "tags", "target_threshold", "thresholds", "timeframe", "type", "warning_threshold"}) + datadog.DeleteKeys(additionalProperties, &[]string{"created_at", "creator", "description", "groups", "id", "modified_at", "monitor_ids", "monitor_tags", "name", "query", "sli_specification", "tags", "target_threshold", "thresholds", "timeframe", "type", "warning_threshold"}) } else { return err } @@ -653,6 +687,7 @@ func (o *ServiceLevelObjective) UnmarshalJSON(bytes []byte) (err error) { hasInvalidField = true } o.Query = all.Query + o.SliSpecification = all.SliSpecification o.Tags = all.Tags o.TargetThreshold = all.TargetThreshold o.Thresholds = *all.Thresholds diff --git a/api/datadogV1/model_service_level_objective_request.go b/api/datadogV1/model_service_level_objective_request.go index f4d36908148..f5fbf5f30ee 100644 --- a/api/datadogV1/model_service_level_objective_request.go +++ b/api/datadogV1/model_service_level_objective_request.go @@ -33,6 +33,8 @@ type ServiceLevelObjectiveRequest struct { // 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. + 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). // Optional in create/update requests. @@ -223,6 +225,34 @@ func (o *ServiceLevelObjectiveRequest) SetQuery(v ServiceLevelObjectiveQuery) { o.Query = &v } +// GetSliSpecification returns the SliSpecification field value if set, zero value otherwise. +func (o *ServiceLevelObjectiveRequest) GetSliSpecification() SLOSliSpec { + if o == nil || o.SliSpecification == nil { + var ret SLOSliSpec + return ret + } + return *o.SliSpecification +} + +// GetSliSpecificationOk returns a tuple with the SliSpecification field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *ServiceLevelObjectiveRequest) GetSliSpecificationOk() (*SLOSliSpec, bool) { + if o == nil || o.SliSpecification == nil { + return nil, false + } + return o.SliSpecification, true +} + +// HasSliSpecification returns a boolean if a field has been set. +func (o *ServiceLevelObjectiveRequest) HasSliSpecification() bool { + return o != nil && o.SliSpecification != nil +} + +// SetSliSpecification gets a reference to the given SLOSliSpec and assigns it to the SliSpecification field. +func (o *ServiceLevelObjectiveRequest) SetSliSpecification(v SLOSliSpec) { + o.SliSpecification = &v +} + // GetTags returns the Tags field value if set, zero value otherwise. func (o *ServiceLevelObjectiveRequest) GetTags() []string { if o == nil || o.Tags == nil { @@ -400,6 +430,9 @@ func (o ServiceLevelObjectiveRequest) MarshalJSON() ([]byte, error) { if o.Query != nil { toSerialize["query"] = o.Query } + if o.SliSpecification != nil { + toSerialize["sli_specification"] = o.SliSpecification + } if o.Tags != nil { toSerialize["tags"] = o.Tags } @@ -429,6 +462,7 @@ func (o *ServiceLevelObjectiveRequest) UnmarshalJSON(bytes []byte) (err error) { MonitorIds []int64 `json:"monitor_ids,omitempty"` Name *string `json:"name"` Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` + SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` Tags []string `json:"tags,omitempty"` TargetThreshold *float64 `json:"target_threshold,omitempty"` Thresholds *[]SLOThreshold `json:"thresholds"` @@ -450,7 +484,7 @@ func (o *ServiceLevelObjectiveRequest) UnmarshalJSON(bytes []byte) (err error) { } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"description", "groups", "monitor_ids", "name", "query", "tags", "target_threshold", "thresholds", "timeframe", "type", "warning_threshold"}) + datadog.DeleteKeys(additionalProperties, &[]string{"description", "groups", "monitor_ids", "name", "query", "sli_specification", "tags", "target_threshold", "thresholds", "timeframe", "type", "warning_threshold"}) } else { return err } @@ -464,6 +498,7 @@ func (o *ServiceLevelObjectiveRequest) UnmarshalJSON(bytes []byte) (err error) { hasInvalidField = true } o.Query = all.Query + o.SliSpecification = all.SliSpecification o.Tags = all.Tags o.TargetThreshold = all.TargetThreshold o.Thresholds = *all.Thresholds diff --git a/api/datadogV1/model_slo_data_source_query_definition.go b/api/datadogV1/model_slo_data_source_query_definition.go new file mode 100644 index 00000000000..f31f066a551 --- /dev/null +++ b/api/datadogV1/model_slo_data_source_query_definition.go @@ -0,0 +1,73 @@ +// 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 ( + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// SLODataSourceQueryDefinition - A formula and function query. +type SLODataSourceQueryDefinition struct { + FormulaAndFunctionMetricQueryDefinition *FormulaAndFunctionMetricQueryDefinition + + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject interface{} +} + +// FormulaAndFunctionMetricQueryDefinitionAsSLODataSourceQueryDefinition is a convenience function that returns FormulaAndFunctionMetricQueryDefinition wrapped in SLODataSourceQueryDefinition. +func FormulaAndFunctionMetricQueryDefinitionAsSLODataSourceQueryDefinition(v *FormulaAndFunctionMetricQueryDefinition) SLODataSourceQueryDefinition { + return SLODataSourceQueryDefinition{FormulaAndFunctionMetricQueryDefinition: v} +} + +// UnmarshalJSON turns data into one of the pointers in the struct. +func (obj *SLODataSourceQueryDefinition) UnmarshalJSON(data []byte) error { + var err error + match := 0 + // try to unmarshal data into FormulaAndFunctionMetricQueryDefinition + err = datadog.Unmarshal(data, &obj.FormulaAndFunctionMetricQueryDefinition) + if err == nil { + if obj.FormulaAndFunctionMetricQueryDefinition != nil && obj.FormulaAndFunctionMetricQueryDefinition.UnparsedObject == nil { + jsonFormulaAndFunctionMetricQueryDefinition, _ := datadog.Marshal(obj.FormulaAndFunctionMetricQueryDefinition) + if string(jsonFormulaAndFunctionMetricQueryDefinition) == "{}" { // empty struct + obj.FormulaAndFunctionMetricQueryDefinition = nil + } else { + match++ + } + } else { + obj.FormulaAndFunctionMetricQueryDefinition = nil + } + } else { + obj.FormulaAndFunctionMetricQueryDefinition = nil + } + + if match != 1 { // more than 1 match + // reset to nil + obj.FormulaAndFunctionMetricQueryDefinition = nil + return datadog.Unmarshal(data, &obj.UnparsedObject) + } + return nil // exactly one match +} + +// MarshalJSON turns data from the first non-nil pointers in the struct to JSON. +func (obj SLODataSourceQueryDefinition) MarshalJSON() ([]byte, error) { + if obj.FormulaAndFunctionMetricQueryDefinition != nil { + return datadog.Marshal(&obj.FormulaAndFunctionMetricQueryDefinition) + } + + if obj.UnparsedObject != nil { + return datadog.Marshal(obj.UnparsedObject) + } + return nil, nil // no data in oneOf schemas +} + +// GetActualInstance returns the actual instance. +func (obj *SLODataSourceQueryDefinition) GetActualInstance() interface{} { + if obj.FormulaAndFunctionMetricQueryDefinition != nil { + return obj.FormulaAndFunctionMetricQueryDefinition + } + + // all schemas are nil + return nil +} diff --git a/api/datadogV1/model_slo_formula.go b/api/datadogV1/model_slo_formula.go new file mode 100644 index 00000000000..5ebbd480000 --- /dev/null +++ b/api/datadogV1/model_slo_formula.go @@ -0,0 +1,101 @@ +// 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" +) + +// SLOFormula A formula that specifies how to combine the results of multiple queries. +type SLOFormula struct { + // The formula string, which is an expression involving named queries. + Formula string `json:"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{} +} + +// NewSLOFormula instantiates a new SLOFormula 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 NewSLOFormula(formula string) *SLOFormula { + this := SLOFormula{} + this.Formula = formula + return &this +} + +// NewSLOFormulaWithDefaults instantiates a new SLOFormula 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 NewSLOFormulaWithDefaults() *SLOFormula { + this := SLOFormula{} + return &this +} + +// GetFormula returns the Formula field value. +func (o *SLOFormula) GetFormula() string { + if o == nil { + var ret string + return ret + } + return o.Formula +} + +// GetFormulaOk returns a tuple with the Formula field value +// and a boolean to check if the value has been set. +func (o *SLOFormula) GetFormulaOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Formula, true +} + +// SetFormula sets field value. +func (o *SLOFormula) SetFormula(v string) { + o.Formula = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOFormula) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["formula"] = o.Formula + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOFormula) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + Formula *string `json:"formula"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.Formula == nil { + return fmt.Errorf("required field formula missing") + } + additionalProperties := make(map[string]interface{}) + if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { + datadog.DeleteKeys(additionalProperties, &[]string{"formula"}) + } else { + return err + } + o.Formula = *all.Formula + + if len(additionalProperties) > 0 { + o.AdditionalProperties = additionalProperties + } + + return nil +} diff --git a/api/datadogV1/model_slo_response_data.go b/api/datadogV1/model_slo_response_data.go index 10d79227017..7c340d4c1ee 100644 --- a/api/datadogV1/model_slo_response_data.go +++ b/api/datadogV1/model_slo_response_data.go @@ -54,6 +54,8 @@ type SLOResponseData struct { // 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. + 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). // Optional in create/update requests. @@ -414,6 +416,34 @@ func (o *SLOResponseData) SetQuery(v ServiceLevelObjectiveQuery) { o.Query = &v } +// GetSliSpecification returns the SliSpecification field value if set, zero value otherwise. +func (o *SLOResponseData) GetSliSpecification() SLOSliSpec { + if o == nil || o.SliSpecification == nil { + var ret SLOSliSpec + return ret + } + return *o.SliSpecification +} + +// GetSliSpecificationOk returns a tuple with the SliSpecification field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *SLOResponseData) GetSliSpecificationOk() (*SLOSliSpec, bool) { + if o == nil || o.SliSpecification == nil { + return nil, false + } + return o.SliSpecification, true +} + +// HasSliSpecification returns a boolean if a field has been set. +func (o *SLOResponseData) HasSliSpecification() bool { + return o != nil && o.SliSpecification != nil +} + +// SetSliSpecification gets a reference to the given SLOSliSpec and assigns it to the SliSpecification field. +func (o *SLOResponseData) SetSliSpecification(v SLOSliSpec) { + o.SliSpecification = &v +} + // GetTags returns the Tags field value if set, zero value otherwise. func (o *SLOResponseData) GetTags() []string { if o == nil || o.Tags == nil { @@ -621,6 +651,9 @@ func (o SLOResponseData) MarshalJSON() ([]byte, error) { if o.Query != nil { toSerialize["query"] = o.Query } + if o.SliSpecification != nil { + toSerialize["sli_specification"] = o.SliSpecification + } if o.Tags != nil { toSerialize["tags"] = o.Tags } @@ -660,6 +693,7 @@ func (o *SLOResponseData) UnmarshalJSON(bytes []byte) (err error) { MonitorTags []string `json:"monitor_tags,omitempty"` Name *string `json:"name,omitempty"` Query *ServiceLevelObjectiveQuery `json:"query,omitempty"` + SliSpecification *SLOSliSpec `json:"sli_specification,omitempty"` Tags []string `json:"tags,omitempty"` TargetThreshold *float64 `json:"target_threshold,omitempty"` Thresholds []SLOThreshold `json:"thresholds,omitempty"` @@ -672,7 +706,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", "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", "type", "warning_threshold"}) } else { return err } @@ -695,6 +729,7 @@ func (o *SLOResponseData) UnmarshalJSON(bytes []byte) (err error) { hasInvalidField = true } o.Query = all.Query + o.SliSpecification = all.SliSpecification o.Tags = all.Tags o.TargetThreshold = all.TargetThreshold o.Thresholds = all.Thresholds diff --git a/api/datadogV1/model_slo_sli_spec.go b/api/datadogV1/model_slo_sli_spec.go new file mode 100644 index 00000000000..17873580fc8 --- /dev/null +++ b/api/datadogV1/model_slo_sli_spec.go @@ -0,0 +1,73 @@ +// 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 ( + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// SLOSliSpec - A generic SLI specification. This is currently used for time-slice SLOs only. +type SLOSliSpec struct { + SLOTimeSliceSpec *SLOTimeSliceSpec + + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject interface{} +} + +// SLOTimeSliceSpecAsSLOSliSpec is a convenience function that returns SLOTimeSliceSpec wrapped in SLOSliSpec. +func SLOTimeSliceSpecAsSLOSliSpec(v *SLOTimeSliceSpec) SLOSliSpec { + return SLOSliSpec{SLOTimeSliceSpec: v} +} + +// UnmarshalJSON turns data into one of the pointers in the struct. +func (obj *SLOSliSpec) UnmarshalJSON(data []byte) error { + var err error + match := 0 + // try to unmarshal data into SLOTimeSliceSpec + err = datadog.Unmarshal(data, &obj.SLOTimeSliceSpec) + if err == nil { + if obj.SLOTimeSliceSpec != nil && obj.SLOTimeSliceSpec.UnparsedObject == nil { + jsonSLOTimeSliceSpec, _ := datadog.Marshal(obj.SLOTimeSliceSpec) + if string(jsonSLOTimeSliceSpec) == "{}" { // empty struct + obj.SLOTimeSliceSpec = nil + } else { + match++ + } + } else { + obj.SLOTimeSliceSpec = nil + } + } else { + obj.SLOTimeSliceSpec = nil + } + + if match != 1 { // more than 1 match + // reset to nil + obj.SLOTimeSliceSpec = nil + return datadog.Unmarshal(data, &obj.UnparsedObject) + } + return nil // exactly one match +} + +// MarshalJSON turns data from the first non-nil pointers in the struct to JSON. +func (obj SLOSliSpec) MarshalJSON() ([]byte, error) { + if obj.SLOTimeSliceSpec != nil { + return datadog.Marshal(&obj.SLOTimeSliceSpec) + } + + if obj.UnparsedObject != nil { + return datadog.Marshal(obj.UnparsedObject) + } + return nil, nil // no data in oneOf schemas +} + +// GetActualInstance returns the actual instance. +func (obj *SLOSliSpec) GetActualInstance() interface{} { + if obj.SLOTimeSliceSpec != nil { + return obj.SLOTimeSliceSpec + } + + // all schemas are nil + return nil +} diff --git a/api/datadogV1/model_slo_time_slice_comparator.go b/api/datadogV1/model_slo_time_slice_comparator.go new file mode 100644 index 00000000000..c5824fbb8c8 --- /dev/null +++ b/api/datadogV1/model_slo_time_slice_comparator.go @@ -0,0 +1,70 @@ +// 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" +) + +// SLOTimeSliceComparator The comparator used to compare the SLI value to the threshold. +type SLOTimeSliceComparator string + +// List of SLOTimeSliceComparator. +const ( + SLOTIMESLICECOMPARATOR_GREATER SLOTimeSliceComparator = ">" + SLOTIMESLICECOMPARATOR_GREATER_EQUAL SLOTimeSliceComparator = ">=" + SLOTIMESLICECOMPARATOR_LESS SLOTimeSliceComparator = "<" + SLOTIMESLICECOMPARATOR_LESS_EQUAL SLOTimeSliceComparator = "<=" +) + +var allowedSLOTimeSliceComparatorEnumValues = []SLOTimeSliceComparator{ + SLOTIMESLICECOMPARATOR_GREATER, + SLOTIMESLICECOMPARATOR_GREATER_EQUAL, + SLOTIMESLICECOMPARATOR_LESS, + SLOTIMESLICECOMPARATOR_LESS_EQUAL, +} + +// GetAllowedValues reeturns the list of possible values. +func (v *SLOTimeSliceComparator) GetAllowedValues() []SLOTimeSliceComparator { + return allowedSLOTimeSliceComparatorEnumValues +} + +// UnmarshalJSON deserializes the given payload. +func (v *SLOTimeSliceComparator) UnmarshalJSON(src []byte) error { + var value string + err := datadog.Unmarshal(src, &value) + if err != nil { + return err + } + *v = SLOTimeSliceComparator(value) + return nil +} + +// NewSLOTimeSliceComparatorFromValue returns a pointer to a valid SLOTimeSliceComparator +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func NewSLOTimeSliceComparatorFromValue(v string) (*SLOTimeSliceComparator, error) { + ev := SLOTimeSliceComparator(v) + if ev.IsValid() { + return &ev, nil + } + return nil, fmt.Errorf("invalid value '%v' for SLOTimeSliceComparator: valid values are %v", v, allowedSLOTimeSliceComparatorEnumValues) +} + +// IsValid return true if the value is valid for the enum, false otherwise. +func (v SLOTimeSliceComparator) IsValid() bool { + for _, existing := range allowedSLOTimeSliceComparatorEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to SLOTimeSliceComparator value. +func (v SLOTimeSliceComparator) Ptr() *SLOTimeSliceComparator { + return &v +} diff --git a/api/datadogV1/model_slo_time_slice_condition.go b/api/datadogV1/model_slo_time_slice_condition.go new file mode 100644 index 00000000000..ab7017b5c97 --- /dev/null +++ b/api/datadogV1/model_slo_time_slice_condition.go @@ -0,0 +1,179 @@ +// 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" +) + +// SLOTimeSliceCondition The time-slice condition, composed of 3 parts: 1. the metric timeseries query, 2. the comparator, +// and 3. the threshold. +type SLOTimeSliceCondition struct { + // The comparator used to compare the SLI value to the threshold. + Comparator SLOTimeSliceComparator `json:"comparator"` + // The queries and formula used to calculate the SLI value. + Query SLOTimeSliceQuery `json:"query"` + // The threshold value to which each SLI value will be compared. + Threshold float64 `json:"threshold"` + // 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{} +} + +// NewSLOTimeSliceCondition instantiates a new SLOTimeSliceCondition 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 NewSLOTimeSliceCondition(comparator SLOTimeSliceComparator, query SLOTimeSliceQuery, threshold float64) *SLOTimeSliceCondition { + this := SLOTimeSliceCondition{} + this.Comparator = comparator + this.Query = query + this.Threshold = threshold + return &this +} + +// NewSLOTimeSliceConditionWithDefaults instantiates a new SLOTimeSliceCondition 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 NewSLOTimeSliceConditionWithDefaults() *SLOTimeSliceCondition { + this := SLOTimeSliceCondition{} + return &this +} + +// GetComparator returns the Comparator field value. +func (o *SLOTimeSliceCondition) GetComparator() SLOTimeSliceComparator { + if o == nil { + var ret SLOTimeSliceComparator + return ret + } + return o.Comparator +} + +// GetComparatorOk returns a tuple with the Comparator field value +// and a boolean to check if the value has been set. +func (o *SLOTimeSliceCondition) GetComparatorOk() (*SLOTimeSliceComparator, bool) { + if o == nil { + return nil, false + } + return &o.Comparator, true +} + +// SetComparator sets field value. +func (o *SLOTimeSliceCondition) SetComparator(v SLOTimeSliceComparator) { + o.Comparator = v +} + +// GetQuery returns the Query field value. +func (o *SLOTimeSliceCondition) GetQuery() SLOTimeSliceQuery { + if o == nil { + var ret SLOTimeSliceQuery + return ret + } + return o.Query +} + +// GetQueryOk returns a tuple with the Query field value +// and a boolean to check if the value has been set. +func (o *SLOTimeSliceCondition) GetQueryOk() (*SLOTimeSliceQuery, bool) { + if o == nil { + return nil, false + } + return &o.Query, true +} + +// SetQuery sets field value. +func (o *SLOTimeSliceCondition) SetQuery(v SLOTimeSliceQuery) { + o.Query = v +} + +// GetThreshold returns the Threshold field value. +func (o *SLOTimeSliceCondition) GetThreshold() float64 { + if o == nil { + var ret float64 + return ret + } + return o.Threshold +} + +// GetThresholdOk returns a tuple with the Threshold field value +// and a boolean to check if the value has been set. +func (o *SLOTimeSliceCondition) GetThresholdOk() (*float64, bool) { + if o == nil { + return nil, false + } + return &o.Threshold, true +} + +// SetThreshold sets field value. +func (o *SLOTimeSliceCondition) SetThreshold(v float64) { + o.Threshold = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOTimeSliceCondition) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["comparator"] = o.Comparator + toSerialize["query"] = o.Query + toSerialize["threshold"] = o.Threshold + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOTimeSliceCondition) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + Comparator *SLOTimeSliceComparator `json:"comparator"` + Query *SLOTimeSliceQuery `json:"query"` + Threshold *float64 `json:"threshold"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.Comparator == nil { + return fmt.Errorf("required field comparator missing") + } + if all.Query == nil { + return fmt.Errorf("required field query missing") + } + if all.Threshold == nil { + return fmt.Errorf("required field threshold missing") + } + additionalProperties := make(map[string]interface{}) + if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { + datadog.DeleteKeys(additionalProperties, &[]string{"comparator", "query", "threshold"}) + } else { + return err + } + + hasInvalidField := false + if !all.Comparator.IsValid() { + hasInvalidField = true + } else { + o.Comparator = *all.Comparator + } + if all.Query.UnparsedObject != nil && o.UnparsedObject == nil { + hasInvalidField = true + } + o.Query = *all.Query + o.Threshold = *all.Threshold + + if len(additionalProperties) > 0 { + o.AdditionalProperties = additionalProperties + } + + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + + return nil +} diff --git a/api/datadogV1/model_slo_time_slice_query.go b/api/datadogV1/model_slo_time_slice_query.go new file mode 100644 index 00000000000..0e66799481b --- /dev/null +++ b/api/datadogV1/model_slo_time_slice_query.go @@ -0,0 +1,133 @@ +// 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" +) + +// SLOTimeSliceQuery The queries and formula used to calculate the SLI value. +type SLOTimeSliceQuery struct { + // A list that contains exactly one formula, as only a single formula may be used in a time-slice SLO. + Formulas []SLOFormula `json:"formulas"` + // A list of queries that are used to calculate the SLI value. + Queries []SLODataSourceQueryDefinition `json:"queries"` + // 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{} +} + +// NewSLOTimeSliceQuery instantiates a new SLOTimeSliceQuery 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 NewSLOTimeSliceQuery(formulas []SLOFormula, queries []SLODataSourceQueryDefinition) *SLOTimeSliceQuery { + this := SLOTimeSliceQuery{} + this.Formulas = formulas + this.Queries = queries + return &this +} + +// NewSLOTimeSliceQueryWithDefaults instantiates a new SLOTimeSliceQuery 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 NewSLOTimeSliceQueryWithDefaults() *SLOTimeSliceQuery { + this := SLOTimeSliceQuery{} + return &this +} + +// GetFormulas returns the Formulas field value. +func (o *SLOTimeSliceQuery) GetFormulas() []SLOFormula { + if o == nil { + var ret []SLOFormula + return ret + } + return o.Formulas +} + +// GetFormulasOk returns a tuple with the Formulas field value +// and a boolean to check if the value has been set. +func (o *SLOTimeSliceQuery) GetFormulasOk() (*[]SLOFormula, bool) { + if o == nil { + return nil, false + } + return &o.Formulas, true +} + +// SetFormulas sets field value. +func (o *SLOTimeSliceQuery) SetFormulas(v []SLOFormula) { + o.Formulas = v +} + +// GetQueries returns the Queries field value. +func (o *SLOTimeSliceQuery) 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 *SLOTimeSliceQuery) GetQueriesOk() (*[]SLODataSourceQueryDefinition, bool) { + if o == nil { + return nil, false + } + return &o.Queries, true +} + +// SetQueries sets field value. +func (o *SLOTimeSliceQuery) SetQueries(v []SLODataSourceQueryDefinition) { + o.Queries = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOTimeSliceQuery) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["formulas"] = o.Formulas + toSerialize["queries"] = o.Queries + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOTimeSliceQuery) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + Formulas *[]SLOFormula `json:"formulas"` + Queries *[]SLODataSourceQueryDefinition `json:"queries"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.Formulas == nil { + return fmt.Errorf("required field formulas missing") + } + if all.Queries == nil { + return fmt.Errorf("required field queries missing") + } + additionalProperties := make(map[string]interface{}) + if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { + datadog.DeleteKeys(additionalProperties, &[]string{"formulas", "queries"}) + } else { + return err + } + o.Formulas = *all.Formulas + o.Queries = *all.Queries + + if len(additionalProperties) > 0 { + o.AdditionalProperties = additionalProperties + } + + return nil +} diff --git a/api/datadogV1/model_slo_time_slice_spec.go b/api/datadogV1/model_slo_time_slice_spec.go new file mode 100644 index 00000000000..341d8b1e4d5 --- /dev/null +++ b/api/datadogV1/model_slo_time_slice_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" +) + +// SLOTimeSliceSpec A time-slice SLI specification. +type SLOTimeSliceSpec struct { + // The time-slice condition, composed of 3 parts: 1. the metric timeseries query, 2. the comparator, + // and 3. the threshold. + TimeSlice SLOTimeSliceCondition `json:"time_slice"` + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject map[string]interface{} `json:"-"` +} + +// NewSLOTimeSliceSpec instantiates a new SLOTimeSliceSpec 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 NewSLOTimeSliceSpec(timeSlice SLOTimeSliceCondition) *SLOTimeSliceSpec { + this := SLOTimeSliceSpec{} + this.TimeSlice = timeSlice + return &this +} + +// NewSLOTimeSliceSpecWithDefaults instantiates a new SLOTimeSliceSpec 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 NewSLOTimeSliceSpecWithDefaults() *SLOTimeSliceSpec { + this := SLOTimeSliceSpec{} + return &this +} + +// GetTimeSlice returns the TimeSlice field value. +func (o *SLOTimeSliceSpec) GetTimeSlice() SLOTimeSliceCondition { + if o == nil { + var ret SLOTimeSliceCondition + return ret + } + return o.TimeSlice +} + +// GetTimeSliceOk returns a tuple with the TimeSlice field value +// and a boolean to check if the value has been set. +func (o *SLOTimeSliceSpec) GetTimeSliceOk() (*SLOTimeSliceCondition, bool) { + if o == nil { + return nil, false + } + return &o.TimeSlice, true +} + +// SetTimeSlice sets field value. +func (o *SLOTimeSliceSpec) SetTimeSlice(v SLOTimeSliceCondition) { + o.TimeSlice = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o SLOTimeSliceSpec) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["time_slice"] = o.TimeSlice + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *SLOTimeSliceSpec) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + TimeSlice *SLOTimeSliceCondition `json:"time_slice"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.TimeSlice == nil { + return fmt.Errorf("required field time_slice missing") + } + + hasInvalidField := false + if all.TimeSlice.UnparsedObject != nil && o.UnparsedObject == nil { + hasInvalidField = true + } + o.TimeSlice = *all.TimeSlice + + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + + return nil +} diff --git a/api/datadogV1/model_slo_type.go b/api/datadogV1/model_slo_type.go index ef8bfd6679f..4221377f538 100644 --- a/api/datadogV1/model_slo_type.go +++ b/api/datadogV1/model_slo_type.go @@ -15,13 +15,15 @@ type SLOType string // List of SLOType. const ( - SLOTYPE_METRIC SLOType = "metric" - SLOTYPE_MONITOR SLOType = "monitor" + SLOTYPE_METRIC SLOType = "metric" + SLOTYPE_MONITOR SLOType = "monitor" + SLOTYPE_TIME_SLICE SLOType = "time_slice" ) var allowedSLOTypeEnumValues = []SLOType{ SLOTYPE_METRIC, SLOTYPE_MONITOR, + SLOTYPE_TIME_SLICE, } // GetAllowedValues reeturns the list of possible values. diff --git a/api/datadogV1/model_slo_type_numeric.go b/api/datadogV1/model_slo_type_numeric.go index 3903a90ceb8..831807fa9ea 100644 --- a/api/datadogV1/model_slo_type_numeric.go +++ b/api/datadogV1/model_slo_type_numeric.go @@ -17,13 +17,15 @@ type SLOTypeNumeric int32 // List of SLOTypeNumeric. const ( - SLOTYPENUMERIC_MONITOR SLOTypeNumeric = 0 - SLOTYPENUMERIC_METRIC SLOTypeNumeric = 1 + SLOTYPENUMERIC_MONITOR SLOTypeNumeric = 0 + SLOTYPENUMERIC_METRIC SLOTypeNumeric = 1 + SLOTYPENUMERIC_TIME_SLICE SLOTypeNumeric = 2 ) var allowedSLOTypeNumericEnumValues = []SLOTypeNumeric{ SLOTYPENUMERIC_MONITOR, SLOTYPENUMERIC_METRIC, + SLOTYPENUMERIC_TIME_SLICE, } // GetAllowedValues reeturns the list of possible values. diff --git a/examples/v1/service-level-objectives/CreateSLO_3765703239.go b/examples/v1/service-level-objectives/CreateSLO_3765703239.go new file mode 100644 index 00000000000..28e22fc912c --- /dev/null +++ b/examples/v1/service-level-objectives/CreateSLO_3765703239.go @@ -0,0 +1,71 @@ +// Create a time-slice SLO object 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_TIME_SLICE, + Description: *datadog.NewNullableString(datadog.PtrString("string")), + Name: "Example-Service-Level-Objective", + SliSpecification: &datadogV1.SLOSliSpec{ + SLOTimeSliceSpec: &datadogV1.SLOTimeSliceSpec{ + TimeSlice: datadogV1.SLOTimeSliceCondition{ + Query: datadogV1.SLOTimeSliceQuery{ + Formulas: []datadogV1.SLOFormula{ + { + Formula: "query1", + }, + }, + Queries: []datadogV1.SLODataSourceQueryDefinition{ + datadogV1.SLODataSourceQueryDefinition{ + FormulaAndFunctionMetricQueryDefinition: &datadogV1.FormulaAndFunctionMetricQueryDefinition{ + DataSource: datadogV1.FORMULAANDFUNCTIONMETRICDATASOURCE_METRICS, + Name: "query1", + Query: "trace.servlet.request{env:prod}", + }}, + }, + }, + Comparator: datadogV1.SLOTIMESLICECOMPARATOR_GREATER, + Threshold: 5, + }, + }}, + Tags: []string{ + "env:prod", + }, + Thresholds: []datadogV1.SLOThreshold{ + { + Target: 97.0, + TargetDisplay: datadog.PtrString("97.0"), + Timeframe: datadogV1.SLOTIMEFRAME_SEVEN_DAYS, + Warning: datadog.PtrFloat64(98), + WarningDisplay: datadog.PtrString("98.0"), + }, + }, + Timeframe: datadogV1.SLOTIMEFRAME_SEVEN_DAYS.Ptr(), + TargetThreshold: datadog.PtrFloat64(97.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/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.freeze new file mode 100644 index 00000000000..0d30f468148 --- /dev/null +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.freeze @@ -0,0 +1 @@ +2024-01-03T22:54:44.816Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.yaml new file mode 100644 index 00000000000..db315206894 --- /dev/null +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_a_time-slice_SLO_object_returns_OK_response.yaml @@ -0,0 +1,41 @@ +interactions: +- request: + body: | + {"description":"string","name":"Test-Create_a_time_slice_SLO_object_returns_OK_response-1704322484","sli_specification":{"time_slice":{"comparator":"\u003e","query":{"formulas":[{"formula":"query1"}],"queries":[{"data_source":"metrics","name":"query1","query":"trace.servlet.request{env:prod}"}]},"threshold":5}},"tags":["env:prod"],"target_threshold":97,"thresholds":[{"target":97,"target_display":"97.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","type":"time_slice","warning_threshold":98} + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + method: POST + url: https://api.datadoghq.com/api/v1/slo + response: + body: '{"data":[{"id":"776b80141eda520bbfae33e897849f61","name":"Test-Create_a_time_slice_SLO_object_returns_OK_response-1704322484","tags":["env:prod"],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":97.0,"target_display":"97.","warning":98.0,"warning_display":"98."}],"type":"time_slice","type_id":2,"description":"string","timeframe":"7d","warning_threshold":98,"target_threshold":97,"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322485,"modified_at":1704322485,"sli_specification":{"time_slice":{"comparator":">","query":{"formulas":[{"formula":"query1"}],"queries":[{"data_source":"metrics","name":"query1","query":"trace.servlet.request{env:prod}"}]},"threshold":5,"query_interval_seconds":300}}}],"error":null} + + ' + code: 200 + duration: '' + headers: + Content-Type: + - application/json + status: 200 OK +- request: + body: '' + form: {} + headers: + Accept: + - application/json + method: DELETE + url: https://api.datadoghq.com/api/v1/slo/776b80141eda520bbfae33e897849f61 + response: + body: '{"data":["776b80141eda520bbfae33e897849f61"],"error":null} + + ' + code: 200 + duration: '' + headers: + Content-Type: + - application/json + status: 200 OK +version: 1 diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.freeze index 04ad7cb7428..931d2be7c21 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.freeze @@ -1 +1 @@ -2022-01-06T00:51:10.351Z \ No newline at end of file +2024-01-03T22:54:45.312Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.yaml index 4f10c8d6664..2fbc3c2098c 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_Bad_Request_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Create_an_SLO_object_returns_Bad_Request_response-1641430270","thresholds":[{"target":95,"target_display":"95.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"type":"monitor"} + {"name":"Test-Create_an_SLO_object_returns_Bad_Request_response-1704322485","thresholds":[{"target":95,"target_display":"95.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"type":"monitor"} form: {} headers: Accept: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.freeze index c04d9ebdbc4..4c19057022f 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.freeze @@ -1 +1 @@ -2023-01-26T10:51:10.970Z \ No newline at end of file +2024-01-03T22:54:45.425Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.yaml index 2fa30979d22..65c23acadc4 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Create_an_SLO_object_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"description":"string","groups":["env:test","role:mysql"],"monitor_ids":[],"name":"Test-Create_an_SLO_object_returns_OK_response-1674730270","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"tags":["env:prod","app:core"],"target_threshold":97,"thresholds":[{"target":97,"target_display":"97.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","type":"metric","warning_threshold":98} + {"description":"string","groups":["env:test","role:mysql"],"monitor_ids":[],"name":"Test-Create_an_SLO_object_returns_OK_response-1704322485","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"tags":["env:prod","app:core"],"target_threshold":97,"thresholds":[{"target":97,"target_display":"97.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","type":"metric","warning_threshold":98} form: {} headers: Accept: @@ -11,7 +11,7 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"id":"fbad7e9ce0aa5a32aa14224b91c699c6","name":"Test-Create_an_SLO_object_returns_OK_response-1674730270","tags":["env:prod","app:core"],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":97.0,"target_display":"97.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"string","timeframe":"7d","warning_threshold":98,"target_threshold":97,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1674730271,"modified_at":1674730271,"groups":["env:test","role:mysql"]}],"error":null} + body: '{"data":[{"id":"6a3ffb99fc285f4f947ccf83d888558b","name":"Test-Create_an_SLO_object_returns_OK_response-1704322485","tags":["app:core","env:prod"],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":97.0,"target_display":"97.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"string","timeframe":"7d","warning_threshold":98,"target_threshold":97,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322485,"modified_at":1704322485,"groups":["env:test","role:mysql"]}],"error":null} ' code: 200 @@ -27,9 +27,9 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/fbad7e9ce0aa5a32aa14224b91c699c6 + url: https://api.datadoghq.com/api/v1/slo/6a3ffb99fc285f4f947ccf83d888558b response: - body: '{"data":["fbad7e9ce0aa5a32aa14224b91c699c6"],"error":null} + body: '{"data":["6a3ffb99fc285f4f947ccf83d888558b"],"error":null} ' code: 200 diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.freeze index f99e15030d0..b861a89a733 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.freeze @@ -1 +1 @@ -2022-01-06T00:51:10.974Z \ No newline at end of file +2024-01-03T22:54:45.952Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.yaml index b892bb694cb..d64abb7dabc 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_Not_found_response.yaml @@ -6,9 +6,9 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/testdeleteansloreturnsnotfoundresponse1641430270 + url: https://api.datadoghq.com/api/v1/slo/testdeleteansloreturnsnotfoundresponse1704322485 response: - body: '{"errors":["SLO not found: testdeleteansloreturnsnotfoundresponse1641430270 + body: '{"errors":["SLO not found: testdeleteansloreturnsnotfoundresponse1704322485 not found"]}' code: 404 duration: '' diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.freeze index f998a181ae1..84e1b4e4448 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.freeze @@ -1 +1 @@ -2022-01-06T00:51:11.158Z \ No newline at end of file +2024-01-03T22:54:46.108Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.yaml index 0b056f2300a..7ab2ba50947 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Delete_an_SLO_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Delete_an_SLO_returns_OK_response-1641430271","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Delete_an_SLO_returns_OK_response-1704322486","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98,"warning_display":"98.","target":95,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"7c7a8700d1125ac99aa0ffa12f686b89","name":"Test-Delete_an_SLO_returns_OK_response-1641430271","created_at":1641430271,"tags":[],"modified_at":1641430271,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"6065f42541b856f3abaf255e6a61de79","name":"Test-Delete_an_SLO_returns_OK_response-1704322486","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322486,"modified_at":1704322486}],"error":null} + + ' code: 200 duration: '' headers: @@ -25,9 +27,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/7c7a8700d1125ac99aa0ffa12f686b89 + url: https://api.datadoghq.com/api/v1/slo/6065f42541b856f3abaf255e6a61de79 response: - body: '{"data":["7c7a8700d1125ac99aa0ffa12f686b89"],"error":null}' + body: '{"data":["6065f42541b856f3abaf255e6a61de79"],"error":null} + + ' code: 200 duration: '' headers: @@ -41,9 +45,9 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/7c7a8700d1125ac99aa0ffa12f686b89 + url: https://api.datadoghq.com/api/v1/slo/6065f42541b856f3abaf255e6a61de79 response: - body: '{"errors":["SLO not found: 7c7a8700d1125ac99aa0ffa12f686b89 not found"]}' + body: '{"errors":["SLO not found: 6065f42541b856f3abaf255e6a61de79 not found"]}' code: 404 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.freeze index 0b05e38af03..9d1d459ec9b 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.freeze @@ -1 +1 @@ -2022-05-12T09:50:24.737Z \ No newline at end of file +2024-01-03T22:54:46.662Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.yaml index 47ed71ac747..e225ef46380 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_Corrections_For_an_SLO_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Get_Corrections_For_an_SLO_returns_OK_response-1652349024","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Get_Corrections_For_an_SLO_returns_OK_response-1704322486","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"dd2615cf2fbf56098f3cf4965d37892f","name":"Test-Get_Corrections_For_an_SLO_returns_OK_response-1652349024","created_at":1652349025,"tags":[],"modified_at":1652349025,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"029b3b619a6255eb899c46681dd7038f","name":"Test-Get_Corrections_For_an_SLO_returns_OK_response-1704322486","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322486,"modified_at":1704322486}],"error":null} + + ' code: 200 duration: '' headers: @@ -20,7 +22,7 @@ interactions: status: 200 OK - request: body: | - {"data":{"attributes":{"category":"Other","description":"Test Correction","end":1652352624,"slo_id":"dd2615cf2fbf56098f3cf4965d37892f","start":1652349024,"timezone":"UTC"},"type":"correction"}} + {"data":{"attributes":{"category":"Other","description":"Test Correction","end":1704326086,"slo_id":"029b3b619a6255eb899c46681dd7038f","start":1704322486,"timezone":"UTC"},"type":"correction"}} form: {} headers: Accept: @@ -30,8 +32,10 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo/correction response: - body: '{"data":{"type":"correction","id":"f2b8ad40-d1d8-11ec-a01e-da7ad0902002","attributes":{"slo_id":"dd2615cf2fbf56098f3cf4965d37892f","start":1652349024,"end":1652352624,"description":"Test - Correction","category":"Other","timezone":"UTC","created_at":null,"modified_at":null,"rrule":null,"duration":null,"creator":{"data":{"type":"users","id":"3ad549bf-eba0-11e9-a77a-0705486660d0","attributes":{"uuid":"3ad549bf-eba0-11e9-a77a-0705486660d0","handle":"frog@datadoghq.com","email":"frog@datadoghq.com","name":null,"icon":"https://secure.gravatar.com/avatar/28a16dfe36e73b60c1d55872cb0f1172?s=48&d=retro"}}},"modifier":null}}}' + body: '{"data":{"type":"correction","id":"17b61420-aa8b-11ee-97f2-da7ad0902002","attributes":{"slo_id":"029b3b619a6255eb899c46681dd7038f","start":1704322486,"end":1704326086,"description":"Test + Correction","category":"Other","timezone":"UTC","created_at":null,"modified_at":null,"rrule":null,"duration":null,"creator":{"data":{"type":"users","id":"3ad549bf-eba0-11e9-a77a-0705486660d0","attributes":{"uuid":"3ad549bf-eba0-11e9-a77a-0705486660d0","handle":"frog@datadoghq.com","email":"frog@datadoghq.com","name":null,"icon":"https://secure.gravatar.com/avatar/28a16dfe36e73b60c1d55872cb0f1172?s=48&d=retro"}}},"modifier":null}}} + + ' code: 200 duration: '' headers: @@ -45,10 +49,12 @@ interactions: Accept: - application/json method: GET - url: https://api.datadoghq.com/api/v1/slo/dd2615cf2fbf56098f3cf4965d37892f/corrections + url: https://api.datadoghq.com/api/v1/slo/029b3b619a6255eb899c46681dd7038f/corrections response: - body: '{"meta":{"pagination":{"type":"offset_limit","prev_offset":0,"next_offset":10,"offset":0,"limit":10,"total":1,"first_offset":0,"last_offset":0}},"data":[{"type":"correction","id":"f2b8ad40-d1d8-11ec-a01e-da7ad0902002","attributes":{"slo_id":"dd2615cf2fbf56098f3cf4965d37892f","start":1652349024,"end":1652352624,"description":"Test - Correction","category":"Other","timezone":"UTC","created_at":1652349025,"modified_at":1652349025,"rrule":null,"duration":null,"creator":{"data":{"type":"users","id":"3ad549bf-eba0-11e9-a77a-0705486660d0","attributes":{"uuid":"3ad549bf-eba0-11e9-a77a-0705486660d0","handle":"frog@datadoghq.com","email":"frog@datadoghq.com","name":null,"icon":"https://secure.gravatar.com/avatar/28a16dfe36e73b60c1d55872cb0f1172?s=48&d=retro"}}},"modifier":null}}],"links":{"next":"https://api.datadoghq.com/api/v1/slo/dd2615cf2fbf56098f3cf4965d37892f/corrections?page[offset]=10&page[limit]=10","self":"https://api.datadoghq.com/api/v1/slo/dd2615cf2fbf56098f3cf4965d37892f/corrections","prev":null,"last":null,"first":"https://api.datadoghq.com/api/v1/slo/dd2615cf2fbf56098f3cf4965d37892f/corrections?page[offset]=0&page[limit]=10"}}' + body: '{"data":[{"type":"correction","id":"17b61420-aa8b-11ee-97f2-da7ad0902002","attributes":{"slo_id":"029b3b619a6255eb899c46681dd7038f","start":1704322486,"end":1704326086,"description":"Test + Correction","category":"Other","timezone":"UTC","created_at":1704322487,"modified_at":1704322487,"rrule":null,"duration":null,"creator":{"data":{"type":"users","id":"3ad549bf-eba0-11e9-a77a-0705486660d0","attributes":{"uuid":"3ad549bf-eba0-11e9-a77a-0705486660d0","handle":"frog@datadoghq.com","email":"frog@datadoghq.com","name":null,"icon":"https://secure.gravatar.com/avatar/28a16dfe36e73b60c1d55872cb0f1172?s=48&d=retro"}}},"modifier":null}}],"meta":{"pagination":{"offset":0,"first_offset":0,"prev_offset":0,"next_offset":10,"last_offset":0,"limit":10,"type":"offset_limit","total":1}},"links":{"self":"https://api.datadoghq.com/api/v1/slo/029b3b619a6255eb899c46681dd7038f/corrections","last":null,"next":"https://api.datadoghq.com/api/v1/slo/029b3b619a6255eb899c46681dd7038f/corrections?page[offset]=10&page[limit]=10","prev":null,"first":"https://api.datadoghq.com/api/v1/slo/029b3b619a6255eb899c46681dd7038f/corrections?page[offset]=0&page[limit]=10"}} + + ' code: 200 duration: '' headers: @@ -62,12 +68,14 @@ interactions: Accept: - '*/*' method: DELETE - url: https://api.datadoghq.com/api/v1/slo/correction/f2b8ad40-d1d8-11ec-a01e-da7ad0902002 + url: https://api.datadoghq.com/api/v1/slo/correction/17b61420-aa8b-11ee-97f2-da7ad0902002 response: body: '' code: 204 duration: '' - headers: {} + headers: + Content-Type: + - text/html; charset=utf-8 status: 204 No Content - request: body: '' @@ -76,9 +84,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/dd2615cf2fbf56098f3cf4965d37892f + url: https://api.datadoghq.com/api/v1/slo/029b3b619a6255eb899c46681dd7038f response: - body: '{"data":["dd2615cf2fbf56098f3cf4965d37892f"],"error":null}' + body: '{"data":["029b3b619a6255eb899c46681dd7038f"],"error":null} + + ' code: 200 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.freeze index fb6bf3e09dc..8d2d61c2b8d 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.freeze @@ -1 +1 @@ -2022-03-08T14:09:49.857Z \ No newline at end of file +2024-01-03T22:54:47.632Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.yaml index b7334184007..dd67a48f102 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_all_SLOs_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Get_all_SLOs_returns_OK_response-1646748589","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Get_all_SLOs_returns_OK_response-1704322487","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"11b6985a7e135c529ea6e1d02d742dd8","name":"Test-Get_all_SLOs_returns_OK_response-1646748589","created_at":1646748590,"tags":[],"modified_at":1646748590,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"c2ce7fb6030c5c0b8035d1ce94dec12c","name":"Test-Get_all_SLOs_returns_OK_response-1704322487","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322487,"modified_at":1704322487}],"error":null} + + ' code: 200 duration: '' headers: @@ -25,9 +27,11 @@ interactions: Accept: - application/json method: GET - url: https://api.datadoghq.com/api/v1/slo?ids=11b6985a7e135c529ea6e1d02d742dd8 + url: https://api.datadoghq.com/api/v1/slo?ids=c2ce7fb6030c5c0b8035d1ce94dec12c response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"11b6985a7e135c529ea6e1d02d742dd8","name":"Test-Get_all_SLOs_returns_OK_response-1646748589","created_at":1646748590,"tags":[],"modified_at":1646748590,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"c2ce7fb6030c5c0b8035d1ce94dec12c","name":"Test-Get_all_SLOs_returns_OK_response-1704322487","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98.0,"target_threshold":95.0,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322487,"modified_at":1704322487}],"error":null} + + ' code: 200 duration: '' headers: @@ -41,9 +45,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/11b6985a7e135c529ea6e1d02d742dd8 + url: https://api.datadoghq.com/api/v1/slo/c2ce7fb6030c5c0b8035d1ce94dec12c response: - body: '{"data":["11b6985a7e135c529ea6e1d02d742dd8"],"error":null}' + body: '{"data":["c2ce7fb6030c5c0b8035d1ce94dec12c"],"error":null} + + ' code: 200 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.freeze index 34aad93e403..02d09fae477 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.freeze @@ -1 +1 @@ -2022-03-08T13:51:10.786Z \ No newline at end of file +2024-01-03T22:54:48.137Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.yaml index e3541751f20..3550c3bf8ae 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_details_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Get_an_SLO_s_details_returns_OK_response-1646747470","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Get_an_SLO_s_details_returns_OK_response-1704322488","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"152e72d970e15e799e4b195d7193ed18","name":"Test-Get_an_SLO_s_details_returns_OK_response-1646747470","created_at":1646747471,"tags":[],"modified_at":1646747471,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"ebf2e048f49a5134b61a586438c66505","name":"Test-Get_an_SLO_s_details_returns_OK_response-1704322488","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322488,"modified_at":1704322488}],"error":null} + + ' code: 200 duration: '' headers: @@ -25,9 +27,11 @@ interactions: Accept: - application/json method: GET - url: https://api.datadoghq.com/api/v1/slo/152e72d970e15e799e4b195d7193ed18 + url: https://api.datadoghq.com/api/v1/slo/ebf2e048f49a5134b61a586438c66505 response: - body: '{"data":{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"152e72d970e15e799e4b195d7193ed18","name":"Test-Get_an_SLO_s_details_returns_OK_response-1646747470","created_at":1646747471,"tags":[],"modified_at":1646747471,"type":"metric"},"error":null}' + body: '{"data":{"id":"ebf2e048f49a5134b61a586438c66505","name":"Test-Get_an_SLO_s_details_returns_OK_response-1704322488","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98.0,"target_threshold":95.0,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322488,"modified_at":1704322488},"error":null} + + ' code: 200 duration: '' headers: @@ -41,9 +45,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/152e72d970e15e799e4b195d7193ed18 + url: https://api.datadoghq.com/api/v1/slo/ebf2e048f49a5134b61a586438c66505 response: - body: '{"data":["152e72d970e15e799e4b195d7193ed18"],"error":null}' + body: '{"data":["ebf2e048f49a5134b61a586438c66505"],"error":null} + + ' code: 200 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.freeze index 324ba61bcfa..0598ce87821 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.freeze @@ -1 +1 @@ -2022-03-08T13:59:13.427Z \ No newline at end of file +2024-01-03T22:54:48.654Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.yaml index 55dbd37c43a..696b74d2329 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Get_an_SLOs_history_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Get_an_SLO_s_history_returns_OK_response-1646747953","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Get_an_SLO_s_history_returns_OK_response-1704322488","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"9236f988e3d25ac6982fd4319912ec43","name":"Test-Get_an_SLO_s_history_returns_OK_response-1646747953","created_at":1646747953,"tags":[],"modified_at":1646747953,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"627a3ccd24af50beb8eacbd36c5962f9","name":"Test-Get_an_SLO_s_history_returns_OK_response-1704322488","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322488,"modified_at":1704322488}],"error":null} + + ' code: 200 duration: '' headers: @@ -25,13 +27,15 @@ interactions: Accept: - application/json method: GET - url: https://api.datadoghq.com/api/v1/slo/9236f988e3d25ac6982fd4319912ec43/history?from_ts=1646661553&to_ts=1646747953 + url: https://api.datadoghq.com/api/v1/slo/627a3ccd24af50beb8eacbd36c5962f9/history?from_ts=1704236088&to_ts=1704322488 response: - body: '{"errors":null,"data":{"to_ts":1646747953,"type_id":1,"series":{"res_type":"time_series","denominator":{"count":13,"sum":0.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"metadata":{"unit":null,"query_index":1,"aggr":"sum","scope":"!code:3xx","metric":"default_zero(httpservice.hits)","expression":"default_zero(sum:httpservice.hits{!code:3xx}.as_count())","tag_set":[]}},"graph_query":"default_zero(sum:httpservice.hits{code:2xx}.as_count()), - default_zero(sum:httpservice.hits{!code:3xx}.as_count()) - default_zero(sum:httpservice.hits{code:2xx}.as_count())","resp_version":2,"interval":7200,"numerator":{"count":13,"sum":0.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"metadata":{"unit":null,"query_index":0,"aggr":"sum","scope":"code:2xx","metric":"default_zero(httpservice.hits)","expression":"default_zero(sum:httpservice.hits{code:2xx}.as_count())","tag_set":[]}},"bad_series_query":"default_zero(sum:httpservice.hits{!code:3xx}.as_count()) - - default_zero(sum:httpservice.hits{code:2xx}.as_count())","times":[1646654400000.0,1646661600000.0,1646668800000.0,1646676000000.0,1646683200000.0,1646690400000.0,1646697600000.0,1646704800000.0,1646712000000.0,1646719200000.0,1646726400000.0,1646733600000.0,1646740800000.0],"denominator_query":"default_zero(sum:httpservice.hits{!code:3xx}.as_count())","from_date":1646661553000,"numerator_query":"default_zero(sum:httpservice.hits{code:2xx}.as_count())","to_date":1646747953000,"timing":"0.0103521347046","query":"default_zero(sum:httpservice.hits{code:2xx}.as_count()), - default_zero(sum:httpservice.hits{!code:3xx}.as_count())","message":""},"thresholds":{"7d":{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}},"overall":{"uptime":null,"errors":[{"error_type":"ZERO_VALUED_DENOMINATOR","error_message":"The - denominator is zero valued"}],"sli_value":null,"precision":{"7d":0},"corrections":[],"span_precision":2},"from_ts":1646661553,"group_by":[],"slo":{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98.0,"warning_display":"98.","target":95.0,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"9236f988e3d25ac6982fd4319912ec43","name":"Test-Get_an_SLO_s_history_returns_OK_response-1646747953","created_at":1646747953,"tags":[],"modified_at":1646747953,"type":"metric"},"type":"metric"}}' + body: '{"data":{"thresholds":{"7d":{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}},"from_ts":1704236088,"to_ts":1704322488,"type":"metric","type_id":1,"slo":{"id":"627a3ccd24af50beb8eacbd36c5962f9","name":"Test-Get_an_SLO_s_history_returns_OK_response-1704322488","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98.0,"target_threshold":95.0,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322488,"modified_at":1704322488},"group_by":[],"series":{"timing":"0.02146005630493164","res_type":"time_series","resp_version":2,"query":"default_zero(sum:httpservice.hits{code:2xx}.as_count()), + default_zero(sum:httpservice.hits{!code:3xx}.as_count())","from_date":1704236088000,"to_date":1704322488000,"message":"","interval":7200,"times":[1704235800000.0,1704240000000.0,1704247200000.0,1704254400000.0,1704261600000.0,1704268800000.0,1704276000000.0,1704283200000.0,1704290400000.0,1704297600000.0,1704304800000.0,1704312000000.0,1704319200000.0],"numerator":{"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"metadata":{"unit":null,"query_index":0,"aggr":"sum","metric":"default_zero(httpservice.hits)","tag_set":[],"expression":"default_zero(sum:httpservice.hits{code:2xx}.as_count())","scope":"code:2xx"},"sum":0.0,"count":13},"denominator":{"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"metadata":{"unit":null,"query_index":1,"aggr":"sum","metric":"default_zero(httpservice.hits)","tag_set":[],"expression":"default_zero(sum:httpservice.hits{!code:3xx}.as_count())","scope":"!code:3xx"},"sum":0.0,"count":13},"numerator_query":"default_zero(sum:httpservice.hits{code:2xx}.as_count())","denominator_query":"default_zero(sum:httpservice.hits{!code:3xx}.as_count())","bad_series_query":"default_zero(sum:httpservice.hits{!code:3xx}.as_count()) + - default_zero(sum:httpservice.hits{code:2xx}.as_count())","graph_query":"default_zero(sum:httpservice.hits{code:2xx}.as_count()), + default_zero(sum:httpservice.hits{!code:3xx}.as_count()) - default_zero(sum:httpservice.hits{code:2xx}.as_count())"},"overall":{"errors":[{"error_message":"The + denominator is zero valued","error_type":"ZERO_VALUED_DENOMINATOR"}],"sli_value":null,"span_precision":2,"precision":{"7d":0},"uptime":null,"corrections":[],"state":"no_data"}},"errors":null} + + ' code: 200 duration: '' headers: @@ -45,9 +49,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/9236f988e3d25ac6982fd4319912ec43 + url: https://api.datadoghq.com/api/v1/slo/627a3ccd24af50beb8eacbd36c5962f9 response: - body: '{"data":["9236f988e3d25ac6982fd4319912ec43"],"error":null}' + body: '{"data":["627a3ccd24af50beb8eacbd36c5962f9"],"error":null} + + ' code: 200 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.freeze index 37ba6cab0e4..a38c0a46eb2 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.freeze @@ -1 +1 @@ -2022-01-06T00:51:12.843Z \ No newline at end of file +2024-01-03T22:54:49.226Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.yaml index 48e9e6294ea..555603614b6 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_Bad_Request_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Update_an_SLO_returns_Bad_Request_response-1641430272","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Update_an_SLO_returns_Bad_Request_response-1704322489","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,9 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"description":"","monitor_tags":[],"creator":{"handle":"frog@datadoghq.com","name":null,"email":"frog@datadoghq.com"},"thresholds":[{"warning":98,"warning_display":"98.","target":95,"target_display":"95.","timeframe":"7d"}],"type_id":1,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"id":"f21337f0ea7059f986448228aaa11f09","name":"Test-Update_an_SLO_returns_Bad_Request_response-1641430272","created_at":1641430273,"tags":[],"modified_at":1641430273,"type":"metric"}],"error":null}' + body: '{"data":[{"id":"9000070725e15b55a16fa1b2bcd1909c","name":"Test-Update_an_SLO_returns_Bad_Request_response-1704322489","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322489,"modified_at":1704322489}],"error":null} + + ' code: 200 duration: '' headers: @@ -20,7 +22,7 @@ interactions: status: 200 OK - request: body: | - {"name":"Test-Update_an_SLO_returns_Bad_Request_response-1641430272","thresholds":[{"target":95,"target_display":"95.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"type":"monitor"} + {"name":"Test-Update_an_SLO_returns_Bad_Request_response-1704322489","thresholds":[{"target":95,"target_display":"95.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"type":"monitor"} form: {} headers: Accept: @@ -28,7 +30,7 @@ interactions: Content-Type: - application/json method: PUT - url: https://api.datadoghq.com/api/v1/slo/f21337f0ea7059f986448228aaa11f09 + url: https://api.datadoghq.com/api/v1/slo/9000070725e15b55a16fa1b2bcd1909c response: body: '{"errors":["Invalid payload: must specify the query for count types"]}' code: 400 @@ -44,9 +46,11 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/f21337f0ea7059f986448228aaa11f09 + url: https://api.datadoghq.com/api/v1/slo/9000070725e15b55a16fa1b2bcd1909c response: - body: '{"data":["f21337f0ea7059f986448228aaa11f09"],"error":null}' + body: '{"data":["9000070725e15b55a16fa1b2bcd1909c"],"error":null} + + ' code: 200 duration: '' headers: diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.freeze index 5e9bd3a34b1..b83299dd7c9 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.freeze @@ -1 +1 @@ -2022-12-23T20:34:34.100Z \ No newline at end of file +2024-01-03T22:54:49.748Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.yaml index 807c920afde..29da2dc9b81 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Service_Level_Objectives/Scenario_Update_an_SLO_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"name":"Test-Update_an_SLO_returns_OK_response-1671827674","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} + {"name":"Test-Update_an_SLO_returns_OK_response-1704322489","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"thresholds":[{"target":95,"timeframe":"7d","warning":98}],"type":"metric"} form: {} headers: Accept: @@ -11,7 +11,7 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/slo response: - body: '{"data":[{"id":"9ca3260165e5524bb05029ae2cf52ceb","name":"Test-Update_an_SLO_returns_OK_response-1671827674","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1671827674,"modified_at":1671827674}],"error":null} + body: '{"data":[{"id":"f38441f875995acc9682503ee2d1901e","name":"Test-Update_an_SLO_returns_OK_response-1704322489","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":95.0,"target_display":"95.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":95,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322489,"modified_at":1704322489}],"error":null} ' code: 200 @@ -22,7 +22,7 @@ interactions: status: 200 OK - request: body: | - {"name":"Test-Update_an_SLO_returns_OK_response-1671827674","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"target_threshold":97,"thresholds":[{"target":97,"timeframe":"7d","warning":98}],"timeframe":"7d","type":"metric","warning_threshold":98} + {"name":"Test-Update_an_SLO_returns_OK_response-1704322489","query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"target_threshold":97,"thresholds":[{"target":97,"timeframe":"7d","warning":98}],"timeframe":"7d","type":"metric","warning_threshold":98} form: {} headers: Accept: @@ -30,9 +30,9 @@ interactions: Content-Type: - application/json method: PUT - url: https://api.datadoghq.com/api/v1/slo/9ca3260165e5524bb05029ae2cf52ceb + url: https://api.datadoghq.com/api/v1/slo/f38441f875995acc9682503ee2d1901e response: - body: '{"data":[{"id":"9ca3260165e5524bb05029ae2cf52ceb","name":"Test-Update_an_SLO_returns_OK_response-1671827674","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":97.0,"target_display":"97.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":97,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1671827674,"modified_at":1671827674}],"error":null} + body: '{"data":[{"id":"f38441f875995acc9682503ee2d1901e","name":"Test-Update_an_SLO_returns_OK_response-1704322489","tags":[],"monitor_tags":[],"thresholds":[{"timeframe":"7d","target":97.0,"target_display":"97.","warning":98.0,"warning_display":"98."}],"type":"metric","type_id":1,"description":"","timeframe":"7d","warning_threshold":98,"target_threshold":97,"query":{"denominator":"sum:httpservice.hits{!code:3xx}.as_count()","numerator":"sum:httpservice.hits{code:2xx}.as_count()"},"creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com"},"created_at":1704322489,"modified_at":1704322490}],"error":null} ' code: 200 @@ -48,9 +48,9 @@ interactions: Accept: - application/json method: DELETE - url: https://api.datadoghq.com/api/v1/slo/9ca3260165e5524bb05029ae2cf52ceb + url: https://api.datadoghq.com/api/v1/slo/f38441f875995acc9682503ee2d1901e response: - body: '{"data":["9ca3260165e5524bb05029ae2cf52ceb"],"error":null} + body: '{"data":["f38441f875995acc9682503ee2d1901e"],"error":null} ' code: 200 diff --git a/tests/scenarios/features/v1/service_level_objectives.feature b/tests/scenarios/features/v1/service_level_objectives.feature index 75e721bb430..c5534618a73 100644 --- a/tests/scenarios/features/v1/service_level_objectives.feature +++ b/tests/scenarios/features/v1/service_level_objectives.feature @@ -48,6 +48,16 @@ Feature: Service Level Objectives When the request is sent Then the response status is 200 OK + @team:DataDog/slo-app + Scenario: Create a time-slice SLO object returns "OK" response + Given new "CreateSLO" request + And body with value {"type":"time_slice","description":"string","name":"{{ unique }}","sli_specification":{"time_slice":{"query":{"formulas":[{"formula":"query1"}],"queries":[{"data_source":"metrics","name":"query1","query":"trace.servlet.request{env:prod}"}]},"comparator":">","threshold":5}},"tags":["env:prod"],"thresholds":[{"target":97.0,"target_display":"97.0","timeframe":"7d","warning":98,"warning_display":"98.0"}],"timeframe":"7d","target_threshold":97.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 97.0 + And the response "data[0].warning_threshold" is equal to 98.0 + @team:DataDog/slo-app Scenario: Create an SLO object returns "Bad Request" response Given new "CreateSLO" request @@ -220,7 +230,7 @@ Feature: Service Level Objectives Scenario: Update an SLO returns "Not Found" response Given new "UpdateSLO" request And request contains "slo_id" parameter from "REPLACE.ME" - And body with value {"description": null, "groups": ["env:prod", "role:mysql"], "monitor_ids": [], "monitor_tags": [], "name": "Custom Metric SLO", "query": {"denominator": "sum:my.custom.metric{*}.as_count()", "numerator": "sum:my.custom.metric{type:good}.as_count()"}, "tags": ["env:prod", "app:core"], "target_threshold": 99.9, "thresholds": [{"target": 95, "timeframe": "7d"}, {"target": 95, "timeframe": "30d", "warning": 97}], "timeframe": "30d", "type": "metric", "warning_threshold": 99.95} + And body with value {"description": null, "groups": ["env:prod", "role:mysql"], "monitor_ids": [], "monitor_tags": [], "name": "Custom Metric SLO", "query": {"denominator": "sum:my.custom.metric{*}.as_count()", "numerator": "sum:my.custom.metric{type:good}.as_count()"}, "sli_specification": {"time_slice": {"comparator": "<", "query": {"formulas": [{"formula": "query2/query1"}], "queries": [{"data_source": "metrics", "name": "query1", "query": "sum:trace.servlet.request.hits{*} by {env}.as_count()"}, {"data_source": "metrics", "name": "query1", "query": "sum:trace.servlet.request.errors{*} by {env}.as_count()"}]}, "threshold": 5}}, "tags": ["env:prod", "app:core"], "target_threshold": 99.9, "thresholds": [{"target": 95, "timeframe": "7d"}, {"target": 95, "timeframe": "30d", "warning": 97}], "timeframe": "30d", "type": "metric", "warning_threshold": 99.95} When the request is sent Then the response status is 404 Not Found