Skip to content

Commit 7dc3dc4

Browse files
feat: Speculative improvement of handling of mixed OTLP profiles (#4470)
* Handle cases where a single profile can contain unsymbolized and symbolized frames (e.g. cross-language profiles)
1 parent c26f585 commit 7dc3dc4

File tree

1 file changed

+58
-11
lines changed

1 file changed

+58
-11
lines changed

pkg/ingester/otlp/convert.go

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -243,9 +243,9 @@ func (p *profileBuilder) convertLocationBack(ol *otelProfile.Location, dictionar
243243
return 0, fmt.Errorf("could not access mapping: %w", err)
244244
}
245245

246-
mappingId, err := p.convertMappingBack(om, dictionary)
247-
if err != nil {
248-
return 0, err
246+
mappingId, ok := p.mappingMap[om]
247+
if !ok {
248+
return 0, fmt.Errorf("mapping not found in mappingMap")
249249
}
250250
gl := &googleProfile.Location{
251251
MappingId: mappingId,
@@ -350,6 +350,30 @@ func (p *profileBuilder) convertSampleBack(os *otelProfile.Sample, dictionary *o
350350
return nil, fmt.Errorf("invalid stack index: %d", stackIndex)
351351
}
352352
stack := dictionary.StackTable[stackIndex]
353+
354+
// First, gather map of locations pointing to each mapping
355+
locationMap := make(map[*otelProfile.Mapping][]*otelProfile.Location)
356+
357+
for _, locIdx := range stack.LocationIndices {
358+
loc, err := at(dictionary.LocationTable, locIdx)
359+
if err != nil {
360+
return nil, fmt.Errorf("could not access location at index %d: %w", locIdx, err)
361+
}
362+
mapping, err := at(dictionary.MappingTable, loc.GetMappingIndex())
363+
if err != nil {
364+
return nil, fmt.Errorf("could not access mapping at index %d: %w", loc.GetMappingIndex(), err)
365+
}
366+
locationMap[mapping] = append(locationMap[mapping], loc)
367+
}
368+
369+
// Now, convert each mapping, based on information from all locations that point to it
370+
for mapping, locs := range locationMap {
371+
_, err := p.convertMappingBack(locs, mapping, dictionary)
372+
if err != nil {
373+
return nil, err
374+
}
375+
}
376+
353377
for _, olocIdx := range stack.LocationIndices {
354378
oloc, err := at(dictionary.LocationTable, olocIdx)
355379
if err != nil {
@@ -403,10 +427,33 @@ func (p *profileBuilder) convertSampleAttributesToLabelsBack(os *otelProfile.Sam
403427
return nil
404428
}
405429

406-
// convertMappingsBack converts a slice of OpenTelemetry Mapping entries to Google Mapping entries.
407-
func (p *profileBuilder) convertMappingBack(om *otelProfile.Mapping, dictionary *otelProfile.ProfilesDictionary) (uint64, error) {
408-
if i, ok := p.mappingMap[om]; ok {
409-
return i, nil
430+
// convertMappingBack converts an OpenTelemetry Mapping to a Google Mapping taking into account availability
431+
// of symbol data in all locations that point to this mapping.
432+
func (p *profileBuilder) convertMappingBack(ols []*otelProfile.Location, om *otelProfile.Mapping, dictionary *otelProfile.ProfilesDictionary) (uint64, error) {
433+
hasLines := true
434+
hasFunctions := true
435+
hasInlineFrames := true
436+
hasFilenames := true
437+
438+
/*
439+
We survey all locations that point to this mapping to determine
440+
whether the mapping has functions, filenames, line numbers, inline frames.
441+
Note that even if a single location does not have symbol information,
442+
the mapping is marked as not having that information.
443+
*/
444+
for _, ol := range ols {
445+
for i, line := range ol.Line {
446+
hasFunctions = hasFunctions && line.FunctionIndex > 0
447+
hasLines = hasLines && line.Line > 0
448+
hasInlineFrames = hasInlineFrames && i >= 1
449+
450+
if line.FunctionIndex > 0 {
451+
function, _ := at(dictionary.FunctionTable, line.FunctionIndex)
452+
if function != nil {
453+
hasFilenames = hasFilenames && function.FilenameStrindex > 0
454+
}
455+
}
456+
}
410457
}
411458

412459
buildID, _ := getAttributeValueByKeyOrEmpty(om.AttributeIndices, dictionary, "process.executable.build_id.gnu")
@@ -420,10 +467,10 @@ func (p *profileBuilder) convertMappingBack(om *otelProfile.Mapping, dictionary
420467
FileOffset: om.FileOffset,
421468
Filename: p.addstr(filenameLabel),
422469
BuildId: p.addstr(buildID),
423-
HasFunctions: true,
424-
HasFilenames: true,
425-
HasLineNumbers: true,
426-
HasInlineFrames: true,
470+
HasFunctions: hasFunctions,
471+
HasFilenames: hasFilenames,
472+
HasLineNumbers: hasLines,
473+
HasInlineFrames: hasInlineFrames,
427474
}
428475
p.dst.Mapping = append(p.dst.Mapping, gm)
429476
gm.Id = uint64(len(p.dst.Mapping))

0 commit comments

Comments
 (0)