mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
rebase: bump google.golang.org/grpc from 1.72.2 to 1.73.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.2 to 1.73.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.72.2...v1.73.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-version: 1.73.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
mergify[bot]
parent
46965acb63
commit
04c5ded613
661
vendor/go.opentelemetry.io/otel/trace/auto.go
generated
vendored
Normal file
661
vendor/go.opentelemetry.io/otel/trace/auto.go
generated
vendored
Normal file
@ -0,0 +1,661 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package trace // import "go.opentelemetry.io/otel/trace"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace/embedded"
|
||||
"go.opentelemetry.io/otel/trace/internal/telemetry"
|
||||
)
|
||||
|
||||
// newAutoTracerProvider returns an auto-instrumentable [trace.TracerProvider].
|
||||
// If an [go.opentelemetry.io/auto.Instrumentation] is configured to instrument
|
||||
// the process using the returned TracerProvider, all of the telemetry it
|
||||
// produces will be processed and handled by that Instrumentation. By default,
|
||||
// if no Instrumentation instruments the TracerProvider it will not generate
|
||||
// any trace telemetry.
|
||||
func newAutoTracerProvider() TracerProvider { return tracerProviderInstance }
|
||||
|
||||
var tracerProviderInstance = new(autoTracerProvider)
|
||||
|
||||
type autoTracerProvider struct{ embedded.TracerProvider }
|
||||
|
||||
var _ TracerProvider = autoTracerProvider{}
|
||||
|
||||
func (p autoTracerProvider) Tracer(name string, opts ...TracerOption) Tracer {
|
||||
cfg := NewTracerConfig(opts...)
|
||||
return autoTracer{
|
||||
name: name,
|
||||
version: cfg.InstrumentationVersion(),
|
||||
schemaURL: cfg.SchemaURL(),
|
||||
}
|
||||
}
|
||||
|
||||
type autoTracer struct {
|
||||
embedded.Tracer
|
||||
|
||||
name, schemaURL, version string
|
||||
}
|
||||
|
||||
var _ Tracer = autoTracer{}
|
||||
|
||||
func (t autoTracer) Start(ctx context.Context, name string, opts ...SpanStartOption) (context.Context, Span) {
|
||||
var psc SpanContext
|
||||
sampled := true
|
||||
span := new(autoSpan)
|
||||
|
||||
// Ask eBPF for sampling decision and span context info.
|
||||
t.start(ctx, span, &psc, &sampled, &span.spanContext)
|
||||
|
||||
span.sampled.Store(sampled)
|
||||
|
||||
ctx = ContextWithSpan(ctx, span)
|
||||
|
||||
if sampled {
|
||||
// Only build traces if sampled.
|
||||
cfg := NewSpanStartConfig(opts...)
|
||||
span.traces, span.span = t.traces(name, cfg, span.spanContext, psc)
|
||||
}
|
||||
|
||||
return ctx, span
|
||||
}
|
||||
|
||||
// Expected to be implemented in eBPF.
|
||||
//
|
||||
//go:noinline
|
||||
func (t *autoTracer) start(
|
||||
ctx context.Context,
|
||||
spanPtr *autoSpan,
|
||||
psc *SpanContext,
|
||||
sampled *bool,
|
||||
sc *SpanContext,
|
||||
) {
|
||||
start(ctx, spanPtr, psc, sampled, sc)
|
||||
}
|
||||
|
||||
// start is used for testing.
|
||||
var start = func(context.Context, *autoSpan, *SpanContext, *bool, *SpanContext) {}
|
||||
|
||||
func (t autoTracer) traces(name string, cfg SpanConfig, sc, psc SpanContext) (*telemetry.Traces, *telemetry.Span) {
|
||||
span := &telemetry.Span{
|
||||
TraceID: telemetry.TraceID(sc.TraceID()),
|
||||
SpanID: telemetry.SpanID(sc.SpanID()),
|
||||
Flags: uint32(sc.TraceFlags()),
|
||||
TraceState: sc.TraceState().String(),
|
||||
ParentSpanID: telemetry.SpanID(psc.SpanID()),
|
||||
Name: name,
|
||||
Kind: spanKind(cfg.SpanKind()),
|
||||
}
|
||||
|
||||
span.Attrs, span.DroppedAttrs = convCappedAttrs(maxSpan.Attrs, cfg.Attributes())
|
||||
|
||||
links := cfg.Links()
|
||||
if limit := maxSpan.Links; limit == 0 {
|
||||
n := int64(len(links))
|
||||
if n > 0 {
|
||||
span.DroppedLinks = uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked.
|
||||
}
|
||||
} else {
|
||||
if limit > 0 {
|
||||
n := int64(max(len(links)-limit, 0))
|
||||
span.DroppedLinks = uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked.
|
||||
links = links[n:]
|
||||
}
|
||||
span.Links = convLinks(links)
|
||||
}
|
||||
|
||||
if t := cfg.Timestamp(); !t.IsZero() {
|
||||
span.StartTime = cfg.Timestamp()
|
||||
} else {
|
||||
span.StartTime = time.Now()
|
||||
}
|
||||
|
||||
return &telemetry.Traces{
|
||||
ResourceSpans: []*telemetry.ResourceSpans{
|
||||
{
|
||||
ScopeSpans: []*telemetry.ScopeSpans{
|
||||
{
|
||||
Scope: &telemetry.Scope{
|
||||
Name: t.name,
|
||||
Version: t.version,
|
||||
},
|
||||
Spans: []*telemetry.Span{span},
|
||||
SchemaURL: t.schemaURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, span
|
||||
}
|
||||
|
||||
func spanKind(kind SpanKind) telemetry.SpanKind {
|
||||
switch kind {
|
||||
case SpanKindInternal:
|
||||
return telemetry.SpanKindInternal
|
||||
case SpanKindServer:
|
||||
return telemetry.SpanKindServer
|
||||
case SpanKindClient:
|
||||
return telemetry.SpanKindClient
|
||||
case SpanKindProducer:
|
||||
return telemetry.SpanKindProducer
|
||||
case SpanKindConsumer:
|
||||
return telemetry.SpanKindConsumer
|
||||
}
|
||||
return telemetry.SpanKind(0) // undefined.
|
||||
}
|
||||
|
||||
type autoSpan struct {
|
||||
embedded.Span
|
||||
|
||||
spanContext SpanContext
|
||||
sampled atomic.Bool
|
||||
|
||||
mu sync.Mutex
|
||||
traces *telemetry.Traces
|
||||
span *telemetry.Span
|
||||
}
|
||||
|
||||
func (s *autoSpan) SpanContext() SpanContext {
|
||||
if s == nil {
|
||||
return SpanContext{}
|
||||
}
|
||||
// s.spanContext is immutable, do not acquire lock s.mu.
|
||||
return s.spanContext
|
||||
}
|
||||
|
||||
func (s *autoSpan) IsRecording() bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return s.sampled.Load()
|
||||
}
|
||||
|
||||
func (s *autoSpan) SetStatus(c codes.Code, msg string) {
|
||||
if s == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.span.Status == nil {
|
||||
s.span.Status = new(telemetry.Status)
|
||||
}
|
||||
|
||||
s.span.Status.Message = msg
|
||||
|
||||
switch c {
|
||||
case codes.Unset:
|
||||
s.span.Status.Code = telemetry.StatusCodeUnset
|
||||
case codes.Error:
|
||||
s.span.Status.Code = telemetry.StatusCodeError
|
||||
case codes.Ok:
|
||||
s.span.Status.Code = telemetry.StatusCodeOK
|
||||
}
|
||||
}
|
||||
|
||||
func (s *autoSpan) SetAttributes(attrs ...attribute.KeyValue) {
|
||||
if s == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
limit := maxSpan.Attrs
|
||||
if limit == 0 {
|
||||
// No attributes allowed.
|
||||
n := int64(len(attrs))
|
||||
if n > 0 {
|
||||
s.span.DroppedAttrs += uint32(min(n, math.MaxUint32)) // nolint: gosec // Bounds checked.
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
m := make(map[string]int)
|
||||
for i, a := range s.span.Attrs {
|
||||
m[a.Key] = i
|
||||
}
|
||||
|
||||
for _, a := range attrs {
|
||||
val := convAttrValue(a.Value)
|
||||
if val.Empty() {
|
||||
s.span.DroppedAttrs++
|
||||
continue
|
||||
}
|
||||
|
||||
if idx, ok := m[string(a.Key)]; ok {
|
||||
s.span.Attrs[idx] = telemetry.Attr{
|
||||
Key: string(a.Key),
|
||||
Value: val,
|
||||
}
|
||||
} else if limit < 0 || len(s.span.Attrs) < limit {
|
||||
s.span.Attrs = append(s.span.Attrs, telemetry.Attr{
|
||||
Key: string(a.Key),
|
||||
Value: val,
|
||||
})
|
||||
m[string(a.Key)] = len(s.span.Attrs) - 1
|
||||
} else {
|
||||
s.span.DroppedAttrs++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convCappedAttrs converts up to limit attrs into a []telemetry.Attr. The
|
||||
// number of dropped attributes is also returned.
|
||||
func convCappedAttrs(limit int, attrs []attribute.KeyValue) ([]telemetry.Attr, uint32) {
|
||||
n := len(attrs)
|
||||
if limit == 0 {
|
||||
var out uint32
|
||||
if n > 0 {
|
||||
out = uint32(min(int64(n), math.MaxUint32)) // nolint: gosec // Bounds checked.
|
||||
}
|
||||
return nil, out
|
||||
}
|
||||
|
||||
if limit < 0 {
|
||||
// Unlimited.
|
||||
return convAttrs(attrs), 0
|
||||
}
|
||||
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
|
||||
limit = min(n, limit)
|
||||
return convAttrs(attrs[:limit]), uint32(n - limit) // nolint: gosec // Bounds checked.
|
||||
}
|
||||
|
||||
func convAttrs(attrs []attribute.KeyValue) []telemetry.Attr {
|
||||
if len(attrs) == 0 {
|
||||
// Avoid allocations if not necessary.
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]telemetry.Attr, 0, len(attrs))
|
||||
for _, attr := range attrs {
|
||||
key := string(attr.Key)
|
||||
val := convAttrValue(attr.Value)
|
||||
if val.Empty() {
|
||||
continue
|
||||
}
|
||||
out = append(out, telemetry.Attr{Key: key, Value: val})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func convAttrValue(value attribute.Value) telemetry.Value {
|
||||
switch value.Type() {
|
||||
case attribute.BOOL:
|
||||
return telemetry.BoolValue(value.AsBool())
|
||||
case attribute.INT64:
|
||||
return telemetry.Int64Value(value.AsInt64())
|
||||
case attribute.FLOAT64:
|
||||
return telemetry.Float64Value(value.AsFloat64())
|
||||
case attribute.STRING:
|
||||
v := truncate(maxSpan.AttrValueLen, value.AsString())
|
||||
return telemetry.StringValue(v)
|
||||
case attribute.BOOLSLICE:
|
||||
slice := value.AsBoolSlice()
|
||||
out := make([]telemetry.Value, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
out = append(out, telemetry.BoolValue(v))
|
||||
}
|
||||
return telemetry.SliceValue(out...)
|
||||
case attribute.INT64SLICE:
|
||||
slice := value.AsInt64Slice()
|
||||
out := make([]telemetry.Value, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
out = append(out, telemetry.Int64Value(v))
|
||||
}
|
||||
return telemetry.SliceValue(out...)
|
||||
case attribute.FLOAT64SLICE:
|
||||
slice := value.AsFloat64Slice()
|
||||
out := make([]telemetry.Value, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
out = append(out, telemetry.Float64Value(v))
|
||||
}
|
||||
return telemetry.SliceValue(out...)
|
||||
case attribute.STRINGSLICE:
|
||||
slice := value.AsStringSlice()
|
||||
out := make([]telemetry.Value, 0, len(slice))
|
||||
for _, v := range slice {
|
||||
v = truncate(maxSpan.AttrValueLen, v)
|
||||
out = append(out, telemetry.StringValue(v))
|
||||
}
|
||||
return telemetry.SliceValue(out...)
|
||||
}
|
||||
return telemetry.Value{}
|
||||
}
|
||||
|
||||
// truncate returns a truncated version of s such that it contains less than
|
||||
// the limit number of characters. Truncation is applied by returning the limit
|
||||
// number of valid characters contained in s.
|
||||
//
|
||||
// If limit is negative, it returns the original string.
|
||||
//
|
||||
// UTF-8 is supported. When truncating, all invalid characters are dropped
|
||||
// before applying truncation.
|
||||
//
|
||||
// If s already contains less than the limit number of bytes, it is returned
|
||||
// unchanged. No invalid characters are removed.
|
||||
func truncate(limit int, s string) string {
|
||||
// This prioritize performance in the following order based on the most
|
||||
// common expected use-cases.
|
||||
//
|
||||
// - Short values less than the default limit (128).
|
||||
// - Strings with valid encodings that exceed the limit.
|
||||
// - No limit.
|
||||
// - Strings with invalid encodings that exceed the limit.
|
||||
if limit < 0 || len(s) <= limit {
|
||||
return s
|
||||
}
|
||||
|
||||
// Optimistically, assume all valid UTF-8.
|
||||
var b strings.Builder
|
||||
count := 0
|
||||
for i, c := range s {
|
||||
if c != utf8.RuneError {
|
||||
count++
|
||||
if count > limit {
|
||||
return s[:i]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
// Invalid encoding.
|
||||
b.Grow(len(s) - 1)
|
||||
_, _ = b.WriteString(s[:i])
|
||||
s = s[i:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Fast-path, no invalid input.
|
||||
if b.Cap() == 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
// Truncate while validating UTF-8.
|
||||
for i := 0; i < len(s) && count < limit; {
|
||||
c := s[i]
|
||||
if c < utf8.RuneSelf {
|
||||
// Optimization for single byte runes (common case).
|
||||
_ = b.WriteByte(c)
|
||||
i++
|
||||
count++
|
||||
continue
|
||||
}
|
||||
|
||||
_, size := utf8.DecodeRuneInString(s[i:])
|
||||
if size == 1 {
|
||||
// We checked for all 1-byte runes above, this is a RuneError.
|
||||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
_, _ = b.WriteString(s[i : i+size])
|
||||
i += size
|
||||
count++
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (s *autoSpan) End(opts ...SpanEndOption) {
|
||||
if s == nil || !s.sampled.Swap(false) {
|
||||
return
|
||||
}
|
||||
|
||||
// s.end exists so the lock (s.mu) is not held while s.ended is called.
|
||||
s.ended(s.end(opts))
|
||||
}
|
||||
|
||||
func (s *autoSpan) end(opts []SpanEndOption) []byte {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
cfg := NewSpanEndConfig(opts...)
|
||||
if t := cfg.Timestamp(); !t.IsZero() {
|
||||
s.span.EndTime = cfg.Timestamp()
|
||||
} else {
|
||||
s.span.EndTime = time.Now()
|
||||
}
|
||||
|
||||
b, _ := json.Marshal(s.traces) // TODO: do not ignore this error.
|
||||
return b
|
||||
}
|
||||
|
||||
// Expected to be implemented in eBPF.
|
||||
//
|
||||
//go:noinline
|
||||
func (*autoSpan) ended(buf []byte) { ended(buf) }
|
||||
|
||||
// ended is used for testing.
|
||||
var ended = func([]byte) {}
|
||||
|
||||
func (s *autoSpan) RecordError(err error, opts ...EventOption) {
|
||||
if s == nil || err == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
cfg := NewEventConfig(opts...)
|
||||
|
||||
attrs := cfg.Attributes()
|
||||
attrs = append(attrs,
|
||||
semconv.ExceptionType(typeStr(err)),
|
||||
semconv.ExceptionMessage(err.Error()),
|
||||
)
|
||||
if cfg.StackTrace() {
|
||||
buf := make([]byte, 2048)
|
||||
n := runtime.Stack(buf, false)
|
||||
attrs = append(attrs, semconv.ExceptionStacktrace(string(buf[0:n])))
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.addEvent(semconv.ExceptionEventName, cfg.Timestamp(), attrs)
|
||||
}
|
||||
|
||||
func typeStr(i any) string {
|
||||
t := reflect.TypeOf(i)
|
||||
if t.PkgPath() == "" && t.Name() == "" {
|
||||
// Likely a builtin type.
|
||||
return t.String()
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", t.PkgPath(), t.Name())
|
||||
}
|
||||
|
||||
func (s *autoSpan) AddEvent(name string, opts ...EventOption) {
|
||||
if s == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
cfg := NewEventConfig(opts...)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.addEvent(name, cfg.Timestamp(), cfg.Attributes())
|
||||
}
|
||||
|
||||
// addEvent adds an event with name and attrs at tStamp to the span. The span
|
||||
// lock (s.mu) needs to be held by the caller.
|
||||
func (s *autoSpan) addEvent(name string, tStamp time.Time, attrs []attribute.KeyValue) {
|
||||
limit := maxSpan.Events
|
||||
|
||||
if limit == 0 {
|
||||
s.span.DroppedEvents++
|
||||
return
|
||||
}
|
||||
|
||||
if limit > 0 && len(s.span.Events) == limit {
|
||||
// Drop head while avoiding allocation of more capacity.
|
||||
copy(s.span.Events[:limit-1], s.span.Events[1:])
|
||||
s.span.Events = s.span.Events[:limit-1]
|
||||
s.span.DroppedEvents++
|
||||
}
|
||||
|
||||
e := &telemetry.SpanEvent{Time: tStamp, Name: name}
|
||||
e.Attrs, e.DroppedAttrs = convCappedAttrs(maxSpan.EventAttrs, attrs)
|
||||
|
||||
s.span.Events = append(s.span.Events, e)
|
||||
}
|
||||
|
||||
func (s *autoSpan) AddLink(link Link) {
|
||||
if s == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
l := maxSpan.Links
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if l == 0 {
|
||||
s.span.DroppedLinks++
|
||||
return
|
||||
}
|
||||
|
||||
if l > 0 && len(s.span.Links) == l {
|
||||
// Drop head while avoiding allocation of more capacity.
|
||||
copy(s.span.Links[:l-1], s.span.Links[1:])
|
||||
s.span.Links = s.span.Links[:l-1]
|
||||
s.span.DroppedLinks++
|
||||
}
|
||||
|
||||
s.span.Links = append(s.span.Links, convLink(link))
|
||||
}
|
||||
|
||||
func convLinks(links []Link) []*telemetry.SpanLink {
|
||||
out := make([]*telemetry.SpanLink, 0, len(links))
|
||||
for _, link := range links {
|
||||
out = append(out, convLink(link))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func convLink(link Link) *telemetry.SpanLink {
|
||||
l := &telemetry.SpanLink{
|
||||
TraceID: telemetry.TraceID(link.SpanContext.TraceID()),
|
||||
SpanID: telemetry.SpanID(link.SpanContext.SpanID()),
|
||||
TraceState: link.SpanContext.TraceState().String(),
|
||||
Flags: uint32(link.SpanContext.TraceFlags()),
|
||||
}
|
||||
l.Attrs, l.DroppedAttrs = convCappedAttrs(maxSpan.LinkAttrs, link.Attributes)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (s *autoSpan) SetName(name string) {
|
||||
if s == nil || !s.sampled.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
s.span.Name = name
|
||||
}
|
||||
|
||||
func (*autoSpan) TracerProvider() TracerProvider { return newAutoTracerProvider() }
|
||||
|
||||
// maxSpan are the span limits resolved during startup.
|
||||
var maxSpan = newSpanLimits()
|
||||
|
||||
type spanLimits struct {
|
||||
// Attrs is the number of allowed attributes for a span.
|
||||
//
|
||||
// This is resolved from the environment variable value for the
|
||||
// OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT key if it exists. Otherwise, the
|
||||
// environment variable value for OTEL_ATTRIBUTE_COUNT_LIMIT, or 128 if
|
||||
// that is not set, is used.
|
||||
Attrs int
|
||||
// AttrValueLen is the maximum attribute value length allowed for a span.
|
||||
//
|
||||
// This is resolved from the environment variable value for the
|
||||
// OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT key if it exists. Otherwise, the
|
||||
// environment variable value for OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, or -1
|
||||
// if that is not set, is used.
|
||||
AttrValueLen int
|
||||
// Events is the number of allowed events for a span.
|
||||
//
|
||||
// This is resolved from the environment variable value for the
|
||||
// OTEL_SPAN_EVENT_COUNT_LIMIT key, or 128 is used if that is not set.
|
||||
Events int
|
||||
// EventAttrs is the number of allowed attributes for a span event.
|
||||
//
|
||||
// The is resolved from the environment variable value for the
|
||||
// OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT key, or 128 is used if that is not set.
|
||||
EventAttrs int
|
||||
// Links is the number of allowed Links for a span.
|
||||
//
|
||||
// This is resolved from the environment variable value for the
|
||||
// OTEL_SPAN_LINK_COUNT_LIMIT, or 128 is used if that is not set.
|
||||
Links int
|
||||
// LinkAttrs is the number of allowed attributes for a span link.
|
||||
//
|
||||
// This is resolved from the environment variable value for the
|
||||
// OTEL_LINK_ATTRIBUTE_COUNT_LIMIT, or 128 is used if that is not set.
|
||||
LinkAttrs int
|
||||
}
|
||||
|
||||
func newSpanLimits() spanLimits {
|
||||
return spanLimits{
|
||||
Attrs: firstEnv(
|
||||
128,
|
||||
"OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT",
|
||||
"OTEL_ATTRIBUTE_COUNT_LIMIT",
|
||||
),
|
||||
AttrValueLen: firstEnv(
|
||||
-1, // Unlimited.
|
||||
"OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT",
|
||||
"OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT",
|
||||
),
|
||||
Events: firstEnv(128, "OTEL_SPAN_EVENT_COUNT_LIMIT"),
|
||||
EventAttrs: firstEnv(128, "OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT"),
|
||||
Links: firstEnv(128, "OTEL_SPAN_LINK_COUNT_LIMIT"),
|
||||
LinkAttrs: firstEnv(128, "OTEL_LINK_ATTRIBUTE_COUNT_LIMIT"),
|
||||
}
|
||||
}
|
||||
|
||||
// firstEnv returns the parsed integer value of the first matching environment
|
||||
// variable from keys. The defaultVal is returned if the value is not an
|
||||
// integer or no match is found.
|
||||
func firstEnv(defaultVal int, keys ...string) int {
|
||||
for _, key := range keys {
|
||||
strV := os.Getenv(key)
|
||||
if strV == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
v, err := strconv.Atoi(strV)
|
||||
if err == nil {
|
||||
return v
|
||||
}
|
||||
// Ignore invalid environment variable.
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
Reference in New Issue
Block a user