You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
97447f5c54
```
goos: darwin
goarch: arm64
pkg: go.opentelemetry.io/otel/baggage
cpu: Apple M1 Max
│ /tmp/old.txt │ /tmp/new.txt │
│ sec/op │ sec/op vs base │
New-10 413.5n ± 1% 410.1n ± 1% ~ (p=0.184 n=10)
NewMemberRaw-10 12.65n ± 1% 12.62n ± 1% ~ (p=0.270 n=10)
Parse-10 1.252µ ± 2% 1.254µ ± 1% ~ (p=0.778 n=10)
String-10 594.9n ± 1% 593.4n ± 1% ~ (p=0.279 n=10)
ValueEscape/nothing_to_escape-10 4.890n ± 1% 4.885n ± 0% ~ (p=0.579 n=10)
ValueEscape/requires_escaping-10 22.02n ± 1% 21.47n ± 1% -2.50% (p=0.000 n=10)
ValueEscape/long_value-10 507.4n ± 1% 506.6n ± 2% ~ (p=0.481 n=10)
MemberString-10 486.7n ± 15% 514.0n ± 5% ~ (p=0.190 n=10)
ParseOversized-10 22544795.0n ± 1% 130.8n ± 4% -100.00% (p=0.000 n=10)
geomean 510.0n 133.8n -73.76%
│ /tmp/old.txt │ /tmp/new.txt │
│ B/op │ B/op vs base │
New-10 592.0 ± 0% 592.0 ± 0% ~ (p=1.000 n=10) ¹
NewMemberRaw-10 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
Parse-10 1.039Ki ± 0% 1.039Ki ± 0% ~ (p=1.000 n=10) ¹
String-10 840.0 ± 0% 840.0 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/nothing_to_escape-10 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/requires_escaping-10 16.00 ± 0% 16.00 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/long_value-10 576.0 ± 0% 576.0 ± 0% ~ (p=1.000 n=10) ¹
MemberString-10 656.0 ± 0% 656.0 ± 0% ~ (p=1.000 n=10) ¹
ParseOversized-10 801126.50 ± 0% 88.00 ± 0% -99.99% (p=0.000 n=10)
geomean ² -63.68% ²
¹ all samples are equal
² summaries must be >0 to compute geomean
│ /tmp/old.txt │ /tmp/new.txt │
│ allocs/op │ allocs/op vs base │
New-10 6.000 ± 0% 6.000 ± 0% ~ (p=1.000 n=10) ¹
NewMemberRaw-10 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
Parse-10 18.00 ± 0% 18.00 ± 0% ~ (p=1.000 n=10) ¹
String-10 8.000 ± 0% 8.000 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/nothing_to_escape-10 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/requires_escaping-10 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹
ValueEscape/long_value-10 2.000 ± 0% 2.000 ± 0% ~ (p=1.000 n=10) ¹
MemberString-10 4.000 ± 0% 4.000 ± 0% ~ (p=1.000 n=10) ¹
ParseOversized-10 250007.000 ± 0% 3.000 ± 0% -100.00% (p=0.000 n=10)
geomean ² -71.61% ²
¹ all samples are equal
² summaries must be >0 to compute geomean
```
---------
Co-authored-by: Robert Pająk <pellared@hotmail.com>
135 lines
3.5 KiB
Go
135 lines
3.5 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package propagation // import "go.opentelemetry.io/otel/propagation"
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"go.opentelemetry.io/otel/baggage"
|
|
"go.opentelemetry.io/otel/internal/errorhandler"
|
|
)
|
|
|
|
const (
|
|
baggageHeader = "baggage"
|
|
|
|
maxParseErrors = 5
|
|
|
|
// W3C Baggage specification limits.
|
|
// https://www.w3.org/TR/baggage/#limits
|
|
maxMembers = 64
|
|
maxBytesPerBaggageString = 8192
|
|
)
|
|
|
|
// Baggage is a propagator that supports the W3C Baggage format.
|
|
//
|
|
// This propagates user-defined baggage associated with a trace. The complete
|
|
// specification is defined at https://www.w3.org/TR/baggage/.
|
|
type Baggage struct{}
|
|
|
|
var _ TextMapPropagator = Baggage{}
|
|
|
|
// Inject sets baggage key-values from ctx into the carrier.
|
|
func (Baggage) Inject(ctx context.Context, carrier TextMapCarrier) {
|
|
bStr := baggage.FromContext(ctx).String()
|
|
if bStr != "" {
|
|
carrier.Set(baggageHeader, bStr)
|
|
}
|
|
}
|
|
|
|
// Extract returns a copy of parent with the baggage from the carrier added.
|
|
// If carrier implements [ValuesGetter] (e.g. [HeaderCarrier]), Values is invoked
|
|
// for multiple values extraction. Otherwise, Get is called.
|
|
func (Baggage) Extract(parent context.Context, carrier TextMapCarrier) context.Context {
|
|
if multiCarrier, ok := carrier.(ValuesGetter); ok {
|
|
return extractMultiBaggage(parent, multiCarrier)
|
|
}
|
|
return extractSingleBaggage(parent, carrier)
|
|
}
|
|
|
|
// Fields returns the keys who's values are set with Inject.
|
|
func (Baggage) Fields() []string {
|
|
return []string{baggageHeader}
|
|
}
|
|
|
|
func extractSingleBaggage(parent context.Context, carrier TextMapCarrier) context.Context {
|
|
bStr := carrier.Get(baggageHeader)
|
|
if bStr == "" {
|
|
return parent
|
|
}
|
|
|
|
bag, err := baggage.Parse(bStr)
|
|
if err != nil {
|
|
errorhandler.GetErrorHandler().Handle(err)
|
|
}
|
|
if bag.Len() == 0 {
|
|
return parent
|
|
}
|
|
return baggage.ContextWithBaggage(parent, bag)
|
|
}
|
|
|
|
func extractMultiBaggage(parent context.Context, carrier ValuesGetter) context.Context {
|
|
bVals := carrier.Values(baggageHeader)
|
|
if len(bVals) == 0 {
|
|
return parent
|
|
}
|
|
|
|
var members []baggage.Member
|
|
var totalBytes int
|
|
var parseErrors int
|
|
var truncateErr error
|
|
for i, bStr := range bVals {
|
|
if i > 0 {
|
|
totalBytes++ // comma separator between combined header values
|
|
}
|
|
totalBytes += len(bStr)
|
|
if totalBytes > maxBytesPerBaggageString {
|
|
// Per the W3C Baggage spec, the byte limit applies to the
|
|
// combination of all baggage headers, not each header
|
|
// individually. Mirror the single-header behavior of
|
|
// reporting the error and returning the parent context
|
|
// with no baggage attached.
|
|
errorhandler.GetErrorHandler().Handle(fmt.Errorf(
|
|
"baggage: aggregate header size %d exceeds %d byte limit",
|
|
totalBytes,
|
|
maxBytesPerBaggageString,
|
|
))
|
|
return parent
|
|
}
|
|
|
|
// If members exceed the limit, stop parsing baggage.
|
|
if len(members) <= maxMembers {
|
|
currBag, err := baggage.Parse(bStr)
|
|
if err != nil {
|
|
parseErrors++
|
|
if parseErrors <= maxParseErrors {
|
|
truncateErr = errors.Join(truncateErr, err)
|
|
}
|
|
}
|
|
if currBag.Len() == 0 {
|
|
continue
|
|
}
|
|
members = append(members, currBag.Members()...)
|
|
}
|
|
}
|
|
|
|
if dropped := parseErrors - maxParseErrors; dropped > 0 {
|
|
truncateErr = errors.Join(truncateErr, fmt.Errorf("and %d more error(s)", dropped))
|
|
}
|
|
|
|
b, err := baggage.New(members...)
|
|
if err != nil {
|
|
truncateErr = errors.Join(truncateErr, err)
|
|
}
|
|
if truncateErr != nil {
|
|
errorhandler.GetErrorHandler().Handle(truncateErr)
|
|
}
|
|
|
|
if b.Len() == 0 {
|
|
return parent
|
|
}
|
|
return baggage.ContextWithBaggage(parent, b)
|
|
}
|