baggage.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package propagation // import "go.opentelemetry.io/otel/propagation"
  4. import (
  5. "context"
  6. "go.opentelemetry.io/otel/baggage"
  7. "go.opentelemetry.io/otel/internal/errorhandler"
  8. )
  9. const (
  10. baggageHeader = "baggage"
  11. // W3C Baggage specification limits.
  12. // https://www.w3.org/TR/baggage/#limits
  13. maxMembers = 64
  14. )
  15. // Baggage is a propagator that supports the W3C Baggage format.
  16. //
  17. // This propagates user-defined baggage associated with a trace. The complete
  18. // specification is defined at https://www.w3.org/TR/baggage/.
  19. type Baggage struct{}
  20. var _ TextMapPropagator = Baggage{}
  21. // Inject sets baggage key-values from ctx into the carrier.
  22. func (Baggage) Inject(ctx context.Context, carrier TextMapCarrier) {
  23. bStr := baggage.FromContext(ctx).String()
  24. if bStr != "" {
  25. carrier.Set(baggageHeader, bStr)
  26. }
  27. }
  28. // Extract returns a copy of parent with the baggage from the carrier added.
  29. // If carrier implements [ValuesGetter] (e.g. [HeaderCarrier]), Values is invoked
  30. // for multiple values extraction. Otherwise, Get is called.
  31. func (Baggage) Extract(parent context.Context, carrier TextMapCarrier) context.Context {
  32. if multiCarrier, ok := carrier.(ValuesGetter); ok {
  33. return extractMultiBaggage(parent, multiCarrier)
  34. }
  35. return extractSingleBaggage(parent, carrier)
  36. }
  37. // Fields returns the keys who's values are set with Inject.
  38. func (Baggage) Fields() []string {
  39. return []string{baggageHeader}
  40. }
  41. func extractSingleBaggage(parent context.Context, carrier TextMapCarrier) context.Context {
  42. bStr := carrier.Get(baggageHeader)
  43. if bStr == "" {
  44. return parent
  45. }
  46. bag, err := baggage.Parse(bStr)
  47. if err != nil {
  48. errorhandler.GetErrorHandler().Handle(err)
  49. }
  50. if bag.Len() == 0 {
  51. return parent
  52. }
  53. return baggage.ContextWithBaggage(parent, bag)
  54. }
  55. func extractMultiBaggage(parent context.Context, carrier ValuesGetter) context.Context {
  56. bVals := carrier.Values(baggageHeader)
  57. if len(bVals) == 0 {
  58. return parent
  59. }
  60. var members []baggage.Member
  61. for _, bStr := range bVals {
  62. currBag, err := baggage.Parse(bStr)
  63. if err != nil {
  64. errorhandler.GetErrorHandler().Handle(err)
  65. }
  66. if currBag.Len() == 0 {
  67. continue
  68. }
  69. members = append(members, currBag.Members()...)
  70. if len(members) >= maxMembers {
  71. break
  72. }
  73. }
  74. b, err := baggage.New(members...)
  75. if err != nil {
  76. errorhandler.GetErrorHandler().Handle(err)
  77. }
  78. if b.Len() == 0 {
  79. return parent
  80. }
  81. return baggage.ContextWithBaggage(parent, b)
  82. }