Phlare: Fix panic on empty pprof profile (#64888)

pull/64999/head
Andrej Ocenas 2 years ago committed by GitHub
parent fef0ee913c
commit 998b035d52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      pkg/tsdb/phlare/query.go
  2. 70
      pkg/tsdb/phlare/query_test.go

@ -374,16 +374,19 @@ func treeToNestedSetDataFrame(tree *ProfileTree, profileTypeID string) *data.Fra
labelField := NewEnumField("label", nil)
fileNameField := NewEnumField("fileName", nil)
walkTree(tree, func(tree *ProfileTree) {
levelField.Append(int64(tree.Level))
valueField.Append(tree.Value)
selfField.Append(tree.Self)
// todo: inline functions
// tree.Inlined
lineNumberField.Append(tree.Function.Line)
labelField.Append(tree.Function.FunctionName)
fileNameField.Append(tree.Function.FileName)
})
// Tree can be nil if profile was empty, we can still send empty frame in that case
if tree != nil {
walkTree(tree, func(tree *ProfileTree) {
levelField.Append(int64(tree.Level))
valueField.Append(tree.Value)
selfField.Append(tree.Self)
// todo: inline functions
// tree.Inlined
lineNumberField.Append(tree.Function.Line)
labelField.Append(tree.Function.FunctionName)
fileNameField.Append(tree.Function.FileName)
})
}
frame.Fields = append(frame.Fields, labelField.GetField(), fileNameField.GetField())
return frame

@ -109,42 +109,50 @@ func makeDataQuery() *backend.DataQuery {
}
func Test_treeToNestedDataFrame(t *testing.T) {
tree := &ProfileTree{
Value: 100, Level: 0, Self: 1, Function: &Function{FunctionName: "root"}, Nodes: []*ProfileTree{
{
Value: 40, Level: 1, Self: 2, Function: &Function{FunctionName: "func1", FileName: "1", Line: 1},
t.Run("sample profile tree", func(t *testing.T) {
tree := &ProfileTree{
Value: 100, Level: 0, Self: 1, Function: &Function{FunctionName: "root"}, Nodes: []*ProfileTree{
{
Value: 40, Level: 1, Self: 2, Function: &Function{FunctionName: "func1", FileName: "1", Line: 1},
},
{Value: 30, Level: 1, Self: 3, Function: &Function{FunctionName: "func2", FileName: "2", Line: 2}, Nodes: []*ProfileTree{
{Value: 15, Level: 2, Self: 4, Function: &Function{FunctionName: "func1:func3", FileName: "3", Line: 3}},
}},
},
{Value: 30, Level: 1, Self: 3, Function: &Function{FunctionName: "func2", FileName: "2", Line: 2}, Nodes: []*ProfileTree{
{Value: 15, Level: 2, Self: 4, Function: &Function{FunctionName: "func1:func3", FileName: "3", Line: 3}},
}},
},
}
}
frame := treeToNestedSetDataFrame(tree, "memory:alloc_objects:count:space:bytes")
frame := treeToNestedSetDataFrame(tree, "memory:alloc_objects:count:space:bytes")
labelConfig := &data.FieldConfig{
TypeConfig: &data.FieldTypeConfig{
Enum: &data.EnumFieldConfig{
Text: []string{"root", "func1", "func2", "func1:func3"},
labelConfig := &data.FieldConfig{
TypeConfig: &data.FieldTypeConfig{
Enum: &data.EnumFieldConfig{
Text: []string{"root", "func1", "func2", "func1:func3"},
},
},
},
}
filenameConfig := &data.FieldConfig{
TypeConfig: &data.FieldTypeConfig{
Enum: &data.EnumFieldConfig{
Text: []string{"", "1", "2", "3"},
}
filenameConfig := &data.FieldConfig{
TypeConfig: &data.FieldTypeConfig{
Enum: &data.EnumFieldConfig{
Text: []string{"", "1", "2", "3"},
},
},
},
}
require.Equal(t,
[]*data.Field{
data.NewField("level", nil, []int64{0, 1, 1, 2}),
data.NewField("value", nil, []int64{100, 40, 30, 15}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("self", nil, []int64{1, 2, 3, 4}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("line", nil, []int64{0, 1, 2, 3}),
data.NewField("label", nil, []int64{0, 1, 2, 3}).SetConfig(labelConfig),
data.NewField("fileName", nil, []int64{0, 1, 2, 3}).SetConfig(filenameConfig),
}, frame.Fields)
}
require.Equal(t,
[]*data.Field{
data.NewField("level", nil, []int64{0, 1, 1, 2}),
data.NewField("value", nil, []int64{100, 40, 30, 15}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("self", nil, []int64{1, 2, 3, 4}).SetConfig(&data.FieldConfig{Unit: "short"}),
data.NewField("line", nil, []int64{0, 1, 2, 3}),
data.NewField("label", nil, []int64{0, 1, 2, 3}).SetConfig(labelConfig),
data.NewField("fileName", nil, []int64{0, 1, 2, 3}).SetConfig(filenameConfig),
}, frame.Fields)
})
t.Run("nil profile tree", func(t *testing.T) {
frame := treeToNestedSetDataFrame(nil, "memory:alloc_objects:count:space:bytes")
require.Equal(t, 6, len(frame.Fields))
require.Equal(t, 0, frame.Fields[0].Len())
})
}
var fooProfile = &googlev1.Profile{

Loading…
Cancel
Save