Skip to content

Commit 93cff7a

Browse files
Fix agent panic on prometheus_text metric parsing (#5166)
Set model.NameValidationScheme to LegacyValidation in an init() to prevent the prometheus/common text parser from panicking when the validation scheme is unset. Additionally, wrap extractMetrics in a deferred recover so any future parsing panic cannot crash the agent. Signed-off-by: Sarvodaya Kumar <sarvodaya.kumar.ctr@sumologic.com>
1 parent 48a7383 commit 93cff7a

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

agent/check_handler.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,18 @@ func (a *Agent) sendFailure(event *corev2.Event, err error) {
425425
}
426426
}
427427

428-
func extractMetrics(event *corev2.Event) []*corev2.MetricPoint {
428+
func extractMetrics(event *corev2.Event) (points []*corev2.MetricPoint) {
429+
defer func() {
430+
if r := recover(); r != nil {
431+
logger.WithFields(logrus.Fields{
432+
"namespace": event.Check.Namespace,
433+
"check": event.Check.Name,
434+
"format": event.Check.OutputMetricFormat,
435+
}).Errorf("recovered from panic during metric extraction: %v", r)
436+
points = nil
437+
}
438+
}()
439+
429440
var transformer Transformer
430441
if !event.HasCheck() {
431442
logger.WithError(transformers.ErrMetricExtraction).Error("event must contain a check to parse and extract metrics")

agent/check_handler_internal_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,24 @@ func TestExtractMetrics(t *testing.T) {
588588
}
589589
}
590590

591+
func TestExtractMetricsPanicRecovery(t *testing.T) {
592+
event := &corev2.Event{
593+
Check: &corev2.Check{
594+
ObjectMeta: corev2.ObjectMeta{
595+
Name: "panic-check",
596+
Namespace: "default",
597+
},
598+
Output: "bogus output",
599+
OutputMetricFormat: corev2.PrometheusOutputMetricFormat,
600+
},
601+
}
602+
603+
assert.NotPanics(t, func() {
604+
metrics := extractMetrics(event)
605+
_ = metrics
606+
})
607+
}
608+
591609
func TestFailOnAssetCheckWithDisabledAssets(t *testing.T) {
592610
config, cleanup := FixtureConfig()
593611
defer cleanup()

agent/transformers/prometheus.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ import (
1212
"github.com/sirupsen/logrus"
1313
)
1414

15+
func init() {
16+
model.NameValidationScheme = model.LegacyValidation
17+
}
18+
1519
const (
1620
PromTypeTagName = "prom_type"
1721
PromHelpTagName = "prom_help"

agent/transformers/prometheus_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,20 @@ func TestParsePromTags(t *testing.T) {
214214
}
215215
}
216216

217+
func TestParsePromValidationScheme(t *testing.T) {
218+
assert := assert.New(t)
219+
220+
event := types.FixtureEvent("test", "test")
221+
event.Check.Output = "# HELP node_cpu_seconds_total Seconds the CPUs spent in each mode.\n# TYPE node_cpu_seconds_total counter\nnode_cpu_seconds_total{cpu=\"0\",mode=\"idle\"} 123456.78\n"
222+
223+
assert.NotPanics(func() {
224+
prom := ParseProm(event)
225+
assert.NotEmpty(prom)
226+
points := prom.Transform()
227+
assert.Equal("node_cpu_seconds_total", points[0].Name)
228+
})
229+
}
230+
217231
func TestTransformProm(t *testing.T) {
218232
assert := assert.New(t)
219233
ts := time.Now().Unix()

0 commit comments

Comments
 (0)