// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package observ // import "go.opentelemetry.io/otel/sdk/trace/internal/observ"

import (
	
	
	

	
	
	
	
	
	
	
)

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 () (Tracer, error) {
	if !x.Observability.Enabled() {
		return Tracer{}, nil
	}
	 := otel.GetMeterProvider().Meter(ScopeName, meterOpts...)

	var  error
	,  := otelconv.NewSDKSpanLive()
	if  != nil {
		 = fmt.Errorf("failed to create span live metric: %w", )
		 = errors.Join(, )
	}

	,  := otelconv.NewSDKSpanStarted()
	if  != nil {
		 = fmt.Errorf("failed to create span started metric: %w", )
		 = errors.Join(, )
	}

	return Tracer{enabled: true, live: .Inst(), started: .Inst()}, 
}

func ( Tracer) () bool { return .enabled }

func ( Tracer) ( context.Context,  trace.SpanContext,  trace.Span) {
	 := spanStartedKey{
		parent:   parentStateNoParent,
		sampling: samplingStateDrop,
	}

	if .IsValid() {
		if .IsRemote() {
			.parent = parentStateRemoteParent
		} else {
			.parent = parentStateLocalParent
		}
	}

	if .IsRecording() {
		if .SpanContext().IsSampled() {
			.sampling = samplingStateRecordAndSample
		} else {
			.sampling = samplingStateRecordOnly
		}
	}

	 := spanStartedOpts[]
	.started.Add(, 1, ...)
}

func ( Tracer) ( context.Context,  trace.Span) {
	.spanLive(, 1, )
}

func ( Tracer) ( context.Context,  trace.Span) {
	.spanLive(, -1, )
}

func ( Tracer) ( context.Context,  int64,  trace.Span) {
	 := spanLiveKey{sampled: .SpanContext().IsSampled()}
	 := spanLiveOpts[]
	.live.Add(, , ...)
}

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,
			),
		)),
	},
}