diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a7a771..4d2942a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +Added: +* Adds support for custom dimension labels in the `chronosphere_slo` resource. + ## 1.7.0 Added: diff --git a/chronosphere/intschema/slo.go b/chronosphere/intschema/slo.go index eae031d..e57fbd1 100644 --- a/chronosphere/intschema/slo.go +++ b/chronosphere/intschema/slo.go @@ -63,6 +63,7 @@ func (o *Slo) Ref() tfid.ID { } type SloSli struct { + CustomDimensionLabels []string `intschema:"custom_dimension_labels,optional"` CustomIndicator *SloSliCustomIndicator `intschema:"custom_indicator,optional,list_encoded_object"` EndpointAvailability *SloSliEndpointAvailability `intschema:"endpoint_availability,optional,list_encoded_object"` EndpointLabel string `intschema:"endpoint_label,optional"` diff --git a/chronosphere/pkg/configunstable/models/configunstable_create_log_control_config_request.go b/chronosphere/pkg/configunstable/models/configunstable_create_log_control_config_request.go index 29e8d2c..9e68640 100644 --- a/chronosphere/pkg/configunstable/models/configunstable_create_log_control_config_request.go +++ b/chronosphere/pkg/configunstable/models/configunstable_create_log_control_config_request.go @@ -18,6 +18,9 @@ import ( // swagger:model configunstableCreateLogControlConfigRequest type ConfigunstableCreateLogControlConfigRequest struct { + // If true, the LogControlConfig will not be created, and no response LogControlConfig will be returned. The response will return an error if the given LogControlConfig is invalid. + DryRun bool `json:"dry_run,omitempty"` + // log control config LogControlConfig *ConfigunstableLogControlConfig `json:"log_control_config,omitempty"` } diff --git a/chronosphere/pkg/configunstable/models/configunstable_rule.go b/chronosphere/pkg/configunstable/models/configunstable_rule.go index 6a1799c..8b38900 100644 --- a/chronosphere/pkg/configunstable/models/configunstable_rule.go +++ b/chronosphere/pkg/configunstable/models/configunstable_rule.go @@ -25,7 +25,7 @@ type ConfigunstableRule struct { DeleteFields *RuleDeleteFields `json:"delete_fields,omitempty"` // drop - Drop *RuleDrop `json:"drop,omitempty"` + Drop RuleDrop `json:"drop,omitempty"` // emit metrics EmitMetrics *RuleEmitMetrics `json:"emit_metrics,omitempty"` @@ -49,10 +49,6 @@ func (m *ConfigunstableRule) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateDrop(formats); err != nil { - res = append(res, err) - } - if err := m.validateEmitMetrics(formats); err != nil { res = append(res, err) } @@ -109,25 +105,6 @@ func (m *ConfigunstableRule) validateDeleteFields(formats strfmt.Registry) error return nil } -func (m *ConfigunstableRule) validateDrop(formats strfmt.Registry) error { - if swag.IsZero(m.Drop) { // not required - return nil - } - - if m.Drop != nil { - if err := m.Drop.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("drop") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("drop") - } - return err - } - } - - return nil -} - func (m *ConfigunstableRule) validateEmitMetrics(formats strfmt.Registry) error { if swag.IsZero(m.EmitMetrics) { // not required return nil @@ -195,10 +172,6 @@ func (m *ConfigunstableRule) ContextValidate(ctx context.Context, formats strfmt res = append(res, err) } - if err := m.contextValidateDrop(ctx, formats); err != nil { - res = append(res, err) - } - if err := m.contextValidateEmitMetrics(ctx, formats); err != nil { res = append(res, err) } @@ -249,22 +222,6 @@ func (m *ConfigunstableRule) contextValidateDeleteFields(ctx context.Context, fo return nil } -func (m *ConfigunstableRule) contextValidateDrop(ctx context.Context, formats strfmt.Registry) error { - - if m.Drop != nil { - if err := m.Drop.ContextValidate(ctx, formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("drop") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("drop") - } - return err - } - } - - return nil -} - func (m *ConfigunstableRule) contextValidateEmitMetrics(ctx context.Context, formats strfmt.Registry) error { if m.EmitMetrics != nil { diff --git a/chronosphere/pkg/configunstable/models/configunstable_s_l_i.go b/chronosphere/pkg/configunstable/models/configunstable_s_l_i.go index 768d6ed..c5dca50 100644 --- a/chronosphere/pkg/configunstable/models/configunstable_s_l_i.go +++ b/chronosphere/pkg/configunstable/models/configunstable_s_l_i.go @@ -19,6 +19,14 @@ import ( // swagger:model configunstableSLI type ConfigunstableSLI struct { + // Custom dimensions are used to configure additional labels to export from + // the underlying queries. This feature provides a logical budget to group + // unique combination of dimensions. For example, if you want to track a + // budget per endpoint, add the endpoint label as a dimension. These dimensions + // are provided on the top-level SLI so that queryful SLOs will receive them + // in `.GroupBy`. + CustomDimensionLabels []string `json:"custom_dimension_labels"` + // custom indicator CustomIndicator *SLICustomIndicatorConfig `json:"custom_indicator,omitempty"` diff --git a/chronosphere/pkg/configunstable/models/configunstable_update_log_control_config_response.go b/chronosphere/pkg/configunstable/models/configunstable_update_log_control_config_response.go index 338899d..da499ba 100644 --- a/chronosphere/pkg/configunstable/models/configunstable_update_log_control_config_response.go +++ b/chronosphere/pkg/configunstable/models/configunstable_update_log_control_config_response.go @@ -18,15 +18,15 @@ import ( // swagger:model configunstableUpdateLogControlConfigResponse type ConfigunstableUpdateLogControlConfigResponse struct { - // log control configconfig - LogControlConfigconfig *ConfigunstableLogControlConfig `json:"log_control_configconfig,omitempty"` + // log control config + LogControlConfig *ConfigunstableLogControlConfig `json:"log_control_config,omitempty"` } // Validate validates this configunstable update log control config response func (m *ConfigunstableUpdateLogControlConfigResponse) Validate(formats strfmt.Registry) error { var res []error - if err := m.validateLogControlConfigconfig(formats); err != nil { + if err := m.validateLogControlConfig(formats); err != nil { res = append(res, err) } @@ -36,17 +36,17 @@ func (m *ConfigunstableUpdateLogControlConfigResponse) Validate(formats strfmt.R return nil } -func (m *ConfigunstableUpdateLogControlConfigResponse) validateLogControlConfigconfig(formats strfmt.Registry) error { - if swag.IsZero(m.LogControlConfigconfig) { // not required +func (m *ConfigunstableUpdateLogControlConfigResponse) validateLogControlConfig(formats strfmt.Registry) error { + if swag.IsZero(m.LogControlConfig) { // not required return nil } - if m.LogControlConfigconfig != nil { - if err := m.LogControlConfigconfig.Validate(formats); err != nil { + if m.LogControlConfig != nil { + if err := m.LogControlConfig.Validate(formats); err != nil { if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("log_control_configconfig") + return ve.ValidateName("log_control_config") } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("log_control_configconfig") + return ce.ValidateName("log_control_config") } return err } @@ -59,7 +59,7 @@ func (m *ConfigunstableUpdateLogControlConfigResponse) validateLogControlConfigc func (m *ConfigunstableUpdateLogControlConfigResponse) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error - if err := m.contextValidateLogControlConfigconfig(ctx, formats); err != nil { + if err := m.contextValidateLogControlConfig(ctx, formats); err != nil { res = append(res, err) } @@ -69,14 +69,14 @@ func (m *ConfigunstableUpdateLogControlConfigResponse) ContextValidate(ctx conte return nil } -func (m *ConfigunstableUpdateLogControlConfigResponse) contextValidateLogControlConfigconfig(ctx context.Context, formats strfmt.Registry) error { +func (m *ConfigunstableUpdateLogControlConfigResponse) contextValidateLogControlConfig(ctx context.Context, formats strfmt.Registry) error { - if m.LogControlConfigconfig != nil { - if err := m.LogControlConfigconfig.ContextValidate(ctx, formats); err != nil { + if m.LogControlConfig != nil { + if err := m.LogControlConfig.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("log_control_configconfig") + return ve.ValidateName("log_control_config") } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("log_control_configconfig") + return ce.ValidateName("log_control_config") } return err } diff --git a/chronosphere/pkg/configunstable/models/control_rule_mode.go b/chronosphere/pkg/configunstable/models/control_rule_mode.go index 6b728da..94aceb1 100644 --- a/chronosphere/pkg/configunstable/models/control_rule_mode.go +++ b/chronosphere/pkg/configunstable/models/control_rule_mode.go @@ -30,11 +30,11 @@ func (m ControlRuleMode) Pointer() *ControlRuleMode { const ( - // ControlRuleModeMODEENABLED captures enum value "MODE_ENABLED" - ControlRuleModeMODEENABLED ControlRuleMode = "MODE_ENABLED" + // ControlRuleModeENABLED captures enum value "ENABLED" + ControlRuleModeENABLED ControlRuleMode = "ENABLED" - // ControlRuleModeMODEDISABLED captures enum value "MODE_DISABLED" - ControlRuleModeMODEDISABLED ControlRuleMode = "MODE_DISABLED" + // ControlRuleModeDISABLED captures enum value "DISABLED" + ControlRuleModeDISABLED ControlRuleMode = "DISABLED" ) // for schema @@ -42,7 +42,7 @@ var controlRuleModeEnum []interface{} func init() { var res []ControlRuleMode - if err := json.Unmarshal([]byte(`["MODE_ENABLED","MODE_DISABLED"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["ENABLED","DISABLED"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/chronosphere/pkg/configunstable/models/emit_metricshistogram_metric.go b/chronosphere/pkg/configunstable/models/emit_metricshistogram_metric.go index fd42a6b..6925fe2 100644 --- a/chronosphere/pkg/configunstable/models/emit_metricshistogram_metric.go +++ b/chronosphere/pkg/configunstable/models/emit_metricshistogram_metric.go @@ -18,7 +18,7 @@ import ( type EmitMetricshistogramMetric struct { // Buckets specify the buckets to use for the histogram. - Buckets []float32 `json:"buckets"` + Buckets []float64 `json:"buckets"` // Value field is used to specify what field holds the numerical value. ValueField string `json:"value_field,omitempty"` diff --git a/chronosphere/pkg/configunstable/models/rule_delete_fields.go b/chronosphere/pkg/configunstable/models/rule_delete_fields.go index c3dafba..567531c 100644 --- a/chronosphere/pkg/configunstable/models/rule_delete_fields.go +++ b/chronosphere/pkg/configunstable/models/rule_delete_fields.go @@ -18,7 +18,7 @@ import ( type RuleDeleteFields struct { // field regex - FieldRegex string `json:"fieldRegex,omitempty"` + FieldRegex string `json:"field_regex,omitempty"` } // Validate validates this rule delete fields diff --git a/chronosphere/pkg/configunstable/models/rule_drop.go b/chronosphere/pkg/configunstable/models/rule_drop.go index 70a48ae..2e3a6aa 100644 --- a/chronosphere/pkg/configunstable/models/rule_drop.go +++ b/chronosphere/pkg/configunstable/models/rule_drop.go @@ -5,103 +5,7 @@ package models // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" -) - // RuleDrop Drop is the configuration for a drop filter // // swagger:model RuleDrop -type RuleDrop struct { - - // enabled - Enabled bool `json:"enabled,omitempty"` - - // label - Label *ConfigunstableLabel `json:"label,omitempty"` -} - -// Validate validates this rule drop -func (m *RuleDrop) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateLabel(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *RuleDrop) validateLabel(formats strfmt.Registry) error { - if swag.IsZero(m.Label) { // not required - return nil - } - - if m.Label != nil { - if err := m.Label.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("label") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("label") - } - return err - } - } - - return nil -} - -// ContextValidate validate this rule drop based on the context it is used -func (m *RuleDrop) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - var res []error - - if err := m.contextValidateLabel(ctx, formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *RuleDrop) contextValidateLabel(ctx context.Context, formats strfmt.Registry) error { - - if m.Label != nil { - if err := m.Label.ContextValidate(ctx, formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("label") - } else if ce, ok := err.(*errors.CompositeError); ok { - return ce.ValidateName("label") - } - return err - } - } - - return nil -} - -// MarshalBinary interface implementation -func (m *RuleDrop) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *RuleDrop) UnmarshalBinary(b []byte) error { - var res RuleDrop - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} +type RuleDrop interface{} diff --git a/chronosphere/pkg/configunstable/models/rule_rule_type.go b/chronosphere/pkg/configunstable/models/rule_rule_type.go index 64443c5..bf9cd91 100644 --- a/chronosphere/pkg/configunstable/models/rule_rule_type.go +++ b/chronosphere/pkg/configunstable/models/rule_rule_type.go @@ -30,20 +30,20 @@ func (m RuleRuleType) Pointer() *RuleRuleType { const ( - // RuleRuleTypeRULETYPESAMPLE captures enum value "RULE_TYPE_SAMPLE" - RuleRuleTypeRULETYPESAMPLE RuleRuleType = "RULE_TYPE_SAMPLE" + // RuleRuleTypeSAMPLE captures enum value "SAMPLE" + RuleRuleTypeSAMPLE RuleRuleType = "SAMPLE" - // RuleRuleTypeRULETYPEDELTEFIELDS captures enum value "RULE_TYPE_DELTE_FIELDS" - RuleRuleTypeRULETYPEDELTEFIELDS RuleRuleType = "RULE_TYPE_DELTE_FIELDS" + // RuleRuleTypeDELETEFIELDS captures enum value "DELETE_FIELDS" + RuleRuleTypeDELETEFIELDS RuleRuleType = "DELETE_FIELDS" - // RuleRuleTypeRULETYPEDEDUPE captures enum value "RULE_TYPE_DE_DUPE" - RuleRuleTypeRULETYPEDEDUPE RuleRuleType = "RULE_TYPE_DE_DUPE" + // RuleRuleTypeDEDUPE captures enum value "DE_DUPE" + RuleRuleTypeDEDUPE RuleRuleType = "DE_DUPE" - // RuleRuleTypeRULETYPEEMITMETRICS captures enum value "RULE_TYPE_EMIT_METRICS" - RuleRuleTypeRULETYPEEMITMETRICS RuleRuleType = "RULE_TYPE_EMIT_METRICS" + // RuleRuleTypeEMITMETRICS captures enum value "EMIT_METRICS" + RuleRuleTypeEMITMETRICS RuleRuleType = "EMIT_METRICS" - // RuleRuleTypeRULETYPEDROP captures enum value "RULE_TYPE_DROP" - RuleRuleTypeRULETYPEDROP RuleRuleType = "RULE_TYPE_DROP" + // RuleRuleTypeDROP captures enum value "DROP" + RuleRuleTypeDROP RuleRuleType = "DROP" ) // for schema @@ -51,7 +51,7 @@ var ruleRuleTypeEnum []interface{} func init() { var res []RuleRuleType - if err := json.Unmarshal([]byte(`["RULE_TYPE_SAMPLE","RULE_TYPE_DELTE_FIELDS","RULE_TYPE_DE_DUPE","RULE_TYPE_EMIT_METRICS","RULE_TYPE_DROP"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["SAMPLE","DELETE_FIELDS","DE_DUPE","EMIT_METRICS","DROP"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/chronosphere/pkg/configunstable/models/rule_sample.go b/chronosphere/pkg/configunstable/models/rule_sample.go index 4b359ab..4f9afec 100644 --- a/chronosphere/pkg/configunstable/models/rule_sample.go +++ b/chronosphere/pkg/configunstable/models/rule_sample.go @@ -18,10 +18,10 @@ import ( type RuleSample struct { // rate - Rate float32 `json:"rate,omitempty"` + Rate float64 `json:"rate,omitempty"` // window secs - WindowSecs int32 `json:"windowSecs,omitempty"` + WindowSecs int32 `json:"window_secs,omitempty"` } // Validate validates this rule sample diff --git a/chronosphere/pkg/configunstable/models/s_l_i_endpoint_availability_config.go b/chronosphere/pkg/configunstable/models/s_l_i_endpoint_availability_config.go index 07ee79f..9a0af74 100644 --- a/chronosphere/pkg/configunstable/models/s_l_i_endpoint_availability_config.go +++ b/chronosphere/pkg/configunstable/models/s_l_i_endpoint_availability_config.go @@ -23,7 +23,8 @@ type SLIEndpointAvailabilityConfig struct { // like `cluster!~"dev"` AdditionalPromqlFilters []*ConfigunstablePromQLMatcher `json:"additional_promql_filters"` - // The endpoints that are monitored by this SLI. + // the API endpoints to monitor in the SLO. If this is left empty then all + // endpoints will be monitored. EndpointsMonitored []string `json:"endpoints_monitored"` // A list of result codes that indicate an unsuccessful event. Either this diff --git a/chronosphere/pkg/configunstable/models/s_l_i_endpoint_latency_config.go b/chronosphere/pkg/configunstable/models/s_l_i_endpoint_latency_config.go index f6c083f..18018dc 100644 --- a/chronosphere/pkg/configunstable/models/s_l_i_endpoint_latency_config.go +++ b/chronosphere/pkg/configunstable/models/s_l_i_endpoint_latency_config.go @@ -23,7 +23,8 @@ type SLIEndpointLatencyConfig struct { // like `cluster!~"dev"` AdditionalPromqlFilters []*ConfigunstablePromQLMatcher `json:"additional_promql_filters"` - // The endpoints that are monitored by this SLI. + // the API endpoints to monitor in the SLO. If this is left empty then all + // endpoints will be monitored. EndpointsMonitored []string `json:"endpoints_monitored"` // The name of the histogram metric that measures latency. diff --git a/chronosphere/pkg/configunstable/swagger.json b/chronosphere/pkg/configunstable/swagger.json index cd0f62f..d56a6eb 100644 --- a/chronosphere/pkg/configunstable/swagger.json +++ b/chronosphere/pkg/configunstable/swagger.json @@ -172,8 +172,8 @@ }, "ControlRuleMode": { "enum": [ - "MODE_ENABLED", - "MODE_DISABLED" + "ENABLED", + "DISABLED" ], "type": "string" }, @@ -213,7 +213,7 @@ "buckets": { "description": "Buckets specify the buckets to use for the histogram.", "items": { - "format": "float", + "format": "double", "type": "number" }, "type": "array" @@ -374,21 +374,13 @@ "RuleDeleteFields": { "description": "DeleteFields is the configuration for a delete fields rule.", "properties": { - "fieldRegex": { + "field_regex": { "type": "string" } }, "type": "object" }, "RuleDrop": { - "properties": { - "enabled": { - "type": "boolean" - }, - "label": { - "$ref": "#/definitions/configunstableLabel" - } - }, "title": "Drop is the configuration for a drop filter", "type": "object" }, @@ -427,11 +419,11 @@ }, "RuleRuleType": { "enum": [ - "RULE_TYPE_SAMPLE", - "RULE_TYPE_DELTE_FIELDS", - "RULE_TYPE_DE_DUPE", - "RULE_TYPE_EMIT_METRICS", - "RULE_TYPE_DROP" + "SAMPLE", + "DELETE_FIELDS", + "DE_DUPE", + "EMIT_METRICS", + "DROP" ], "type": "string" }, @@ -439,10 +431,10 @@ "description": "Sample is the configuration for a sample rule.", "properties": { "rate": { - "format": "float", + "format": "double", "type": "number" }, - "windowSecs": { + "window_secs": { "format": "int32", "type": "integer" } @@ -471,7 +463,7 @@ "description": "Configuration for an endpoint availability SLI.", "properties": { "endpoints_monitored": { - "description": "The endpoints that are monitored by this SLI.", + "description": "the API endpoints to monitor in the SLO. If this is left empty then all\nendpoints will be monitored.", "items": { "type": "string" }, @@ -498,7 +490,7 @@ "description": "Configuration for an endpoint latency SLI.", "properties": { "endpoints_monitored": { - "description": "The endpoints that are monitored by this SLI.", + "description": "the API endpoints to monitor in the SLO. If this is left empty then all\nendpoints will be monitored.", "items": { "type": "string" }, @@ -1178,6 +1170,10 @@ "properties": { "log_control_config": { "$ref": "#/definitions/configunstableLogControlConfig" + }, + "dry_run": { + "description": "If true, the LogControlConfig will not be created, and no response LogControlConfig will be returned. The response will return an error if the given LogControlConfig is invalid.", + "type": "boolean" } }, "type": "object" @@ -1915,6 +1911,13 @@ }, "endpoint_latency": { "$ref": "#/definitions/SLIEndpointLatencyConfig" + }, + "custom_dimension_labels": { + "description": "Custom dimensions are used to configure additional labels to export from\nthe underlying queries. This feature provides a logical budget to group\nunique combination of dimensions. For example, if you want to track a\nbudget per endpoint, add the endpoint label as a dimension. These dimensions\nare provided on the top-level SLI so that queryful SLOs will receive them\nin `.GroupBy`.", + "items": { + "type": "string" + }, + "type": "array" } }, "type": "object" @@ -2438,7 +2441,7 @@ }, "configunstableUpdateLogControlConfigResponse": { "properties": { - "log_control_configconfig": { + "log_control_config": { "$ref": "#/definitions/configunstableLogControlConfig" } }, diff --git a/chronosphere/pkg/configv1/models/allocation_threshold.go b/chronosphere/pkg/configv1/models/allocation_threshold.go new file mode 100644 index 0000000..38b5997 --- /dev/null +++ b/chronosphere/pkg/configv1/models/allocation_threshold.go @@ -0,0 +1,55 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// AllocationThreshold allocation threshold +// +// swagger:model AllocationThreshold +type AllocationThreshold struct { + + // Threshold expressed as a percent of the license allocated to a pool. + // A value of `100` represents a threshold that is the pool's full allocation. + // Values over `100` indicate thresholds that exceed the pool's allocation. + // For example, a value of `50` represents a threshold that is half the pool's + // allocation and a value of `200` represents a threshold that is double the + // pool's allocation. + PercentOfPoolAllocation float64 `json:"percent_of_pool_allocation,omitempty"` +} + +// Validate validates this allocation threshold +func (m *AllocationThreshold) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this allocation threshold based on context it is used +func (m *AllocationThreshold) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *AllocationThreshold) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *AllocationThreshold) UnmarshalBinary(b []byte) error { + var res AllocationThreshold + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/chronosphere/pkg/configv1/models/allocation_thresholds.go b/chronosphere/pkg/configv1/models/allocation_thresholds.go new file mode 100644 index 0000000..626b298 --- /dev/null +++ b/chronosphere/pkg/configv1/models/allocation_thresholds.go @@ -0,0 +1,239 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// AllocationThresholds Thresholds define strict quota limits for each metrics license. +// **This feature is part of pre-release functionality and is subject to change.** +// +// swagger:model AllocationThresholds +type AllocationThresholds struct { + + // all priorities + AllPriorities *AllocationThreshold `json:"all_priorities,omitempty"` + + // default and low priority + DefaultAndLowPriority *AllocationThreshold `json:"default_and_low_priority,omitempty"` + + // license + License ResourcePoolsLicense `json:"license,omitempty"` + + // low priority + LowPriority *AllocationThreshold `json:"low_priority,omitempty"` +} + +// Validate validates this allocation thresholds +func (m *AllocationThresholds) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAllPriorities(formats); err != nil { + res = append(res, err) + } + + if err := m.validateDefaultAndLowPriority(formats); err != nil { + res = append(res, err) + } + + if err := m.validateLicense(formats); err != nil { + res = append(res, err) + } + + if err := m.validateLowPriority(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *AllocationThresholds) validateAllPriorities(formats strfmt.Registry) error { + if swag.IsZero(m.AllPriorities) { // not required + return nil + } + + if m.AllPriorities != nil { + if err := m.AllPriorities.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("all_priorities") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("all_priorities") + } + return err + } + } + + return nil +} + +func (m *AllocationThresholds) validateDefaultAndLowPriority(formats strfmt.Registry) error { + if swag.IsZero(m.DefaultAndLowPriority) { // not required + return nil + } + + if m.DefaultAndLowPriority != nil { + if err := m.DefaultAndLowPriority.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("default_and_low_priority") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("default_and_low_priority") + } + return err + } + } + + return nil +} + +func (m *AllocationThresholds) validateLicense(formats strfmt.Registry) error { + if swag.IsZero(m.License) { // not required + return nil + } + + if err := m.License.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("license") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("license") + } + return err + } + + return nil +} + +func (m *AllocationThresholds) validateLowPriority(formats strfmt.Registry) error { + if swag.IsZero(m.LowPriority) { // not required + return nil + } + + if m.LowPriority != nil { + if err := m.LowPriority.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("low_priority") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("low_priority") + } + return err + } + } + + return nil +} + +// ContextValidate validate this allocation thresholds based on the context it is used +func (m *AllocationThresholds) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateAllPriorities(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateDefaultAndLowPriority(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateLicense(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateLowPriority(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *AllocationThresholds) contextValidateAllPriorities(ctx context.Context, formats strfmt.Registry) error { + + if m.AllPriorities != nil { + if err := m.AllPriorities.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("all_priorities") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("all_priorities") + } + return err + } + } + + return nil +} + +func (m *AllocationThresholds) contextValidateDefaultAndLowPriority(ctx context.Context, formats strfmt.Registry) error { + + if m.DefaultAndLowPriority != nil { + if err := m.DefaultAndLowPriority.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("default_and_low_priority") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("default_and_low_priority") + } + return err + } + } + + return nil +} + +func (m *AllocationThresholds) contextValidateLicense(ctx context.Context, formats strfmt.Registry) error { + + if err := m.License.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("license") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("license") + } + return err + } + + return nil +} + +func (m *AllocationThresholds) contextValidateLowPriority(ctx context.Context, formats strfmt.Registry) error { + + if m.LowPriority != nil { + if err := m.LowPriority.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("low_priority") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("low_priority") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *AllocationThresholds) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *AllocationThresholds) UnmarshalBinary(b []byte) error { + var res AllocationThresholds + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/chronosphere/pkg/configv1/models/configv1_rollup_rule.go b/chronosphere/pkg/configv1/models/configv1_rollup_rule.go index a322887..2ffa0dd 100644 --- a/chronosphere/pkg/configv1/models/configv1_rollup_rule.go +++ b/chronosphere/pkg/configv1/models/configv1_rollup_rule.go @@ -34,26 +34,59 @@ type Configv1RollupRule struct { // Format: date-time CreatedAt strfmt.DateTime `json:"created_at,omitempty"` - // Defines whether to automatically generate drop rules for this rollup. + // Defines whether to automatically generate drop rules for this rollup rule. + // Set to `true` to remove raw metrics that match this rollup rule. Default: `false`. DropRaw bool `json:"drop_raw,omitempty"` - // Enables expansive label matching behavior for the provided filters and - // label_policy.keep or graphite_label_policy.replace (if set). By default - // (expansive_match=false), a series matches and aggregates only if each label - // defined by filters and label_policy.keep or graphite_label_policy.replace - // (respectively) exist in said series. Setting expansive_match=true removes - // this restriction. + // A series matches and aggregates only if each label defined by filters and + // `label_policy.keep` or `graphite_label_policy.replace` (respectively) exist in + // the series. Setting `expansive_match=true` removes this restriction. Default: + // `expansive_match=false`. + // + // If `false`, a series matches and aggregates only if each label defined by the + // provided `filters` and the `label_policy.keep` or + // `graphite_label_policy.replace` settings exist in the series. ExpansiveMatch bool `json:"expansive_match,omitempty"` - // Filters that determine to which metrics to apply the rule. + // Filters incoming metrics by label. If multiple label filters are specified, an + // incoming metric must match every label filter to match the rule. Label values + // support glob patterns, including matching multiple patterns with an `OR`, such + // as `service:{svc1,svc2}`. These special filters are available for matching + // metrics by non-label request metadata: + // * `__metric_type__`: Matches the incoming metric's [Observability Platform + // metric + // type](https://docs.chronosphere.io/control/shaping/types#observability-platform-types). + // This is the recommended method for filtering on metric type. Valid values: + // `cumulative_counter`, `cumulative_exponential_histogram`, `delta_counter`, + // `delta_exponential_histogram`, `gauge`, `measurement`. + // * `__metric_source__`: Matches the incoming metric's [source + // format](https://docs.chronosphere.io/control/shaping/types#supported-formats). + // Valid values: `carbon`, `chrono_gcp`, `dogstatsd`, `open_metrics`, + // `open_telemetry`, `prometheus`, `signalfx`, `statsd`, `wavefront`. + // * `__m3_prom_type__`: When ingesting with Prometheus, matches the incoming + // metric's [Prometheus metric + // type](https://docs.chronosphere.io/control/shaping/types#prometheus). Valid + // values: `counter`, `gauge`, `histogram`, `gauge_histogram`, `summary`, + // `info`, `state_set`, `quantile`. + // * `__otel_type__`: When ingesting with OpenTelemetry, matches on the incoming + // metric's [OpenTelemetry metric type](https://docs.chronosphere.io/control/shaping/types#opentelemetry). + // Valid values: `sum`, `monotonic_sum`, `gauge`, `histogram`, `exp_histogram`, + // `summary`. + // For example, the following filter matches any cumulative counter metric with a + // `service=gateway` label whose metric name starts with `http_requests_`: + // ``` + // __metric_type__:cumulative_counter service:gateway __name__:http_requests_* + // ``` Filters []*Configv1LabelFilter `json:"filters"` // graphite label policy GraphiteLabelPolicy *RollupRuleGraphiteLabelPolicy `json:"graphite_label_policy,omitempty"` - // Interval between aggregated data points, equivalent to the resolution - // field in storage policy. If set, then the storage_policy field can't be - // set. + // The distance in time between aggregated data points. Intervals are based on your + // [retention policy](https://docs.chronosphere.io/administer/licensing#retention-policies). + // Use this optional field to set a custom interval. + // This field was known as `storage_policies` in version + // 0.286.0-2023-01-06-release.1 and earlier. Interval string `json:"interval,omitempty"` // label policy @@ -62,7 +95,7 @@ type Configv1RollupRule struct { // label replace LabelReplace RollupRuleLabelReplace `json:"label_replace,omitempty"` - // Name of the new metric created as a result of the rollup. + // This field is optional for Graphite rollup rules. MetricName string `json:"metric_name,omitempty"` // metric type diff --git a/chronosphere/pkg/configv1/models/configv1_trace_behavior_config.go b/chronosphere/pkg/configv1/models/configv1_trace_behavior_config.go index c78a4da..d6500da 100644 --- a/chronosphere/pkg/configv1/models/configv1_trace_behavior_config.go +++ b/chronosphere/pkg/configv1/models/configv1_trace_behavior_config.go @@ -60,7 +60,7 @@ type Configv1TraceBehaviorConfig struct { // List of assignments for the preview behavior. The // referenced behaviors are in preview mode for the assigned dataset. // You can assign only one preview behavior to a dataset. - PreviewBehaviorAssignments []*TraceBehaviorConfigMainBehaviorAssignment `json:"preview_behavior_assignments"` + PreviewBehaviorAssignments []*TraceBehaviorConfigOverrideBehaviorAssignment `json:"preview_behavior_assignments"` // Timestamp of when the TraceBehaviorConfig was last updated. Cannot be set by clients. // Read Only: true diff --git a/chronosphere/pkg/configv1/models/drop_rule_conditional_rate_based_drop.go b/chronosphere/pkg/configv1/models/drop_rule_conditional_rate_based_drop.go index 57a7406..f0c28b9 100644 --- a/chronosphere/pkg/configv1/models/drop_rule_conditional_rate_based_drop.go +++ b/chronosphere/pkg/configv1/models/drop_rule_conditional_rate_based_drop.go @@ -12,7 +12,8 @@ import ( "github.com/go-openapi/swag" ) -// DropRuleConditionalRateBasedDrop drop rule conditional rate based drop +// DropRuleConditionalRateBasedDrop No longer supported and cannot be used. +// Defines behavior for conditional drop policies. // // swagger:model DropRuleConditionalRateBasedDrop type DropRuleConditionalRateBasedDrop struct { diff --git a/chronosphere/pkg/configv1/models/resource_pools_license.go b/chronosphere/pkg/configv1/models/resource_pools_license.go index 38be18f..abee4db 100644 --- a/chronosphere/pkg/configv1/models/resource_pools_license.go +++ b/chronosphere/pkg/configv1/models/resource_pools_license.go @@ -36,6 +36,12 @@ const ( // ResourcePoolsLicensePERSISTEDWRITESHISTOGRAM captures enum value "PERSISTED_WRITES_HISTOGRAM" ResourcePoolsLicensePERSISTEDWRITESHISTOGRAM ResourcePoolsLicense = "PERSISTED_WRITES_HISTOGRAM" + // ResourcePoolsLicensePERSISTEDCARDINALITYSTANDARD captures enum value "PERSISTED_CARDINALITY_STANDARD" + ResourcePoolsLicensePERSISTEDCARDINALITYSTANDARD ResourcePoolsLicense = "PERSISTED_CARDINALITY_STANDARD" + + // ResourcePoolsLicensePERSISTEDCARDINALITYHISTOGRAM captures enum value "PERSISTED_CARDINALITY_HISTOGRAM" + ResourcePoolsLicensePERSISTEDCARDINALITYHISTOGRAM ResourcePoolsLicense = "PERSISTED_CARDINALITY_HISTOGRAM" + // ResourcePoolsLicenseMATCHEDWRITESSTANDARD captures enum value "MATCHED_WRITES_STANDARD" ResourcePoolsLicenseMATCHEDWRITESSTANDARD ResourcePoolsLicense = "MATCHED_WRITES_STANDARD" @@ -48,7 +54,7 @@ var resourcePoolsLicenseEnum []interface{} func init() { var res []ResourcePoolsLicense - if err := json.Unmarshal([]byte(`["PERSISTED_WRITES_STANDARD","PERSISTED_WRITES_HISTOGRAM","MATCHED_WRITES_STANDARD","MATCHED_WRITES_HISTOGRAM"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["PERSISTED_WRITES_STANDARD","PERSISTED_WRITES_HISTOGRAM","PERSISTED_CARDINALITY_STANDARD","PERSISTED_CARDINALITY_HISTOGRAM","MATCHED_WRITES_STANDARD","MATCHED_WRITES_HISTOGRAM"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/chronosphere/pkg/configv1/swagger.json b/chronosphere/pkg/configv1/swagger.json index 4ad7668..0c0607c 100644 --- a/chronosphere/pkg/configv1/swagger.json +++ b/chronosphere/pkg/configv1/swagger.json @@ -15,6 +15,34 @@ }, "type": "object" }, + "AllocationThreshold": { + "properties": { + "percent_of_pool_allocation": { + "description": "Threshold expressed as a percent of the license allocated to a pool.\nA value of `100` represents a threshold that is the pool's full allocation.\nValues over `100` indicate thresholds that exceed the pool's allocation.\nFor example, a value of `50` represents a threshold that is half the pool's\nallocation and a value of `200` represents a threshold that is double the\npool's allocation.", + "format": "double", + "type": "number" + } + }, + "type": "object" + }, + "AllocationThresholds": { + "properties": { + "license": { + "$ref": "#/definitions/ResourcePoolsLicense" + }, + "all_priorities": { + "$ref": "#/definitions/AllocationThreshold" + }, + "default_and_low_priority": { + "$ref": "#/definitions/AllocationThreshold" + }, + "low_priority": { + "$ref": "#/definitions/AllocationThreshold" + } + }, + "title": "Thresholds define strict quota limits for each metrics license.\n**This feature is part of pre-release functionality and is subject to change.**", + "type": "object" + }, "ConditionOp": { "enum": [ "GEQ", @@ -482,6 +510,7 @@ "type": "object" }, "DropRuleConditionalRateBasedDrop": { + "description": "No longer supported and cannot be used.\nDefines behavior for conditional drop policies.", "properties": { "enabled": { "description": "Enables rate-based metric dropping.", @@ -1497,6 +1526,8 @@ "enum": [ "PERSISTED_WRITES_STANDARD", "PERSISTED_WRITES_HISTOGRAM", + "PERSISTED_CARDINALITY_STANDARD", + "PERSISTED_CARDINALITY_HISTOGRAM", "MATCHED_WRITES_STANDARD", "MATCHED_WRITES_HISTOGRAM" ], @@ -4365,14 +4396,14 @@ "type": "string" }, "filters": { - "description": "Filters that determine to which metrics to apply the rule.", + "description": "Filters incoming metrics by label. If multiple label filters are specified, an\nincoming metric must match every label filter to match the rule. Label values\nsupport glob patterns, including matching multiple patterns with an `OR`, such\nas `service:{svc1,svc2}`. These special filters are available for matching\nmetrics by non-label request metadata:\n * `__metric_type__`: Matches the incoming metric's [Observability Platform\n metric\n type](https://docs.chronosphere.io/control/shaping/types#observability-platform-types).\n This is the recommended method for filtering on metric type. Valid values:\n `cumulative_counter`, `cumulative_exponential_histogram`, `delta_counter`,\n `delta_exponential_histogram`, `gauge`, `measurement`.\n * `__metric_source__`: Matches the incoming metric's [source\n format](https://docs.chronosphere.io/control/shaping/types#supported-formats).\n Valid values: `carbon`, `chrono_gcp`, `dogstatsd`, `open_metrics`,\n `open_telemetry`, `prometheus`, `signalfx`, `statsd`, `wavefront`.\n * `__m3_prom_type__`: When ingesting with Prometheus, matches the incoming\n metric's [Prometheus metric\n type](https://docs.chronosphere.io/control/shaping/types#prometheus). Valid\n values: `counter`, `gauge`, `histogram`, `gauge_histogram`, `summary`,\n `info`, `state_set`, `quantile`.\n * `__otel_type__`: When ingesting with OpenTelemetry, matches on the incoming\n metric's [OpenTelemetry metric type](https://docs.chronosphere.io/control/shaping/types#opentelemetry).\n Valid values: `sum`, `monotonic_sum`, `gauge`, `histogram`, `exp_histogram`,\n `summary`.\nFor example, the following filter matches any cumulative counter metric with a\n`service=gateway` label whose metric name starts with `http_requests_`:\n```\n__metric_type__:cumulative_counter service:gateway __name__:http_requests_*\n```", "items": { "$ref": "#/definitions/configv1LabelFilter" }, "type": "array" }, "metric_name": { - "description": "Name of the new metric created as a result of the rollup.", + "description": "This field is optional for Graphite rollup rules.", "type": "string" }, "metric_type": { @@ -4385,11 +4416,11 @@ "$ref": "#/definitions/configv1RollupRuleStoragePolicy" }, "interval": { - "description": "Interval between aggregated data points, equivalent to the resolution\nfield in storage policy. If set, then the storage_policy field can't be\nset.", + "description": "The distance in time between aggregated data points. Intervals are based on your\n[retention policy](https://docs.chronosphere.io/administer/licensing#retention-policies).\nUse this optional field to set a custom interval.\nThis field was known as `storage_policies` in version\n0.286.0-2023-01-06-release.1 and earlier.", "type": "string" }, "expansive_match": { - "description": "Enables expansive label matching behavior for the provided filters and\nlabel_policy.keep or graphite_label_policy.replace (if set). By default\n(expansive_match=false), a series matches and aggregates only if each label\ndefined by filters and label_policy.keep or graphite_label_policy.replace\n(respectively) exist in said series. Setting expansive_match=true removes\nthis restriction.", + "description": "A series matches and aggregates only if each label defined by filters and\n`label_policy.keep` or `graphite_label_policy.replace` (respectively) exist in\nthe series. Setting `expansive_match=true` removes this restriction. Default:\n`expansive_match=false`.\n\nIf `false`, a series matches and aggregates only if each label defined by the\nprovided `filters` and the `label_policy.keep` or\n`graphite_label_policy.replace` settings exist in the series.", "type": "boolean" }, "add_metric_type_label": { @@ -4397,7 +4428,7 @@ "type": "boolean" }, "drop_raw": { - "description": "Defines whether to automatically generate drop rules for this rollup.", + "description": "Defines whether to automatically generate drop rules for this rollup rule.\nSet to `true` to remove raw metrics that match this rollup rule. Default: `false`.", "type": "boolean" }, "label_policy": { @@ -4614,7 +4645,7 @@ "preview_behavior_assignments": { "description": "List of assignments for the preview behavior. The\nreferenced behaviors are in preview mode for the assigned dataset.\nYou can assign only one preview behavior to a dataset.", "items": { - "$ref": "#/definitions/TraceBehaviorConfigMainBehaviorAssignment" + "$ref": "#/definitions/TraceBehaviorConfigOverrideBehaviorAssignment" }, "type": "array" } diff --git a/chronosphere/resource_slo.go b/chronosphere/resource_slo.go index eecdcb3..1abdf4d 100644 --- a/chronosphere/resource_slo.go +++ b/chronosphere/resource_slo.go @@ -111,6 +111,7 @@ func (sloConverter) toModel(s *intschema.Slo) (*models.ConfigunstableSLO, error) CustomIndicator: customIndicator, EndpointAvailability: endpointAvailability, EndpointLatency: endpointLatency, + CustomDimensionLabels: s.Sli.CustomDimensionLabels, }, SignalGrouping: unstableMonitorSignalGroupingToModel(s.SignalGrouping), Annotations: s.Annotations, @@ -174,6 +175,7 @@ func (sloConverter) fromModel( CustomIndicator: customIndicator, EndpointAvailability: endpointAvailability, EndpointLatency: endpointLatency, + CustomDimensionLabels: s.Sli.CustomDimensionLabels, }, SignalGrouping: unstableMonitorSignalGroupingFromModel(s.SignalGrouping), Annotations: s.Annotations, diff --git a/chronosphere/tfschema/slo.go b/chronosphere/tfschema/slo.go index 2d41531..e4d9a22 100644 --- a/chronosphere/tfschema/slo.go +++ b/chronosphere/tfschema/slo.go @@ -144,6 +144,11 @@ var SLI = map[string]*schema.Schema{ Schema: SloEndpointLatency, }, }, + "custom_dimension_labels": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, } var SloEndpointAvailability = map[string]*schema.Schema{ diff --git a/examples/slo/main.tf b/examples/slo/main.tf index 1ec5284..c1a5654 100644 --- a/examples/slo/main.tf +++ b/examples/slo/main.tf @@ -40,6 +40,7 @@ resource "chronosphere_slo" "slo" { bad_query_template = "sum(rate(http_request_duration_seconds_count{error=\"true\"}[{{ .Window }}]))" total_query_template = "sum(rate(http_request_duration_seconds_count[{{ .Window }}]))" } + custom_dimension_labels = ["label1", "label2"] } }