Files
daa5bf7ea2 [exporter/debug] Guard from out of bounds profiles dictionary indices (#14804)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
#### Description
check before accessing profiles dictionary indices and fail gracefully
if they are out of bounds
<!-- Issue number if applicable -->
#### Link to tracking issue
Fixes #14803

<!--Describe what testing was performed and which tests were added.-->
#### Testing
Added tests to prove missing dictionary indices fail and don't panic
<!--Describe the documentation added.-->
#### Documentation

<!--Please delete paragraphs that you did not use before submitting.-->

---------

Co-authored-by: Andrzej Stencel <[email protected]>
2026-04-06 23:16:53 +00:00

74 lines
2.5 KiB
Go

// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
package normal // import "go.opentelemetry.io/collector/exporter/debugexporter/internal/normal"
import (
"bytes"
"fmt"
"strconv"
"strings"
"go.opentelemetry.io/collector/pdata/pprofile"
)
type normalProfilesMarshaler struct{}
// Ensure normalProfilesMarshaller implements interface pprofile.Marshaler
var _ pprofile.Marshaler = normalProfilesMarshaler{}
// NewNormalProfilesMarshaler returns a pprofile.Marshaler for normal verbosity. It writes one line of text per log record
func NewNormalProfilesMarshaler() pprofile.Marshaler {
return normalProfilesMarshaler{}
}
func (normalProfilesMarshaler) MarshalProfiles(pd pprofile.Profiles) ([]byte, error) {
var buffer bytes.Buffer
dic := pd.Dictionary()
for i := 0; i < pd.ResourceProfiles().Len(); i++ {
resourceProfiles := pd.ResourceProfiles().At(i)
buffer.WriteString(fmt.Sprintf("ResourceProfiles #%d%s%s\n", i, writeResourceDetails(resourceProfiles.SchemaUrl()), writeAttributesString(resourceProfiles.Resource().Attributes())))
for j := 0; j < resourceProfiles.ScopeProfiles().Len(); j++ {
scopeProfiles := resourceProfiles.ScopeProfiles().At(j)
buffer.WriteString(fmt.Sprintf("ScopeProfiles #%d%s%s\n", i, writeScopeDetails(scopeProfiles.Scope().Name(), scopeProfiles.Scope().Version(), scopeProfiles.SchemaUrl()), writeAttributesString(scopeProfiles.Scope().Attributes())))
for k := 0; k < scopeProfiles.Profiles().Len(); k++ {
profile := scopeProfiles.Profiles().At(k)
buffer.WriteString(profile.ProfileID().String())
buffer.WriteString(" samples=")
buffer.WriteString(strconv.Itoa(profile.Samples().Len()))
if profile.AttributeIndices().Len() > 0 {
attrs := []string{}
for _, i := range profile.AttributeIndices().AsRaw() {
attrIdx := int(i)
if attrIdx >= dic.AttributeTable().Len() {
attrs = append(attrs, fmt.Sprintf("[Missing Dictionary AttributeTable Item #%d]", attrIdx))
continue
}
a := dic.AttributeTable().At(attrIdx)
keyIdx := int(a.KeyStrindex())
key := fmt.Sprintf("[Missing Dictionary Key String Item #%d]", keyIdx)
if keyIdx < dic.StringTable().Len() {
key = dic.StringTable().At(keyIdx)
}
attrs = append(attrs, fmt.Sprintf("%s=%s", key, a.Value().AsString()))
}
buffer.WriteString(" ")
buffer.WriteString(strings.Join(attrs, " "))
}
buffer.WriteString("\n")
}
}
}
return buffer.Bytes(), nil
}