Alerting/Annotations: Prevent panics from composite store jobs from crashing Grafana (#83459)
* Don't directly use pointer to json * Don't crash entire process if a store job panics * Add debug logs when failing to parse/handle Loki entries
This commit is contained in:
@@ -69,6 +69,10 @@ func NewLokiHistorianStore(cfg setting.UnifiedAlertingStateHistorySettings, ft f
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LokiHistorianStore) Type() string {
|
||||
return "loki"
|
||||
}
|
||||
|
||||
func (r *LokiHistorianStore) Get(ctx context.Context, query *annotations.ItemQuery, accessResources *accesscontrol.AccessResources) ([]*annotations.ItemDTO, error) {
|
||||
if query.Type == "annotation" {
|
||||
return make([]*annotations.ItemDTO, 0), nil
|
||||
@@ -124,6 +128,7 @@ func (r *LokiHistorianStore) annotationsFromStream(stream historian.Stream, ac a
|
||||
err := json.Unmarshal([]byte(sample.V), &entry)
|
||||
if err != nil {
|
||||
// bad data, skip
|
||||
r.log.Debug("failed to unmarshal loki entry", "error", err, "entry", sample.V)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -135,6 +140,7 @@ func (r *LokiHistorianStore) annotationsFromStream(stream historian.Stream, ac a
|
||||
transition, err := buildTransition(entry)
|
||||
if err != nil {
|
||||
// bad data, skip
|
||||
r.log.Debug("failed to build transition", "error", err, "entry", entry)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -207,6 +213,10 @@ type number interface {
|
||||
|
||||
// numericMap converts a simplejson map[string]any to a map[string]N, where N is numeric (int or float).
|
||||
func numericMap[N number](j *simplejson.Json) (map[string]N, error) {
|
||||
if j == nil {
|
||||
return nil, fmt.Errorf("unexpected nil value")
|
||||
}
|
||||
|
||||
m, err := j.Map()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -374,7 +374,23 @@ func TestHasAccess(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestFloat64Map(t *testing.T) {
|
||||
func TestNumericMap(t *testing.T) {
|
||||
t.Run("should return error for nil value", func(t *testing.T) {
|
||||
var jsonMap *simplejson.Json
|
||||
_, err := numericMap[float64](jsonMap)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "unexpected nil value")
|
||||
})
|
||||
|
||||
t.Run("should return error for nil interface value", func(t *testing.T) {
|
||||
jsonMap := simplejson.NewFromAny(map[string]any{
|
||||
"key1": nil,
|
||||
})
|
||||
_, err := numericMap[float64](jsonMap)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "unexpected value type")
|
||||
})
|
||||
|
||||
t.Run(`should convert json string:float kv to Golang map[string]float64`, func(t *testing.T) {
|
||||
jsonMap := simplejson.NewFromAny(map[string]any{
|
||||
"key1": json.Number("1.0"),
|
||||
|
||||
Reference in New Issue
Block a user