mirror of
https://github.com/SigNoz/signoz.git
synced 2026-07-10 08:30:33 +01:00
Compare commits
2 Commits
worktree-j
...
nv/span-ga
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4afbaccd91 | ||
|
|
ef892f3361 |
@@ -7394,9 +7394,11 @@ components:
|
||||
op:
|
||||
$ref: '#/components/schemas/RuletypesCompareOperator'
|
||||
recoveryTarget:
|
||||
format: double
|
||||
nullable: true
|
||||
type: number
|
||||
target:
|
||||
format: double
|
||||
nullable: true
|
||||
type: number
|
||||
targetUnit:
|
||||
@@ -7680,6 +7682,7 @@ components:
|
||||
selectedQueryName:
|
||||
type: string
|
||||
target:
|
||||
format: double
|
||||
nullable: true
|
||||
type: number
|
||||
targetUnit:
|
||||
|
||||
@@ -8480,10 +8480,12 @@ export interface RuletypesBasicRuleThresholdDTO {
|
||||
op: RuletypesCompareOperatorDTO;
|
||||
/**
|
||||
* @type number,null
|
||||
* @format double
|
||||
*/
|
||||
recoveryTarget?: number | null;
|
||||
/**
|
||||
* @type number,null
|
||||
* @format double
|
||||
*/
|
||||
target: number | null;
|
||||
/**
|
||||
@@ -8677,6 +8679,7 @@ export interface RuletypesRuleConditionDTO {
|
||||
selectedQueryName?: string;
|
||||
/**
|
||||
* @type number,null
|
||||
* @format double
|
||||
*/
|
||||
target?: number | null;
|
||||
/**
|
||||
|
||||
@@ -38,7 +38,7 @@ func newTestDashboardV2(t *testing.T, orgID valuer.UUID, source Source) *Dashboa
|
||||
LineInterpolation: LineInterpolationSpline,
|
||||
LineStyle: LineStyleSolid,
|
||||
FillMode: FillModeSolid,
|
||||
SpanGaps: SpanGaps{FillLessThan: valuer.MustParseTextDuration("60s")},
|
||||
SpanGaps: SpanGaps{FillLessThan: "60s"},
|
||||
},
|
||||
Legend: Legend{Position: LegendPositionBottom, Mode: LegendModeList},
|
||||
},
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/perses/spec/go/dashboard"
|
||||
@@ -1371,7 +1370,7 @@ func TestSpanGaps(t *testing.T) {
|
||||
t.Run("defaults", func(t *testing.T) {
|
||||
var sg SpanGaps
|
||||
assert.False(t, sg.FillOnlyBelow, "expected FillOnlyBelow default false")
|
||||
assert.True(t, sg.FillLessThan.IsZero(), "expected FillLessThan default zero")
|
||||
assert.Empty(t, sg.FillLessThan, "expected FillLessThan default empty")
|
||||
})
|
||||
|
||||
t.Run("fillOnlyBelow true", func(t *testing.T) {
|
||||
@@ -1382,12 +1381,27 @@ func TestSpanGaps(t *testing.T) {
|
||||
t.Run("fillLessThan duration", func(t *testing.T) {
|
||||
sg := unmarshal(t, `{"fillOnlyBelow": false, "fillLessThan": "5m"}`)
|
||||
assert.False(t, sg.FillOnlyBelow)
|
||||
assert.Equal(t, 5*time.Minute, sg.FillLessThan.Duration())
|
||||
assert.Equal(t, "5m", sg.FillLessThan)
|
||||
})
|
||||
|
||||
t.Run("fillLessThan compound duration", func(t *testing.T) {
|
||||
sg := unmarshal(t, `{"fillLessThan": "1h30m"}`)
|
||||
assert.Equal(t, 90*time.Minute, sg.FillLessThan.Duration())
|
||||
assert.Equal(t, "1h30m", sg.FillLessThan)
|
||||
})
|
||||
|
||||
t.Run("fillLessThan day duration", func(t *testing.T) {
|
||||
sg := unmarshal(t, `{"fillLessThan": "1d"}`)
|
||||
assert.Equal(t, "1d", sg.FillLessThan)
|
||||
})
|
||||
|
||||
t.Run("invalid fillLessThan rejected on unmarshal", func(t *testing.T) {
|
||||
var sg SpanGaps
|
||||
require.Error(t, json.Unmarshal([]byte(`{"fillLessThan": "not-a-duration"}`), &sg))
|
||||
})
|
||||
|
||||
t.Run("non-positive fillLessThan rejected on unmarshal", func(t *testing.T) {
|
||||
var sg SpanGaps
|
||||
require.Error(t, json.Unmarshal([]byte(`{"fillLessThan": "0s"}`), &sg))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
qb "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/SigNoz/signoz/pkg/valuer"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/swaggest/jsonschema-go"
|
||||
)
|
||||
|
||||
@@ -621,8 +622,35 @@ func (fm *FillMode) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
type SpanGaps struct {
|
||||
FillOnlyBelow bool `json:"fillOnlyBelow" description:"Controls whether lines connect across null values. When false (default), all gaps are connected. When true, only gaps smaller than fillLessThan are connected."`
|
||||
FillLessThan valuer.TextDuration `json:"fillLessThan" description:"The maximum gap size to connect when fillOnlyBelow is true. Gaps larger than this duration are left disconnected."`
|
||||
FillOnlyBelow bool `json:"fillOnlyBelow" description:"Controls whether lines connect across null values. When false (default), all gaps are connected. When true, only gaps smaller than fillLessThan are connected."`
|
||||
FillLessThan string `json:"fillLessThan" description:"The maximum gap size to connect when fillOnlyBelow is true. Gaps larger than this duration are left disconnected."`
|
||||
}
|
||||
|
||||
func (sg *SpanGaps) UnmarshalJSON(data []byte) error {
|
||||
type alias SpanGaps
|
||||
var tmp alias
|
||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||
return errors.WrapInvalidInputf(err, ErrCodeDashboardInvalidInput, "invalid spanGaps")
|
||||
}
|
||||
*sg = SpanGaps(tmp)
|
||||
return sg.validate()
|
||||
}
|
||||
|
||||
// validate checks that FillLessThan, when set, is a valid positive duration.
|
||||
// It uses prometheus's parser so day/week/year units (e.g. "1d") are accepted;
|
||||
// time.ParseDuration caps at hours.
|
||||
func (sg SpanGaps) validate() error {
|
||||
if sg.FillLessThan == "" {
|
||||
return nil
|
||||
}
|
||||
d, err := model.ParseDuration(sg.FillLessThan)
|
||||
if err != nil {
|
||||
return errors.WrapInvalidInputf(err, ErrCodeDashboardInvalidInput, "invalid spanGaps.fillLessThan duration %q", sg.FillLessThan)
|
||||
}
|
||||
if d <= 0 {
|
||||
return errors.NewInvalidInputf(ErrCodeDashboardInvalidInput, "spanGaps.fillLessThan duration must be positive, got %q", sg.FillLessThan)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PrecisionOption struct{ valuer.String }
|
||||
|
||||
@@ -112,7 +112,7 @@ type AlertCompositeQuery struct {
|
||||
type RuleCondition struct {
|
||||
CompositeQuery *AlertCompositeQuery `json:"compositeQuery" required:"true"`
|
||||
CompareOperator CompareOperator `json:"op,omitzero"`
|
||||
Target *float64 `json:"target,omitempty"`
|
||||
Target *float64 `json:"target,omitempty" format:"double"`
|
||||
AlertOnAbsent bool `json:"alertOnAbsent,omitempty"`
|
||||
AbsentFor uint64 `json:"absentFor,omitempty"`
|
||||
MatchType MatchType `json:"matchType,omitzero"`
|
||||
@@ -187,4 +187,3 @@ func (rc *RuleCondition) String() string {
|
||||
data, _ := json.Marshal(*rc)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
|
||||
@@ -134,9 +134,9 @@ type RuleThreshold interface {
|
||||
|
||||
type BasicRuleThreshold struct {
|
||||
Name string `json:"name" required:"true"`
|
||||
TargetValue *float64 `json:"target" required:"true"`
|
||||
TargetValue *float64 `json:"target" required:"true" format:"double"`
|
||||
TargetUnit string `json:"targetUnit"`
|
||||
RecoveryTarget *float64 `json:"recoveryTarget"`
|
||||
RecoveryTarget *float64 `json:"recoveryTarget" format:"double"`
|
||||
MatchType MatchType `json:"matchType" required:"true"`
|
||||
CompareOperator CompareOperator `json:"op" required:"true"`
|
||||
Channels []string `json:"channels"`
|
||||
|
||||
Reference in New Issue
Block a user