mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description When multiple exporters are used in a profiles pipeline, the same data object is shared and marked as read-only, causing a panic when mutation is attempted. Fix this by only creating a copy when the input is marked as read-only. This preserves the in-place mutation optimization for mutable data while preventing panics in shared data scenarios. <!-- Issue number if applicable --> #### Link to tracking issue Fixes #15080 <!--Describe what testing was performed and which tests were added.--> #### Testing <!--Describe the documentation added.--> #### Documentation <!--Please delete paragraphs that you did not use before submitting.--> --------- Signed-off-by: Florian Lehner <[email protected]> Co-authored-by: Damien Mathieu <[email protected]>
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package pprofile // import "go.opentelemetry.io/collector/pdata/pprofile"
|
|
|
|
import (
|
|
"slices"
|
|
|
|
"go.opentelemetry.io/collector/pdata/internal/json"
|
|
"go.opentelemetry.io/collector/pdata/internal/otlp"
|
|
)
|
|
|
|
// JSONMarshaler marshals pprofile.Profiles to JSON bytes using the OTLP/JSON format.
|
|
type JSONMarshaler struct{}
|
|
|
|
// MarshalProfiles marshals Profiles to OTLP/JSON format bytes.
|
|
// If the input data is read-only, it will be copied to a mutable
|
|
// instance before mutation.
|
|
func (*JSONMarshaler) MarshalProfiles(pd Profiles) ([]byte, error) {
|
|
// Only copy if data is shared/read-only to avoid unnecessary allocation
|
|
pdToUse := pd
|
|
if pd.IsReadOnly() {
|
|
pdCopy := NewProfiles()
|
|
pd.CopyTo(pdCopy)
|
|
pdToUse = pdCopy
|
|
}
|
|
|
|
// Convert strings to references for efficient transmission
|
|
convertProfilesToReferences(pdToUse)
|
|
|
|
dest := json.BorrowStream(nil)
|
|
defer json.ReturnStream(dest)
|
|
pdToUse.getOrig().MarshalJSON(dest)
|
|
if dest.Error() != nil {
|
|
return nil, dest.Error()
|
|
}
|
|
return slices.Clone(dest.Buffer()), nil
|
|
}
|
|
|
|
// JSONUnmarshaler unmarshals OTLP/JSON formatted-bytes to pprofile.Profiles.
|
|
type JSONUnmarshaler struct{}
|
|
|
|
// UnmarshalProfiles from OTLP/JSON format into pprofile.Profiles.
|
|
func (*JSONUnmarshaler) UnmarshalProfiles(buf []byte) (Profiles, error) {
|
|
iter := json.BorrowIterator(buf)
|
|
defer json.ReturnIterator(iter)
|
|
pd := NewProfiles()
|
|
pd.getOrig().UnmarshalJSON(iter)
|
|
if iter.Error() != nil {
|
|
return Profiles{}, iter.Error()
|
|
}
|
|
otlp.MigrateProfiles(pd.getOrig().ResourceProfiles)
|
|
|
|
// Resolve all string_value_ref and key_ref to their actual strings
|
|
// so the pdata API works transparently
|
|
resolveProfilesReferences(pd)
|
|
|
|
return pd, nil
|
|
}
|