mirror of
https://github.com/prometheus/prometheus.git
synced 2026-05-28 04:02:21 -04:00
Merge branch 'main' into fix/consul-filter-health-endpoint
Signed-off-by: Mohammad Varmazyar <mrvarmazyar@gmail.com>
This commit is contained in:
commit
207e7d9386
21 changed files with 779 additions and 488 deletions
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
* [BUGFIX] Discovery/Consul: Fix filter parameter not being applied to health service endpoint, causing Node and Node.Meta filters to be ignored. #16087
|
||||
|
||||
## 3.7.1 / 2025-10-16
|
||||
|
||||
* [BUGFIX] OTLP: Prefix `key_` to label name when translating an OTel attribute name starting with a single underscore, and keep multiple consecutive underscores in label name when translating an OTel attribute name. This reverts the breaking changes introduced in 3.7.0. #17344
|
||||
|
||||
## 3.7.0 / 2025-10-15
|
||||
|
||||
* [CHANGE] Remote-write: the following metrics are deprecated:
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
3.7.0
|
||||
3.7.1
|
||||
|
|
|
|||
|
|
@ -696,7 +696,7 @@ metric : metric_identifier label_set
|
|||
;
|
||||
|
||||
|
||||
metric_identifier: AVG | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | IDENTIFIER | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | QUANTILE | STDDEV | STDVAR | SUM | TOPK | WITHOUT | START | END | LIMITK | LIMIT_RATIO | STEP;
|
||||
metric_identifier: AVG | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | IDENTIFIER | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | QUANTILE | STDDEV | STDVAR | SUM | TOPK | WITHOUT | START | END | LIMITK | LIMIT_RATIO | STEP | ANCHORED | SMOOTHED;
|
||||
|
||||
label_set : LEFT_BRACE label_set_list RIGHT_BRACE
|
||||
{ $$ = labels.New($2...) }
|
||||
|
|
@ -953,7 +953,7 @@ counter_reset_hint : UNKNOWN_COUNTER_RESET | COUNTER_RESET | NOT_COUNTER_RESET |
|
|||
aggregate_op : AVG | BOTTOMK | COUNT | COUNT_VALUES | GROUP | MAX | MIN | QUANTILE | STDDEV | STDVAR | SUM | TOPK | LIMITK | LIMIT_RATIO;
|
||||
|
||||
// Inside of grouping options label names can be recognized as keywords by the lexer. This is a list of keywords that could also be a label name.
|
||||
maybe_label : AVG | BOOL | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | GROUP_LEFT | GROUP_RIGHT | IDENTIFIER | IGNORING | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | ON | QUANTILE | STDDEV | STDVAR | SUM | TOPK | START | END | ATAN2 | LIMITK | LIMIT_RATIO | STEP;
|
||||
maybe_label : AVG | BOOL | BOTTOMK | BY | COUNT | COUNT_VALUES | GROUP | GROUP_LEFT | GROUP_RIGHT | IDENTIFIER | IGNORING | LAND | LOR | LUNLESS | MAX | METRIC_IDENTIFIER | MIN | OFFSET | ON | QUANTILE | STDDEV | STDVAR | SUM | TOPK | START | END | ATAN2 | LIMITK | LIMIT_RATIO | STEP | ANCHORED | SMOOTHED;
|
||||
|
||||
unary_op : ADD | SUB;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -798,6 +798,28 @@ var testExpr = []struct {
|
|||
EndPos: 21,
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `anchored{job="test"}`,
|
||||
expected: &VectorSelector{
|
||||
Name: "anchored",
|
||||
LabelMatchers: []*labels.Matcher{
|
||||
MustLabelMatcher(labels.MatchEqual, "job", "test"),
|
||||
MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "anchored"),
|
||||
},
|
||||
PosRange: posrange.PositionRange{Start: 0, End: 20},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `smoothed{job="test"}`,
|
||||
expected: &VectorSelector{
|
||||
Name: "smoothed",
|
||||
LabelMatchers: []*labels.Matcher{
|
||||
MustLabelMatcher(labels.MatchEqual, "job", "test"),
|
||||
MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "smoothed"),
|
||||
},
|
||||
PosRange: posrange.PositionRange{Start: 0, End: 20},
|
||||
},
|
||||
},
|
||||
// Vector binary operations.
|
||||
{
|
||||
input: "foo * bar",
|
||||
|
|
@ -2773,6 +2795,36 @@ var testExpr = []struct {
|
|||
PosRange: posrange.PositionRange{Start: 0, End: 25},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "sum by (anchored)(some_metric)",
|
||||
expected: &AggregateExpr{
|
||||
Op: SUM,
|
||||
Expr: &VectorSelector{
|
||||
Name: "some_metric",
|
||||
LabelMatchers: []*labels.Matcher{
|
||||
MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
|
||||
},
|
||||
PosRange: posrange.PositionRange{Start: 18, End: 29},
|
||||
},
|
||||
Grouping: []string{"anchored"},
|
||||
PosRange: posrange.PositionRange{Start: 0, End: 30},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "sum by (smoothed)(some_metric)",
|
||||
expected: &AggregateExpr{
|
||||
Op: SUM,
|
||||
Expr: &VectorSelector{
|
||||
Name: "some_metric",
|
||||
LabelMatchers: []*labels.Matcher{
|
||||
MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
|
||||
},
|
||||
PosRange: posrange.PositionRange{Start: 18, End: 29},
|
||||
},
|
||||
Grouping: []string{"smoothed"},
|
||||
PosRange: posrange.PositionRange{Start: 0, End: 30},
|
||||
},
|
||||
},
|
||||
{
|
||||
input: `sum by ("foo bar")({"some.metric"})`,
|
||||
expected: &AggregateExpr{
|
||||
|
|
|
|||
|
|
@ -229,7 +229,6 @@ func (node *Call) ShortString() string {
|
|||
}
|
||||
|
||||
func (node *MatrixSelector) atOffset() (string, string) {
|
||||
// Copy the Vector selector before changing the offset
|
||||
vecSelector := node.VectorSelector.(*VectorSelector)
|
||||
offset := ""
|
||||
switch {
|
||||
|
|
@ -254,20 +253,21 @@ func (node *MatrixSelector) atOffset() (string, string) {
|
|||
|
||||
func (node *MatrixSelector) String() string {
|
||||
at, offset := node.atOffset()
|
||||
// Copy the Vector selector before changing the offset
|
||||
// Copy the Vector selector so we can modify it to not print @, offset, and other modifiers twice.
|
||||
vecSelector := *node.VectorSelector.(*VectorSelector)
|
||||
// Do not print the @ and offset twice.
|
||||
offsetVal, offsetExprVal, atVal, preproc := vecSelector.OriginalOffset, vecSelector.OriginalOffsetExpr, vecSelector.Timestamp, vecSelector.StartOrEnd
|
||||
anchored, smoothed := vecSelector.Anchored, vecSelector.Smoothed
|
||||
vecSelector.OriginalOffset = 0
|
||||
vecSelector.OriginalOffsetExpr = nil
|
||||
vecSelector.Timestamp = nil
|
||||
vecSelector.StartOrEnd = 0
|
||||
vecSelector.Anchored = false
|
||||
vecSelector.Smoothed = false
|
||||
|
||||
extendedAttribute := ""
|
||||
switch {
|
||||
case vecSelector.Anchored:
|
||||
case anchored:
|
||||
extendedAttribute = " anchored"
|
||||
case vecSelector.Smoothed:
|
||||
case smoothed:
|
||||
extendedAttribute = " smoothed"
|
||||
}
|
||||
rangeStr := model.Duration(node.Range).String()
|
||||
|
|
@ -276,8 +276,6 @@ func (node *MatrixSelector) String() string {
|
|||
}
|
||||
str := fmt.Sprintf("%s[%s]%s%s%s", vecSelector.String(), rangeStr, extendedAttribute, at, offset)
|
||||
|
||||
vecSelector.OriginalOffset, vecSelector.OriginalOffsetExpr, vecSelector.Timestamp, vecSelector.StartOrEnd = offsetVal, offsetExprVal, atVal, preproc
|
||||
|
||||
return str
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,36 @@ func TestExprString(t *testing.T) {
|
|||
{
|
||||
in: `a[1h:5m] offset 1m`,
|
||||
},
|
||||
{
|
||||
in: `a anchored`,
|
||||
},
|
||||
{
|
||||
in: `a[5m] anchored`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] anchored`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] anchored offset 1m`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] anchored @ start() offset 1m`,
|
||||
},
|
||||
{
|
||||
in: `a smoothed`,
|
||||
},
|
||||
{
|
||||
in: `a[5m] smoothed`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] smoothed`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] smoothed offset 1m`,
|
||||
},
|
||||
{
|
||||
in: `a{b="c"}[5m] smoothed @ start() offset 1m`,
|
||||
},
|
||||
{
|
||||
in: `{__name__="a"}`,
|
||||
},
|
||||
|
|
@ -222,6 +252,11 @@ func TestExprString(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
EnableExtendedRangeSelectors = true
|
||||
t.Cleanup(func() {
|
||||
EnableExtendedRangeSelectors = false
|
||||
})
|
||||
|
||||
for _, test := range inputs {
|
||||
t.Run(test.in, func(t *testing.T) {
|
||||
expr, err := ParseExpr(test.in)
|
||||
|
|
|
|||
|
|
@ -50,8 +50,10 @@ const (
|
|||
type AlertState int
|
||||
|
||||
const (
|
||||
// StateUnknown is the state of an alert that has not yet been evaluated.
|
||||
StateUnknown AlertState = iota
|
||||
// StateInactive is the state of an alert that is neither firing nor pending.
|
||||
StateInactive AlertState = iota
|
||||
StateInactive
|
||||
// StatePending is the state of an alert that has been active for less than
|
||||
// the configured threshold duration.
|
||||
StatePending
|
||||
|
|
@ -62,6 +64,8 @@ const (
|
|||
|
||||
func (s AlertState) String() string {
|
||||
switch s {
|
||||
case StateUnknown:
|
||||
return "unknown"
|
||||
case StateInactive:
|
||||
return "inactive"
|
||||
case StatePending:
|
||||
|
|
@ -530,10 +534,14 @@ func (r *AlertingRule) Eval(ctx context.Context, queryOffset time.Duration, ts t
|
|||
}
|
||||
|
||||
// State returns the maximum state of alert instances for this rule.
|
||||
// StateFiring > StatePending > StateInactive.
|
||||
// StateFiring > StatePending > StateInactive > StateUnknown.
|
||||
func (r *AlertingRule) State() AlertState {
|
||||
r.activeMtx.Lock()
|
||||
defer r.activeMtx.Unlock()
|
||||
// Check if the rule has been evaluated
|
||||
if r.evaluationTimestamp.Load().IsZero() {
|
||||
return StateUnknown
|
||||
}
|
||||
|
||||
maxState := StateInactive
|
||||
for _, a := range r.active {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ func TestAlertingRuleState(t *testing.T) {
|
|||
for i, test := range tests {
|
||||
rule := NewAlertingRule(test.name, nil, 0, 0, labels.EmptyLabels(), labels.EmptyLabels(), labels.EmptyLabels(), "", true, nil)
|
||||
rule.active = test.active
|
||||
// Set evaluation timestamp to simulate that the rule has been evaluated
|
||||
rule.SetEvaluationTimestamp(time.Now())
|
||||
got := rule.State()
|
||||
require.Equal(t, test.want, got, "test case %d unexpected AlertState, want:%d got:%d", i, test.want, got)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,11 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
|||
c.scratchBuilder.Sort()
|
||||
sortedLabels := c.scratchBuilder.Labels()
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: settings.AllowUTF8}
|
||||
labelNamer := otlptranslator.LabelNamer{
|
||||
UTF8Allowed: settings.AllowUTF8,
|
||||
UnderscoreLabelSanitization: settings.LabelNameUnderscoreSanitization,
|
||||
PreserveMultipleUnderscores: settings.LabelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
|
||||
if settings.AllowUTF8 {
|
||||
// UTF8 is allowed, so conflicts aren't possible.
|
||||
|
|
@ -118,7 +122,7 @@ func (c *PrometheusConverter) createAttributes(resource pcommon.Resource, attrib
|
|||
}
|
||||
}
|
||||
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, settings.AllowUTF8)
|
||||
err := settings.PromoteResourceAttributes.addPromotedAttributes(c.builder, resourceAttrs, labelNamer)
|
||||
if err != nil {
|
||||
return labels.EmptyLabels(), err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,15 +67,35 @@ func TestCreateAttributes(t *testing.T) {
|
|||
attrs.PutStr("metric-attr", "metric value")
|
||||
attrs.PutStr("metric-attr-other", "metric value other")
|
||||
|
||||
// Setup resources with underscores for sanitization tests
|
||||
resourceAttrsWithUnderscores := map[string]string{
|
||||
"service.name": "service name",
|
||||
"service.instance.id": "service ID",
|
||||
"_private": "private value",
|
||||
"__reserved__": "reserved value",
|
||||
"label___multi": "multi value",
|
||||
}
|
||||
resourceWithUnderscores := pcommon.NewResource()
|
||||
for k, v := range resourceAttrsWithUnderscores {
|
||||
resourceWithUnderscores.Attributes().PutStr(k, v)
|
||||
}
|
||||
attrsWithUnderscores := pcommon.NewMap()
|
||||
attrsWithUnderscores.PutStr("_metric_private", "private metric")
|
||||
attrsWithUnderscores.PutStr("metric___multi", "multi metric")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
expectedLabels labels.Labels
|
||||
name string
|
||||
resource pcommon.Resource
|
||||
attrs pcommon.Map
|
||||
scope scope
|
||||
promoteAllResourceAttributes bool
|
||||
promoteResourceAttributes []string
|
||||
promoteScope bool
|
||||
ignoreResourceAttributes []string
|
||||
ignoreAttrs []string
|
||||
labelNameUnderscoreLabelSanitization bool
|
||||
labelNamePreserveMultipleUnderscores bool
|
||||
expectedLabels labels.Labels
|
||||
}{
|
||||
{
|
||||
name: "Successful conversion without resource attribute promotion and without scope promotion",
|
||||
|
|
@ -251,6 +271,121 @@ func TestCreateAttributes(t *testing.T) {
|
|||
"otel_scope_attr2", "value2",
|
||||
),
|
||||
},
|
||||
// Label sanitization test cases
|
||||
{
|
||||
name: "Underscore sanitization enabled - prepends key_ to labels starting with single _",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Underscore sanitization disabled - keeps labels with _ as-is",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores preserved - keeps consecutive underscores",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label___multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Multiple underscores collapsed - collapses to single underscore",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options enabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: true,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"key_private", "private value",
|
||||
"label___multi", "multi value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric___multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Both sanitization options disabled",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"_private", "label___multi"},
|
||||
labelNameUnderscoreLabelSanitization: false,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"_private", "private value",
|
||||
"label_multi", "multi value",
|
||||
"_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Reserved labels (starting with __) are never modified",
|
||||
resource: resourceWithUnderscores,
|
||||
attrs: attrsWithUnderscores,
|
||||
promoteResourceAttributes: []string{"__reserved__"},
|
||||
labelNameUnderscoreLabelSanitization: true,
|
||||
labelNamePreserveMultipleUnderscores: false,
|
||||
expectedLabels: labels.FromStrings(
|
||||
"__name__", "test_metric",
|
||||
"instance", "service ID",
|
||||
"job", "service name",
|
||||
"__reserved__", "reserved value",
|
||||
"key_metric_private", "private metric",
|
||||
"metric_multi", "multi metric",
|
||||
),
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
|
@ -261,9 +396,24 @@ func TestCreateAttributes(t *testing.T) {
|
|||
PromoteResourceAttributes: tc.promoteResourceAttributes,
|
||||
IgnoreResourceAttributes: tc.ignoreResourceAttributes,
|
||||
}),
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
PromoteScopeMetadata: tc.promoteScope,
|
||||
LabelNameUnderscoreSanitization: tc.labelNameUnderscoreLabelSanitization,
|
||||
LabelNamePreserveMultipleUnderscores: tc.labelNamePreserveMultipleUnderscores,
|
||||
}
|
||||
lbls, err := c.createAttributes(resource, attrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
// Use test case specific resource/attrs if provided, otherwise use defaults
|
||||
// Check if tc.resource is initialized (non-zero) by trying to get its attributes
|
||||
testResource := resource
|
||||
testAttrs := attrs
|
||||
// For pcommon types, we can check if they're non-zero by seeing if they have attributes
|
||||
// Since zero-initialized Resource is not valid, we use a simple heuristic:
|
||||
// if the struct has been explicitly set in the test case, use it
|
||||
if tc.resource != (pcommon.Resource{}) {
|
||||
testResource = tc.resource
|
||||
}
|
||||
if tc.attrs != (pcommon.Map{}) {
|
||||
testAttrs = tc.attrs
|
||||
}
|
||||
lbls, err := c.createAttributes(testResource, testAttrs, tc.scope, settings, tc.ignoreAttrs, false, Metadata{}, model.MetricNameLabel, "test_metric")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RequireEqual(t, lbls, tc.expectedLabels)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ type Settings struct {
|
|||
// PromoteScopeMetadata controls whether to promote OTel scope metadata to metric labels.
|
||||
PromoteScopeMetadata bool
|
||||
EnableTypeAndUnitLabels bool
|
||||
// LabelNameUnderscoreSanitization controls whether to enable prepending of 'key' to labels
|
||||
// starting with '_'. Reserved labels starting with `__` are not modified.
|
||||
LabelNameUnderscoreSanitization bool
|
||||
// LabelNamePreserveMultipleUnderscores enables preserving of multiple
|
||||
// consecutive underscores in label names when AllowUTF8 is false.
|
||||
LabelNamePreserveMultipleUnderscores bool
|
||||
}
|
||||
|
||||
// PrometheusConverter converts from OTel write format to Prometheus remote write format.
|
||||
|
|
@ -305,12 +311,11 @@ func NewPromoteResourceAttributes(otlpCfg config.OTLPConfig) *PromoteResourceAtt
|
|||
}
|
||||
|
||||
// addPromotedAttributes adds labels for promoted resourceAttributes to the builder.
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, allowUTF8 bool) error {
|
||||
func (s *PromoteResourceAttributes) addPromotedAttributes(builder *labels.Builder, resourceAttributes pcommon.Map, labelNamer otlptranslator.LabelNamer) error {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: allowUTF8}
|
||||
if s.promoteAll {
|
||||
var err error
|
||||
resourceAttributes.Range(func(name string, value pcommon.Value) bool {
|
||||
|
|
|
|||
|
|
@ -680,6 +680,10 @@ func (rw *rwExporter) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) er
|
|||
AllowDeltaTemporality: rw.allowDeltaTemporality,
|
||||
LookbackDelta: rw.lookbackDelta,
|
||||
EnableTypeAndUnitLabels: rw.enableTypeAndUnitLabels,
|
||||
// For backwards compatibility.
|
||||
LabelNameUnderscoreSanitization: true,
|
||||
// For backwards compatibility.
|
||||
LabelNamePreserveMultipleUnderscores: true,
|
||||
})
|
||||
|
||||
defer func() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@prometheus-io/mantine-ui",
|
||||
"private": true,
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "vite",
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@nexucis/fuzzy": "^0.5.1",
|
||||
"@nexucis/kvsearch": "^0.9.1",
|
||||
"@prometheus-io/codemirror-promql": "0.307.0",
|
||||
"@prometheus-io/codemirror-promql": "0.307.1",
|
||||
"@reduxjs/toolkit": "^2.9.0",
|
||||
"@tabler/icons-react": "^3.35.0",
|
||||
"@tanstack/react-query": "^5.90.2",
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export const useSuspenseAPIQuery = <T>({ key, path, params }: QueryOptions) => {
|
|||
queryKey: key !== undefined ? key : [path, params],
|
||||
retry: false,
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: Infinity, // Required for suspense queries since the component is briefly unmounted when loading the data, which together with a gcTime of 0 will cause the data to be garbage collected before it can be used.
|
||||
gcTime: 0,
|
||||
queryFn: createQueryFn({ pathPrefix, path, params }),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
type RuleState = "pending" | "firing" | "inactive";
|
||||
type RuleState = "pending" | "firing" | "inactive" | "unknown";
|
||||
|
||||
export interface Alert {
|
||||
labels: Record<string, string>;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ type AlertsPageData = {
|
|||
inactive: number;
|
||||
pending: number;
|
||||
firing: number;
|
||||
unknown: number;
|
||||
};
|
||||
groups: {
|
||||
name: string;
|
||||
|
|
@ -55,6 +56,7 @@ type AlertsPageData = {
|
|||
inactive: number;
|
||||
pending: number;
|
||||
firing: number;
|
||||
unknown: number;
|
||||
};
|
||||
rules: {
|
||||
rule: AlertingRule;
|
||||
|
|
@ -82,6 +84,7 @@ const buildAlertsPageData = (
|
|||
inactive: 0,
|
||||
pending: 0,
|
||||
firing: 0,
|
||||
unknown: 0,
|
||||
},
|
||||
groups: [],
|
||||
};
|
||||
|
|
@ -92,6 +95,7 @@ const buildAlertsPageData = (
|
|||
inactive: 0,
|
||||
pending: 0,
|
||||
firing: 0,
|
||||
unknown: 0,
|
||||
};
|
||||
|
||||
for (const r of group.rules) {
|
||||
|
|
@ -109,6 +113,10 @@ const buildAlertsPageData = (
|
|||
pageData.globalCounts.pending++;
|
||||
groupCounts.pending++;
|
||||
break;
|
||||
case "unknown":
|
||||
pageData.globalCounts.unknown++;
|
||||
groupCounts.unknown++;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown rule state: ${r.state}`);
|
||||
}
|
||||
|
|
@ -239,6 +247,11 @@ export default function AlertsPage() {
|
|||
pending ({g.counts.pending})
|
||||
</Badge>
|
||||
)}
|
||||
{g.counts.unknown > 0 && (
|
||||
<Badge className={badgeClasses.healthUnknown}>
|
||||
unknown ({g.counts.unknown})
|
||||
</Badge>
|
||||
)}
|
||||
{g.counts.inactive > 0 && (
|
||||
<Badge className={badgeClasses.healthOk}>
|
||||
inactive ({g.counts.inactive})
|
||||
|
|
@ -285,7 +298,9 @@ export default function AlertsPage() {
|
|||
? panelClasses.panelHealthErr
|
||||
: r.counts.pending > 0
|
||||
? panelClasses.panelHealthWarn
|
||||
: panelClasses.panelHealthOk
|
||||
: r.rule.state === "unknown"
|
||||
? panelClasses.panelHealthUnknown
|
||||
: panelClasses.panelHealthOk
|
||||
}
|
||||
>
|
||||
<Accordion.Control
|
||||
|
|
@ -401,13 +416,15 @@ export default function AlertsPage() {
|
|||
<Stack mt="xs">
|
||||
<Group>
|
||||
<StateMultiSelect
|
||||
options={["inactive", "pending", "firing"]}
|
||||
options={["inactive", "pending", "firing", "unknown"]}
|
||||
optionClass={(o) =>
|
||||
o === "inactive"
|
||||
? badgeClasses.healthOk
|
||||
: o === "pending"
|
||||
? badgeClasses.healthWarn
|
||||
: badgeClasses.healthErr
|
||||
: o === "firing"
|
||||
? badgeClasses.healthErr
|
||||
: badgeClasses.healthUnknown
|
||||
}
|
||||
optionCount={(o) =>
|
||||
alertsPageData.globalCounts[
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@prometheus-io/codemirror-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"description": "a CodeMirror mode for the PromQL language",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"module": "dist/esm/index.js",
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/prometheus/prometheus/blob/main/web/ui/module/codemirror-promql/README.md",
|
||||
"dependencies": {
|
||||
"@prometheus-io/lezer-promql": "0.307.0",
|
||||
"@prometheus-io/lezer-promql": "0.307.1",
|
||||
"lru-cache": "^11.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@prometheus-io/lezer-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"description": "lezer-based PromQL grammar",
|
||||
"main": "dist/index.cjs",
|
||||
"type": "module",
|
||||
|
|
|
|||
14
web/ui/package-lock.json
generated
14
web/ui/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "prometheus-io",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "prometheus-io",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"workspaces": [
|
||||
"mantine-ui",
|
||||
"module/*"
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
"mantine-ui": {
|
||||
"name": "@prometheus-io/mantine-ui",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.19.0",
|
||||
"@codemirror/language": "^6.11.3",
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@nexucis/fuzzy": "^0.5.1",
|
||||
"@nexucis/kvsearch": "^0.9.1",
|
||||
"@prometheus-io/codemirror-promql": "0.307.0",
|
||||
"@prometheus-io/codemirror-promql": "0.307.1",
|
||||
"@reduxjs/toolkit": "^2.9.0",
|
||||
"@tabler/icons-react": "^3.35.0",
|
||||
"@tanstack/react-query": "^5.90.2",
|
||||
|
|
@ -87,10 +87,10 @@
|
|||
},
|
||||
"module/codemirror-promql": {
|
||||
"name": "@prometheus-io/codemirror-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@prometheus-io/lezer-promql": "0.307.0",
|
||||
"@prometheus-io/lezer-promql": "0.307.1",
|
||||
"lru-cache": "^11.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
},
|
||||
"module/lezer-promql": {
|
||||
"name": "@prometheus-io/lezer-promql",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@lezer/generator": "^1.8.0",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "prometheus-io",
|
||||
"description": "Monorepo for the Prometheus UI",
|
||||
"version": "0.307.0",
|
||||
"version": "0.307.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "bash build_ui.sh --all",
|
||||
|
|
|
|||
Loading…
Reference in a new issue