diff --git a/pkg/parcacol/querier.go b/pkg/parcacol/querier.go index 2ad7bc86a6a..37d8fd92f73 100644 --- a/pkg/parcacol/querier.go +++ b/pkg/parcacol/querier.go @@ -969,6 +969,20 @@ func (q *Querier) SymbolizeArrowRecord( defer valuePerSecondColumn.Release() } + indices = schema.FieldIndices(profile.ColumnTimestamp) + var timestampColumn *array.Int64 + if len(indices) != 1 { + timestampColumn = arrowutils.MakeNullArray(q.pool, arrow.PrimitiveTypes.Int64, valueColumn.Len()).(*array.Int64) + defer timestampColumn.Release() + } + + indices = schema.FieldIndices(profile.ColumnDuration) + var durationColumn *array.Int64 + if len(indices) != 1 { + durationColumn = arrowutils.MakeNullArray(q.pool, arrow.PrimitiveTypes.Int64, valueColumn.Len()).(*array.Int64) + defer durationColumn.Release() + } + profileLabels := []arrow.Field{} profileLabelColumns := []arrow.Array{} for i, field := range schema.Fields() { @@ -984,14 +998,17 @@ func (q *Querier) SymbolizeArrowRecord( } defer locationsRecord.Release() - columns := make([]arrow.Array, len(profileLabels)+3) // +3 for stacktrace locations, value and diff + columns := make([]arrow.Array, len(profileLabels)+5) // +5 for stacktrace locations, value, diff, timestamp and duration copy(columns, profileLabelColumns) - columns[len(columns)-3] = locationsRecord.Column(0) - columns[len(columns)-2] = valueColumn + columns[len(columns)-5] = locationsRecord.Column(0) + columns[len(columns)-4] = valueColumn diffColumn := CreateDiffColumn(q.pool, int(r.NumRows())) defer diffColumn.Release() - columns[len(columns)-1] = diffColumn + columns[len(columns)-3] = diffColumn + + columns[len(columns)-2] = timestampColumn + columns[len(columns)-1] = durationColumn res[i] = array.NewRecord(profile.ArrowSchema(profileLabels), columns, r.NumRows()) } diff --git a/pkg/profile/profile.go b/pkg/profile/profile.go index 76aecd97492..2f8b61db46e 100644 --- a/pkg/profile/profile.go +++ b/pkg/profile/profile.go @@ -76,7 +76,7 @@ func ArrowSamplesField(profileLabelFields []arrow.Field) []arrow.Field { fields := make([]arrow.Field, numFields) copy(fields, profileLabelFields) fields[numFields-5] = LocationsField - fields[numFields-3] = arrow.Field{ + fields[numFields-4] = arrow.Field{ Name: "value", Type: arrow.PrimitiveTypes.Int64, } diff --git a/pkg/query/flamegraph_arrow_test.go b/pkg/query/flamegraph_arrow_test.go index 7a128ca8d1e..b8abba8c9e2 100644 --- a/pkg/query/flamegraph_arrow_test.go +++ b/pkg/query/flamegraph_arrow_test.go @@ -62,6 +62,7 @@ type flamegraphRow struct { Cumulative uint8 Flat uint8 Diff int8 + GroupByMetadata map[string]string } type flamegraphColumns struct { @@ -80,6 +81,7 @@ type flamegraphColumns struct { cumulative []uint8 flat []uint8 diff []int8 + groupByMetadata []map[string]string } func rowsToColumn(rows []flamegraphRow) flamegraphColumns { @@ -100,6 +102,7 @@ func rowsToColumn(rows []flamegraphRow) flamegraphColumns { columns.cumulative = append(columns.cumulative, row.Cumulative) columns.flat = append(columns.flat, row.Flat) columns.diff = append(columns.diff, row.Diff) + columns.groupByMetadata = append(columns.groupByMetadata, row.GroupByMetadata) } return columns } @@ -365,14 +368,14 @@ func TestGenerateFlamegraphArrow(t *testing.T) { cumulative: 11, height: 5, trimmed: 0, - cols: 14, + cols: 15, rows: []flamegraphRow{ - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: array.NullValueStr, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1}}, // 0 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{2}}, // 1 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0x0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 3, Labels: nil, Children: []uint32{3}}, // 2 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{4, 5}}, // 3 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil}, // 4 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 5, Flat: 5, Labels: nil, Children: nil}, // 5 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: array.NullValueStr, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1}, GroupByMetadata: nil}, // 0 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{2}, GroupByMetadata: nil}, // 1 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0x0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 3, Labels: nil, Children: []uint32{3}, GroupByMetadata: nil}, // 2 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{4, 5}, GroupByMetadata: nil}, // 3 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil, GroupByMetadata: nil}, // 4 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 5, Flat: 5, Labels: nil, Children: nil, GroupByMetadata: nil}, // 5 }, }, { name: "aggregate-labels-first-of-two", @@ -381,27 +384,27 @@ func TestGenerateFlamegraphArrow(t *testing.T) { cumulative: 11, height: 6, trimmed: 0, - cols: 15, + cols: 16, rows: []flamegraphRow{ // root - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 6, 11}}, // 0 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 6, 11}, GroupByMetadata: nil}, // 0 // stack 1 -- labels: goroutine=foo - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 3, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{2}, LabelsOnly: true}, // 1 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 3, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{3}}, // 2 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 3, Flat: 2, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{4}}, // 3 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{5}}, // 4 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"goroutine": "app"}, Children: nil}, // 5 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 3, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{2}, LabelsOnly: true, GroupByMetadata: nil}, // 1 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 3, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{3}, GroupByMetadata: nil}, // 2 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 3, Flat: 2, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{4}, GroupByMetadata: nil}, // 3 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"goroutine": "app"}, Children: []uint32{5}, GroupByMetadata: nil}, // 4 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"goroutine": "app"}, Children: nil, GroupByMetadata: nil}, // 5 // stack 2 -- labels: goroutine=bar - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{7}, LabelsOnly: true}, // 6 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{8}}, // 7 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{9}}, // 8 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{10}}, // 9 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: map[string]string{"goroutine": "container"}, Children: nil}, // 10 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{7}, LabelsOnly: true, GroupByMetadata: nil}, // 6 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{8}, GroupByMetadata: nil}, // 7 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{9}, GroupByMetadata: nil}, // 8 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{10}, GroupByMetadata: nil}, // 9 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: map[string]string{"goroutine": "container"}, Children: nil, GroupByMetadata: nil}, // 10 // stack 3 -- no labels - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: nil, Children: []uint32{12}}, // 11 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 1, Labels: nil, Children: []uint32{13}}, // 12 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 3, Flat: 0, Labels: nil, Children: []uint32{14}}, // 13 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil}, // 14 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: nil, Children: []uint32{12}, GroupByMetadata: nil}, // 11 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 1, Labels: nil, Children: []uint32{13}, GroupByMetadata: nil}, // 12 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 3, Flat: 0, Labels: nil, Children: []uint32{14}, GroupByMetadata: nil}, // 13 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil, GroupByMetadata: nil}, // 14 }, }, { name: "aggregate-labels-last-of-two", @@ -410,26 +413,26 @@ func TestGenerateFlamegraphArrow(t *testing.T) { cumulative: 11, height: 6, trimmed: 0, - cols: 15, + cols: 16, rows: []flamegraphRow{ // root - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 4, 9}}, // 0 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 4, 9}, GroupByMetadata: nil}, // 0 // stack 1 -- labels: cpu=0 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0"}, Children: []uint32{2}, LabelsOnly: true}, // 1 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0"}, Children: []uint32{3}}, // 2 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 2, Flat: 2, Labels: map[string]string{"cpu": "0"}, Children: nil}, // 3 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0"}, Children: []uint32{2}, LabelsOnly: true, GroupByMetadata: nil}, // 1 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0"}, Children: []uint32{3}, GroupByMetadata: nil}, // 2 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 2, Flat: 2, Labels: map[string]string{"cpu": "0"}, Children: nil, GroupByMetadata: nil}, // 3 // stack 2 -- labels: cpu=1 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{5}, LabelsOnly: true}, // 4 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{6}}, // 5 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{7}}, // 6 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{8}}, // 7 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"cpu": "1"}, Children: nil}, // 8 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{5}, LabelsOnly: true, GroupByMetadata: nil}, // 4 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{6}, GroupByMetadata: nil}, // 5 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{7}, GroupByMetadata: nil}, // 6 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1"}, Children: []uint32{8}, GroupByMetadata: nil}, // 7 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"cpu": "1"}, Children: nil, GroupByMetadata: nil}, // 8 // stack 3 -- no labels - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{10}}, // 9 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 8, Flat: 1, Labels: nil, Children: []uint32{11}}, // 10 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 7, Flat: 0, Labels: nil, Children: []uint32{12, 13}}, // 11 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil}, // 12 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: nil, Children: nil}, // 13 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{10}, GroupByMetadata: nil}, // 9 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 8, Flat: 1, Labels: nil, Children: []uint32{11}, GroupByMetadata: nil}, // 10 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 7, Flat: 0, Labels: nil, Children: []uint32{12, 13}, GroupByMetadata: nil}, // 11 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil, GroupByMetadata: nil}, // 12 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: nil, Children: nil, GroupByMetadata: nil}, // 13 }, }, { name: "aggregate-labels-two-of-two", @@ -438,31 +441,31 @@ func TestGenerateFlamegraphArrow(t *testing.T) { cumulative: 11, height: 6, trimmed: 0, - cols: 16, + cols: 17, rows: []flamegraphRow{ // root - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 4, 9, 14}}, // 0 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1, 4, 9, 14}, GroupByMetadata: nil}, // 0 // stack 1 -- labels: cpu=0, goroutine=1 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: []uint32{2}, LabelsOnly: true}, // 1 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: []uint32{3}}, // 2 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 2, Flat: 2, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: nil}, // 3 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: []uint32{2}, LabelsOnly: true, GroupByMetadata: nil}, // 1 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 2, Flat: 0, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: []uint32{3}, GroupByMetadata: nil}, // 2 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 2, Flat: 2, Labels: map[string]string{"cpu": "0", "goroutine": "app"}, Children: nil, GroupByMetadata: nil}, // 3 // stack 1 -- labels: cpu=1, goroutine=1 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{5}, LabelsOnly: true}, // 4 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{6}}, // 5 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{7}}, // 6 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{8}}, // 7 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: nil}, // 8 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{5}, LabelsOnly: true, GroupByMetadata: nil}, // 4 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{6}, GroupByMetadata: nil}, // 5 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{7}, GroupByMetadata: nil}, // 6 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 1, Flat: 0, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: []uint32{8}, GroupByMetadata: nil}, // 7 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 1, Flat: 1, Labels: map[string]string{"cpu": "1", "goroutine": "app"}, Children: nil, GroupByMetadata: nil}, // 8 // stack 3 -- labels: goroutine=2 - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{10}, LabelsOnly: true}, // 9 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{11}}, // 10 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{12}}, // 11 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{13}}, // 12 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: map[string]string{"goroutine": "container"}, Children: nil}, // 13 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: `(null)`, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{10}, LabelsOnly: true, GroupByMetadata: nil}, // 9 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{11}, GroupByMetadata: nil}, // 10 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{12}, GroupByMetadata: nil}, // 11 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 4, Flat: 0, Labels: map[string]string{"goroutine": "container"}, Children: []uint32{13}, GroupByMetadata: nil}, // 12 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 4, Flat: 4, Labels: map[string]string{"goroutine": "container"}, Children: nil, GroupByMetadata: nil}, // 13 // stack 4 -- no labels - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: nil, Children: []uint32{15}}, // 14 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 1, Labels: nil, Children: []uint32{16}}, // 15 - the nulls in this are due to merging with different underlying values - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 3, Flat: 0, Labels: nil, Children: []uint32{17}}, // 16 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil}, // 17 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 4, Flat: 0, Labels: nil, Children: []uint32{15}, GroupByMetadata: nil}, // 14 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: "2", FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 4, Flat: 1, Labels: nil, Children: []uint32{16}, GroupByMetadata: nil}, // 15 - the nulls in this are due to merging with different underlying values + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 3, Flat: 0, Labels: nil, Children: []uint32{17}, GroupByMetadata: nil}, // 16 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil, GroupByMetadata: nil}, // 17 }, }, { name: "aggregate-mapping-file", @@ -471,16 +474,16 @@ func TestGenerateFlamegraphArrow(t *testing.T) { cumulative: 11, height: 5, trimmed: 0, - cols: 14, + cols: 15, rows: []flamegraphRow{ // This aggregates all the rows with the same mapping file, meaning that we only keep one flamegraphRow per stack depth in this example. - {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: array.NullValueStr, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1}}, // 0 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{2, 6}}, // 1 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 10, Flat: 2, Labels: nil, Children: []uint32{3}}, // 2 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{4, 5}}, // 3 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil}, // 4 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 5, Flat: 5, Labels: nil, Children: nil}, // 5 - {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "b", MappingBuildID: "bID", LocationAddress: 0xa6, LocationLine: 6, FunctionStartLine: 6, FunctionName: "2", FunctionSystemName: "6", FunctionFilename: "6", Cumulative: 1, Flat: 1, Labels: nil, Children: nil}, // 5 + {MappingStart: 0, MappingLimit: 0, MappingOffset: 0, MappingFile: array.NullValueStr, MappingBuildID: array.NullValueStr, LocationAddress: 0, LocationLine: 0, FunctionStartLine: 0, FunctionName: array.NullValueStr, FunctionSystemName: array.NullValueStr, FunctionFilename: array.NullValueStr, Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{1}, GroupByMetadata: nil}, // 0 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa1, LocationLine: 1, FunctionStartLine: 1, FunctionName: "1", FunctionSystemName: "1", FunctionFilename: "1", Cumulative: 11, Flat: 0, Labels: nil, Children: []uint32{2, 6}, GroupByMetadata: nil}, // 1 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa2, LocationLine: 2, FunctionStartLine: 2, FunctionName: "2", FunctionSystemName: "2", FunctionFilename: "2", Cumulative: 10, Flat: 2, Labels: nil, Children: []uint32{3}, GroupByMetadata: nil}, // 2 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa3, LocationLine: 3, FunctionStartLine: 3, FunctionName: "3", FunctionSystemName: "3", FunctionFilename: "3", Cumulative: 8, Flat: 0, Labels: nil, Children: []uint32{4, 5}, GroupByMetadata: nil}, // 3 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa4, LocationLine: 4, FunctionStartLine: 4, FunctionName: "4", FunctionSystemName: "4", FunctionFilename: "4", Cumulative: 3, Flat: 3, Labels: nil, Children: nil, GroupByMetadata: nil}, // 4 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "a", MappingBuildID: "aID", LocationAddress: 0xa5, LocationLine: 5, FunctionStartLine: 5, FunctionName: "5", FunctionSystemName: "5", FunctionFilename: "5", Cumulative: 5, Flat: 5, Labels: nil, Children: nil, GroupByMetadata: nil}, // 5 + {MappingStart: 1, MappingLimit: 1, MappingOffset: 0x1234, MappingFile: "b", MappingBuildID: "bID", LocationAddress: 0xa6, LocationLine: 6, FunctionStartLine: 6, FunctionName: "2", FunctionSystemName: "6", FunctionFilename: "6", Cumulative: 1, Flat: 1, Labels: nil, Children: nil, GroupByMetadata: nil}, // 5 }, }} { t.Run(tc.name, func(t *testing.T) { @@ -658,7 +661,7 @@ func TestGenerateFlamegraphArrowEmpty(t *testing.T) { require.Equal(t, int64(0), total) require.Equal(t, int32(1), height) require.Equal(t, int64(0), trimmed) - require.Equal(t, int64(14), record.NumCols()) + require.Equal(t, int64(15), record.NumCols()) require.Equal(t, int64(1), record.NumRows()) } @@ -708,7 +711,7 @@ func TestGenerateFlamegraphArrowWithInlined(t *testing.T) { require.Equal(t, int32(5), height) require.Equal(t, int64(0), trimmed) - require.Equal(t, int64(14), record.NumCols()) + require.Equal(t, int64(15), record.NumCols()) require.Equal(t, int64(5), record.NumRows()) rows := []flamegraphRow{ @@ -809,7 +812,7 @@ func TestGenerateFlamegraphArrowUnsymbolized(t *testing.T) { require.Equal(t, tc.height, height) require.Equal(t, tc.trimmed, trimmed) require.Equal(t, int64(len(tc.rows)), fa.NumRows()) - require.Equal(t, int64(14), fa.NumCols()) + require.Equal(t, int64(15), fa.NumCols()) // Convert the numRows to columns for easier access when testing below. expectedColumns := rowsToColumn(tc.rows) @@ -896,7 +899,7 @@ func TestGenerateFlamegraphArrowTrimming(t *testing.T) { require.Equal(t, int32(5), height) require.Equal(t, int64(4), trimmed) require.Equal(t, int64(3), fa.NumRows()) - require.Equal(t, int64(14), fa.NumCols()) + require.Equal(t, int64(15), fa.NumCols()) // TODO: MappingBuildID and FunctionSystemNames shouldn't be "" but null? rows := []flamegraphRow{ @@ -1185,7 +1188,7 @@ main;func_fib 10 2000 20 main;func_fib 10 3000 20 runtime;gc 20 2000 30 runtime;gc 20 3000 30 -main;func_add 30 1000 20 +runtime;gc 30 1000 20 main;func_add 30 3000 20 `)) require.NoError(t, err) @@ -1330,6 +1333,8 @@ func drawFlamegraphToConsole(testing *testing.T, record arrow.Record) { childrenCol := record.Column(childrenColIdx).(*array.List) functionNameCol := record.Column(functionNameColIdx).(*array.Dictionary) ChildrenValues := childrenCol.ListValues().(*array.Uint32) + cumulativeColIdx := schema.FieldIndices("cumulative")[0] + cumulativeCol := record.Column(cumulativeColIdx).(*array.Uint8) groupByMetadataColIdx := schema.FieldIndices("groupby_metadata")[0] groupByMetadataCol := record.Column(groupByMetadataColIdx).(*array.Struct) tsValues := groupByMetadataCol.Field(1).(*array.Binary) @@ -1344,6 +1349,7 @@ func drawFlamegraphToConsole(testing *testing.T, record arrow.Record) { nums := offsetEnd - offsetStart for j := int64(0); j < nums; j++ { child := ChildrenValues.Value(int(offsetStart + j)) + cumulativeValue := cumulativeCol.Value(int(child)) fBytes := functionNameCol.ValueStr(int(child)) funcName, err := base64.StdEncoding.DecodeString(fBytes) if err != nil { @@ -1351,7 +1357,7 @@ func drawFlamegraphToConsole(testing *testing.T, record arrow.Record) { } tsBytes := tsValues.Value(int(child)) durationBytes := durationValues.Value(int(child)) - childT := t.AddChild(tree.NodeString(string(funcName) + " " + string(tsBytes) + " " + string(durationBytes))) + childT := t.AddChild(tree.NodeString(string(funcName) + " " + string(tsBytes) + " " + string(durationBytes) + " " + fmt.Sprint(cumulativeValue))) populateChild(childT, int(child)) } }