Initial QSfera import
This commit is contained in:
Generated
Vendored
+119
@@ -0,0 +1,119 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package observ // import "go.opentelemetry.io/otel/sdk/trace/internal/observ"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/sdk"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.40.0"
|
||||
"go.opentelemetry.io/otel/semconv/v1.40.0/otelconv"
|
||||
)
|
||||
|
||||
const (
|
||||
// ScopeName is the name of the instrumentation scope.
|
||||
ScopeName = "go.opentelemetry.io/otel/sdk/trace/internal/observ"
|
||||
|
||||
// SchemaURL is the schema URL of the instrumentation.
|
||||
SchemaURL = semconv.SchemaURL
|
||||
)
|
||||
|
||||
// ErrQueueFull is the attribute value for the "queue_full" error type.
|
||||
var ErrQueueFull = otelconv.SDKProcessorSpanProcessed{}.AttrErrorType(
|
||||
otelconv.ErrorTypeAttr("queue_full"),
|
||||
)
|
||||
|
||||
// BSPComponentName returns the component name attribute for a
|
||||
// BatchSpanProcessor with the given ID.
|
||||
func BSPComponentName(id int64) attribute.KeyValue {
|
||||
t := otelconv.ComponentTypeBatchingSpanProcessor
|
||||
name := fmt.Sprintf("%s/%d", t, id)
|
||||
return semconv.OTelComponentName(name)
|
||||
}
|
||||
|
||||
// BSP is the instrumentation for an OTel SDK BatchSpanProcessor.
|
||||
type BSP struct {
|
||||
reg metric.Registration
|
||||
|
||||
processed metric.Int64Counter
|
||||
processedOpts []metric.AddOption
|
||||
processedQueueFullOpts []metric.AddOption
|
||||
}
|
||||
|
||||
func NewBSP(id int64, qLen func() int64, qMax int64) (*BSP, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
meter := otel.GetMeterProvider().Meter(
|
||||
ScopeName,
|
||||
metric.WithInstrumentationVersion(sdk.Version()),
|
||||
metric.WithSchemaURL(SchemaURL),
|
||||
)
|
||||
|
||||
qCap, err := otelconv.NewSDKProcessorSpanQueueCapacity(meter)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create BSP queue capacity metric: %w", err)
|
||||
}
|
||||
qCapInst := qCap.Inst()
|
||||
|
||||
qSize, e := otelconv.NewSDKProcessorSpanQueueSize(meter)
|
||||
if e != nil {
|
||||
e := fmt.Errorf("failed to create BSP queue size metric: %w", e)
|
||||
err = errors.Join(err, e)
|
||||
}
|
||||
qSizeInst := qSize.Inst()
|
||||
|
||||
cmpntT := semconv.OTelComponentTypeBatchingSpanProcessor
|
||||
cmpnt := BSPComponentName(id)
|
||||
set := attribute.NewSet(cmpnt, cmpntT)
|
||||
|
||||
obsOpts := []metric.ObserveOption{metric.WithAttributeSet(set)}
|
||||
reg, e := meter.RegisterCallback(
|
||||
func(_ context.Context, o metric.Observer) error {
|
||||
o.ObserveInt64(qSizeInst, qLen(), obsOpts...)
|
||||
o.ObserveInt64(qCapInst, qMax, obsOpts...)
|
||||
return nil
|
||||
},
|
||||
qSizeInst,
|
||||
qCapInst,
|
||||
)
|
||||
if e != nil {
|
||||
e := fmt.Errorf("failed to register BSP queue size/capacity callback: %w", e)
|
||||
err = errors.Join(err, e)
|
||||
}
|
||||
|
||||
processed, e := otelconv.NewSDKProcessorSpanProcessed(meter)
|
||||
if e != nil {
|
||||
e := fmt.Errorf("failed to create BSP processed spans metric: %w", e)
|
||||
err = errors.Join(err, e)
|
||||
}
|
||||
processedOpts := []metric.AddOption{metric.WithAttributeSet(set)}
|
||||
|
||||
set = attribute.NewSet(cmpnt, cmpntT, ErrQueueFull)
|
||||
processedQueueFullOpts := []metric.AddOption{metric.WithAttributeSet(set)}
|
||||
|
||||
return &BSP{
|
||||
reg: reg,
|
||||
processed: processed.Inst(),
|
||||
processedOpts: processedOpts,
|
||||
processedQueueFullOpts: processedQueueFullOpts,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (b *BSP) Shutdown() error { return b.reg.Unregister() }
|
||||
|
||||
func (b *BSP) Processed(ctx context.Context, n int64) {
|
||||
b.processed.Add(ctx, n, b.processedOpts...)
|
||||
}
|
||||
|
||||
func (b *BSP) ProcessedQueueFull(ctx context.Context, n int64) {
|
||||
b.processed.Add(ctx, n, b.processedQueueFullOpts...)
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package observ provides observability instrumentation for the OTel trace SDK
|
||||
// package.
|
||||
package observ // import "go.opentelemetry.io/otel/sdk/trace/internal/observ"
|
||||
Generated
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package observ // import "go.opentelemetry.io/otel/sdk/trace/internal/observ"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/sdk"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.40.0"
|
||||
"go.opentelemetry.io/otel/semconv/v1.40.0/otelconv"
|
||||
)
|
||||
|
||||
var measureAttrsPool = sync.Pool{
|
||||
New: func() any {
|
||||
// "component.name" + "component.type" + "error.type"
|
||||
const n = 1 + 1 + 1
|
||||
s := make([]attribute.KeyValue, 0, n)
|
||||
// Return a pointer to a slice instead of a slice itself
|
||||
// to avoid allocations on every call.
|
||||
return &s
|
||||
},
|
||||
}
|
||||
|
||||
// SSP is the instrumentation for an OTel SDK SimpleSpanProcessor.
|
||||
type SSP struct {
|
||||
spansProcessedCounter metric.Int64Counter
|
||||
addOpts []metric.AddOption
|
||||
attrs []attribute.KeyValue
|
||||
}
|
||||
|
||||
// SSPComponentName returns the component name attribute for a
|
||||
// SimpleSpanProcessor with the given ID.
|
||||
func SSPComponentName(id int64) attribute.KeyValue {
|
||||
t := otelconv.ComponentTypeSimpleSpanProcessor
|
||||
name := fmt.Sprintf("%s/%d", t, id)
|
||||
return semconv.OTelComponentName(name)
|
||||
}
|
||||
|
||||
// NewSSP returns instrumentation for an OTel SDK SimpleSpanProcessor with the
|
||||
// provided ID.
|
||||
//
|
||||
// If the experimental observability is disabled, nil is returned.
|
||||
func NewSSP(id int64) (*SSP, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
meter := otel.GetMeterProvider().Meter(
|
||||
ScopeName,
|
||||
metric.WithInstrumentationVersion(sdk.Version()),
|
||||
metric.WithSchemaURL(SchemaURL),
|
||||
)
|
||||
spansProcessedCounter, err := otelconv.NewSDKProcessorSpanProcessed(meter)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create SSP processed spans metric: %w", err)
|
||||
}
|
||||
|
||||
componentName := SSPComponentName(id)
|
||||
componentType := spansProcessedCounter.AttrComponentType(otelconv.ComponentTypeSimpleSpanProcessor)
|
||||
attrs := []attribute.KeyValue{componentName, componentType}
|
||||
addOpts := []metric.AddOption{metric.WithAttributeSet(attribute.NewSet(attrs...))}
|
||||
|
||||
return &SSP{
|
||||
spansProcessedCounter: spansProcessedCounter.Inst(),
|
||||
addOpts: addOpts,
|
||||
attrs: attrs,
|
||||
}, err
|
||||
}
|
||||
|
||||
// SpanProcessed records that a span has been processed by the SimpleSpanProcessor.
|
||||
// If err is non-nil, it records the processing error as an attribute.
|
||||
func (ssp *SSP) SpanProcessed(ctx context.Context, err error) {
|
||||
ssp.spansProcessedCounter.Add(ctx, 1, ssp.addOption(err)...)
|
||||
}
|
||||
|
||||
func (ssp *SSP) addOption(err error) []metric.AddOption {
|
||||
if err == nil {
|
||||
return ssp.addOpts
|
||||
}
|
||||
attrs := measureAttrsPool.Get().(*[]attribute.KeyValue)
|
||||
defer func() {
|
||||
*attrs = (*attrs)[:0] // reset the slice for reuse
|
||||
measureAttrsPool.Put(attrs)
|
||||
}()
|
||||
*attrs = append(*attrs, ssp.attrs...)
|
||||
*attrs = append(*attrs, semconv.ErrorType(err))
|
||||
// Do not inefficiently make a copy of attrs by using
|
||||
// WithAttributes instead of WithAttributeSet.
|
||||
return []metric.AddOption{metric.WithAttributeSet(attribute.NewSet(*attrs...))}
|
||||
}
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package observ // import "go.opentelemetry.io/otel/sdk/trace/internal/observ"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/sdk"
|
||||
"go.opentelemetry.io/otel/sdk/internal/x"
|
||||
"go.opentelemetry.io/otel/semconv/v1.40.0/otelconv"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var meterOpts = []metric.MeterOption{
|
||||
metric.WithInstrumentationVersion(sdk.Version()),
|
||||
metric.WithSchemaURL(SchemaURL),
|
||||
}
|
||||
|
||||
// Tracer is instrumentation for an OTel SDK Tracer.
|
||||
type Tracer struct {
|
||||
enabled bool
|
||||
|
||||
live metric.Int64UpDownCounter
|
||||
started metric.Int64Counter
|
||||
}
|
||||
|
||||
func NewTracer() (Tracer, error) {
|
||||
if !x.Observability.Enabled() {
|
||||
return Tracer{}, nil
|
||||
}
|
||||
meter := otel.GetMeterProvider().Meter(ScopeName, meterOpts...)
|
||||
|
||||
var err error
|
||||
l, e := otelconv.NewSDKSpanLive(meter)
|
||||
if e != nil {
|
||||
e = fmt.Errorf("failed to create span live metric: %w", e)
|
||||
err = errors.Join(err, e)
|
||||
}
|
||||
|
||||
s, e := otelconv.NewSDKSpanStarted(meter)
|
||||
if e != nil {
|
||||
e = fmt.Errorf("failed to create span started metric: %w", e)
|
||||
err = errors.Join(err, e)
|
||||
}
|
||||
|
||||
return Tracer{enabled: true, live: l.Inst(), started: s.Inst()}, err
|
||||
}
|
||||
|
||||
func (t Tracer) Enabled() bool { return t.enabled }
|
||||
|
||||
func (t Tracer) SpanStarted(ctx context.Context, psc trace.SpanContext, span trace.Span) {
|
||||
if !t.started.Enabled(ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
key := spanStartedKey{
|
||||
parent: parentStateNoParent,
|
||||
sampling: samplingStateDrop,
|
||||
}
|
||||
|
||||
if psc.IsValid() {
|
||||
if psc.IsRemote() {
|
||||
key.parent = parentStateRemoteParent
|
||||
} else {
|
||||
key.parent = parentStateLocalParent
|
||||
}
|
||||
}
|
||||
|
||||
if span.IsRecording() {
|
||||
if span.SpanContext().IsSampled() {
|
||||
key.sampling = samplingStateRecordAndSample
|
||||
} else {
|
||||
key.sampling = samplingStateRecordOnly
|
||||
}
|
||||
}
|
||||
|
||||
opts := spanStartedOpts[key]
|
||||
t.started.Add(ctx, 1, opts...)
|
||||
}
|
||||
|
||||
func (t Tracer) SpanLive(ctx context.Context, span trace.Span) {
|
||||
t.spanLive(ctx, 1, span)
|
||||
}
|
||||
|
||||
func (t Tracer) SpanEnded(ctx context.Context, span trace.Span) {
|
||||
t.spanLive(ctx, -1, span)
|
||||
}
|
||||
|
||||
func (t Tracer) spanLive(ctx context.Context, value int64, span trace.Span) {
|
||||
if !t.live.Enabled(ctx) {
|
||||
return
|
||||
}
|
||||
|
||||
key := spanLiveKey{sampled: span.SpanContext().IsSampled()}
|
||||
opts := spanLiveOpts[key]
|
||||
t.live.Add(ctx, value, opts...)
|
||||
}
|
||||
|
||||
type parentState int
|
||||
|
||||
const (
|
||||
parentStateNoParent parentState = iota
|
||||
parentStateLocalParent
|
||||
parentStateRemoteParent
|
||||
)
|
||||
|
||||
type samplingState int
|
||||
|
||||
const (
|
||||
samplingStateDrop samplingState = iota
|
||||
samplingStateRecordOnly
|
||||
samplingStateRecordAndSample
|
||||
)
|
||||
|
||||
type spanStartedKey struct {
|
||||
parent parentState
|
||||
sampling samplingState
|
||||
}
|
||||
|
||||
var spanStartedOpts = map[spanStartedKey][]metric.AddOption{
|
||||
{
|
||||
parentStateNoParent,
|
||||
samplingStateDrop,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginNone),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultDrop),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateLocalParent,
|
||||
samplingStateDrop,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginLocal),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultDrop),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateRemoteParent,
|
||||
samplingStateDrop,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginRemote),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultDrop),
|
||||
)),
|
||||
},
|
||||
|
||||
{
|
||||
parentStateNoParent,
|
||||
samplingStateRecordOnly,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginNone),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordOnly),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateLocalParent,
|
||||
samplingStateRecordOnly,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginLocal),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordOnly),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateRemoteParent,
|
||||
samplingStateRecordOnly,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginRemote),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordOnly),
|
||||
)),
|
||||
},
|
||||
|
||||
{
|
||||
parentStateNoParent,
|
||||
samplingStateRecordAndSample,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginNone),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordAndSample),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateLocalParent,
|
||||
samplingStateRecordAndSample,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginLocal),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordAndSample),
|
||||
)),
|
||||
},
|
||||
{
|
||||
parentStateRemoteParent,
|
||||
samplingStateRecordAndSample,
|
||||
}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanStarted{}.AttrSpanParentOrigin(otelconv.SpanParentOriginRemote),
|
||||
otelconv.SDKSpanStarted{}.AttrSpanSamplingResult(otelconv.SpanSamplingResultRecordAndSample),
|
||||
)),
|
||||
},
|
||||
}
|
||||
|
||||
type spanLiveKey struct {
|
||||
sampled bool
|
||||
}
|
||||
|
||||
var spanLiveOpts = map[spanLiveKey][]metric.AddOption{
|
||||
{true}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanLive{}.AttrSpanSamplingResult(
|
||||
otelconv.SpanSamplingResultRecordAndSample,
|
||||
),
|
||||
)),
|
||||
},
|
||||
{false}: {
|
||||
metric.WithAttributeSet(attribute.NewSet(
|
||||
otelconv.SDKSpanLive{}.AttrSpanSamplingResult(
|
||||
otelconv.SpanSamplingResultRecordOnly,
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user