diff --git a/daemon/command/daemon.go b/daemon/command/daemon.go index 40f5b541b5..7e0430ab25 100644 --- a/daemon/command/daemon.go +++ b/daemon/command/daemon.go @@ -61,6 +61,7 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/pflag" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/bridge/opencensus" "go.opentelemetry.io/otel/propagation" "tags.cncf.io/container-device-interface/pkg/cdi" ) @@ -240,6 +241,11 @@ func (cli *daemonCLI) start(ctx context.Context) (err error) { tp, otelShutdown := otelutil.NewTracerProvider(ctx, true) otel.SetTracerProvider(tp) log.G(ctx).Logger.AddHook(tracing.NewLogrusHook()) + // The github.com/microsoft/hcsshim module is instrumented with + // OpenCensus, but we use OpenTelemetry for tracing in the daemon. + // Bridge OpenCensus to OpenTelemetry so OC trace spans are exported to + // the daemon's configured OTEL collector. + opencensus.InstallTraceBridge() pluginStore := plugin.NewStore() diff --git a/go.mod b/go.mod index 5f8d4c629f..4c45217763 100644 --- a/go.mod +++ b/go.mod @@ -101,6 +101,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 go.opentelemetry.io/contrib/processors/baggagecopy v0.4.0 go.opentelemetry.io/otel v1.38.0 + go.opentelemetry.io/otel/bridge/opencensus v1.38.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 go.opentelemetry.io/otel/sdk v1.38.0 go.opentelemetry.io/otel/trace v1.38.0 diff --git a/go.sum b/go.sum index c0445f0771..228f7c8e7b 100644 --- a/go.sum +++ b/go.sum @@ -665,6 +665,8 @@ go.opentelemetry.io/contrib/processors/baggagecopy v0.4.0 h1:SUsGRzllvPRJK6VKn1S go.opentelemetry.io/contrib/processors/baggagecopy v0.4.0/go.mod h1:68LCyaHcLhUf3tciKAAbSFKkr4Pkrt24ei0/xHm0No8= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/bridge/opencensus v1.38.0 h1:LUFKh5lYqNalr6E2Wr54fymStzDmlDQoVWp5UlJ8yG0= +go.opentelemetry.io/otel/bridge/opencensus v1.38.0/go.mod h1:84yBtJ/OnEa2I40lMyrGadED8nVH/JfzoK+5p7aYyIY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 h1:vl9obrcoWVKp/lwl8tRE33853I8Xru9HFbw/skNeLs8= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0/go.mod h1:GAXRxmLJcVM3u22IjTg74zWBrRCKq8BnOqUVLodpcpw= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 h1:Oe2z/BCg5q7k4iXC3cqJxKYg0ieRiOqF0cecFYdPTwk= diff --git a/vendor/go.opencensus.io/metric/metricdata/doc.go b/vendor/go.opencensus.io/metric/metricdata/doc.go new file mode 100644 index 0000000000..52a7b3bf85 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/doc.go @@ -0,0 +1,19 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package metricdata contains the metrics data model. +// +// This is an EXPERIMENTAL package, and may change in arbitrary ways without +// notice. +package metricdata // import "go.opencensus.io/metric/metricdata" diff --git a/vendor/go.opencensus.io/metric/metricdata/exemplar.go b/vendor/go.opencensus.io/metric/metricdata/exemplar.go new file mode 100644 index 0000000000..12695ce2dc --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/exemplar.go @@ -0,0 +1,38 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricdata + +import ( + "time" +) + +// Exemplars keys. +const ( + AttachmentKeySpanContext = "SpanContext" +) + +// Exemplar is an example data point associated with each bucket of a +// distribution type aggregation. +// +// Their purpose is to provide an example of the kind of thing +// (request, RPC, trace span, etc.) that resulted in that measurement. +type Exemplar struct { + Value float64 // the value that was recorded + Timestamp time.Time // the time the value was recorded + Attachments Attachments // attachments (if any) +} + +// Attachments is a map of extra values associated with a recorded data point. +type Attachments map[string]interface{} diff --git a/vendor/go.opencensus.io/metric/metricdata/label.go b/vendor/go.opencensus.io/metric/metricdata/label.go new file mode 100644 index 0000000000..aadae41e6a --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/label.go @@ -0,0 +1,35 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricdata + +// LabelKey represents key of a label. It has optional +// description attribute. +type LabelKey struct { + Key string + Description string +} + +// LabelValue represents the value of a label. +// The zero value represents a missing label value, which may be treated +// differently to an empty string value by some back ends. +type LabelValue struct { + Value string // string value of the label + Present bool // flag that indicated whether a value is present or not +} + +// NewLabelValue creates a new non-nil LabelValue that represents the given string. +func NewLabelValue(val string) LabelValue { + return LabelValue{Value: val, Present: true} +} diff --git a/vendor/go.opencensus.io/metric/metricdata/metric.go b/vendor/go.opencensus.io/metric/metricdata/metric.go new file mode 100644 index 0000000000..8293712c77 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/metric.go @@ -0,0 +1,46 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricdata + +import ( + "time" + + "go.opencensus.io/resource" +) + +// Descriptor holds metadata about a metric. +type Descriptor struct { + Name string // full name of the metric + Description string // human-readable description + Unit Unit // units for the measure + Type Type // type of measure + LabelKeys []LabelKey // label keys +} + +// Metric represents a quantity measured against a resource with different +// label value combinations. +type Metric struct { + Descriptor Descriptor // metric descriptor + Resource *resource.Resource // resource against which this was measured + TimeSeries []*TimeSeries // one time series for each combination of label values +} + +// TimeSeries is a sequence of points associated with a combination of label +// values. +type TimeSeries struct { + LabelValues []LabelValue // label values, same order as keys in the metric descriptor + Points []Point // points sequence + StartTime time.Time // time we started recording this time series +} diff --git a/vendor/go.opencensus.io/metric/metricdata/point.go b/vendor/go.opencensus.io/metric/metricdata/point.go new file mode 100644 index 0000000000..7fe057b19c --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/point.go @@ -0,0 +1,193 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricdata + +import ( + "time" +) + +// Point is a single data point of a time series. +type Point struct { + // Time is the point in time that this point represents in a time series. + Time time.Time + // Value is the value of this point. Prefer using ReadValue to switching on + // the value type, since new value types might be added. + Value interface{} +} + +//go:generate stringer -type ValueType + +// NewFloat64Point creates a new Point holding a float64 value. +func NewFloat64Point(t time.Time, val float64) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewInt64Point creates a new Point holding an int64 value. +func NewInt64Point(t time.Time, val int64) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewDistributionPoint creates a new Point holding a Distribution value. +func NewDistributionPoint(t time.Time, val *Distribution) Point { + return Point{ + Value: val, + Time: t, + } +} + +// NewSummaryPoint creates a new Point holding a Summary value. +func NewSummaryPoint(t time.Time, val *Summary) Point { + return Point{ + Value: val, + Time: t, + } +} + +// ValueVisitor allows reading the value of a point. +type ValueVisitor interface { + VisitFloat64Value(float64) + VisitInt64Value(int64) + VisitDistributionValue(*Distribution) + VisitSummaryValue(*Summary) +} + +// ReadValue accepts a ValueVisitor and calls the appropriate method with the +// value of this point. +// Consumers of Point should use this in preference to switching on the type +// of the value directly, since new value types may be added. +func (p Point) ReadValue(vv ValueVisitor) { + switch v := p.Value.(type) { + case int64: + vv.VisitInt64Value(v) + case float64: + vv.VisitFloat64Value(v) + case *Distribution: + vv.VisitDistributionValue(v) + case *Summary: + vv.VisitSummaryValue(v) + default: + panic("unexpected value type") + } +} + +// Distribution contains summary statistics for a population of values. It +// optionally contains a histogram representing the distribution of those +// values across a set of buckets. +type Distribution struct { + // Count is the number of values in the population. Must be non-negative. This value + // must equal the sum of the values in bucket_counts if a histogram is + // provided. + Count int64 + // Sum is the sum of the values in the population. If count is zero then this field + // must be zero. + Sum float64 + // SumOfSquaredDeviation is the sum of squared deviations from the mean of the values in the + // population. For values x_i this is: + // + // Sum[i=1..n]((x_i - mean)^2) + // + // Knuth, "The Art of Computer Programming", Vol. 2, page 323, 3rd edition + // describes Welford's method for accumulating this sum in one pass. + // + // If count is zero then this field must be zero. + SumOfSquaredDeviation float64 + // BucketOptions describes the bounds of the histogram buckets in this + // distribution. + // + // A Distribution may optionally contain a histogram of the values in the + // population. + // + // If nil, there is no associated histogram. + BucketOptions *BucketOptions + // Bucket If the distribution does not have a histogram, then omit this field. + // If there is a histogram, then the sum of the values in the Bucket counts + // must equal the value in the count field of the distribution. + Buckets []Bucket +} + +// BucketOptions describes the bounds of the histogram buckets in this +// distribution. +type BucketOptions struct { + // Bounds specifies a set of bucket upper bounds. + // This defines len(bounds) + 1 (= N) buckets. The boundaries for bucket + // index i are: + // + // [0, Bounds[i]) for i == 0 + // [Bounds[i-1], Bounds[i]) for 0 < i < N-1 + // [Bounds[i-1], +infinity) for i == N-1 + Bounds []float64 +} + +// Bucket represents a single bucket (value range) in a distribution. +type Bucket struct { + // Count is the number of values in each bucket of the histogram, as described in + // bucket_bounds. + Count int64 + // Exemplar associated with this bucket (if any). + Exemplar *Exemplar +} + +// Summary is a representation of percentiles. +type Summary struct { + // Count is the cumulative count (if available). + Count int64 + // Sum is the cumulative sum of values (if available). + Sum float64 + // HasCountAndSum is true if Count and Sum are available. + HasCountAndSum bool + // Snapshot represents percentiles calculated over an arbitrary time window. + // The values in this struct can be reset at arbitrary unknown times, with + // the requirement that all of them are reset at the same time. + Snapshot Snapshot +} + +// Snapshot represents percentiles over an arbitrary time. +// The values in this struct can be reset at arbitrary unknown times, with +// the requirement that all of them are reset at the same time. +type Snapshot struct { + // Count is the number of values in the snapshot. Optional since some systems don't + // expose this. Set to 0 if not available. + Count int64 + // Sum is the sum of values in the snapshot. Optional since some systems don't + // expose this. If count is 0 then this field must be zero. + Sum float64 + // Percentiles is a map from percentile (range (0-100.0]) to the value of + // the percentile. + Percentiles map[float64]float64 +} + +//go:generate stringer -type Type + +// Type is the overall type of metric, including its value type and whether it +// represents a cumulative total (since the start time) or if it represents a +// gauge value. +type Type int + +// Metric types. +const ( + TypeGaugeInt64 Type = iota + TypeGaugeFloat64 + TypeGaugeDistribution + TypeCumulativeInt64 + TypeCumulativeFloat64 + TypeCumulativeDistribution + TypeSummary +) diff --git a/vendor/go.opencensus.io/metric/metricdata/type_string.go b/vendor/go.opencensus.io/metric/metricdata/type_string.go new file mode 100644 index 0000000000..c3f8ec27b5 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/type_string.go @@ -0,0 +1,16 @@ +// Code generated by "stringer -type Type"; DO NOT EDIT. + +package metricdata + +import "strconv" + +const _Type_name = "TypeGaugeInt64TypeGaugeFloat64TypeGaugeDistributionTypeCumulativeInt64TypeCumulativeFloat64TypeCumulativeDistributionTypeSummary" + +var _Type_index = [...]uint8{0, 14, 30, 51, 70, 91, 117, 128} + +func (i Type) String() string { + if i < 0 || i >= Type(len(_Type_index)-1) { + return "Type(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Type_name[_Type_index[i]:_Type_index[i+1]] +} diff --git a/vendor/go.opencensus.io/metric/metricdata/unit.go b/vendor/go.opencensus.io/metric/metricdata/unit.go new file mode 100644 index 0000000000..b483a1371b --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricdata/unit.go @@ -0,0 +1,27 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricdata + +// Unit is a string encoded according to the case-sensitive abbreviations from the +// Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html +type Unit string + +// Predefined units. To record against a unit not represented here, create your +// own Unit type constant from a string. +const ( + UnitDimensionless Unit = "1" + UnitBytes Unit = "By" + UnitMilliseconds Unit = "ms" +) diff --git a/vendor/go.opencensus.io/metric/metricproducer/manager.go b/vendor/go.opencensus.io/metric/metricproducer/manager.go new file mode 100644 index 0000000000..ca1f390493 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricproducer/manager.go @@ -0,0 +1,78 @@ +// Copyright 2019, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricproducer + +import ( + "sync" +) + +// Manager maintains a list of active producers. Producers can register +// with the manager to allow readers to read all metrics provided by them. +// Readers can retrieve all producers registered with the manager, +// read metrics from the producers and export them. +type Manager struct { + mu sync.RWMutex + producers map[Producer]struct{} +} + +var prodMgr *Manager +var once sync.Once + +// GlobalManager is a single instance of producer manager +// that is used by all producers and all readers. +func GlobalManager() *Manager { + once.Do(func() { + prodMgr = &Manager{} + prodMgr.producers = make(map[Producer]struct{}) + }) + return prodMgr +} + +// AddProducer adds the producer to the Manager if it is not already present. +func (pm *Manager) AddProducer(producer Producer) { + if producer == nil { + return + } + pm.mu.Lock() + defer pm.mu.Unlock() + pm.producers[producer] = struct{}{} +} + +// DeleteProducer deletes the producer from the Manager if it is present. +func (pm *Manager) DeleteProducer(producer Producer) { + if producer == nil { + return + } + pm.mu.Lock() + defer pm.mu.Unlock() + delete(pm.producers, producer) +} + +// GetAll returns a slice of all producer currently registered with +// the Manager. For each call it generates a new slice. The slice +// should not be cached as registration may change at any time. It is +// typically called periodically by exporter to read metrics from +// the producers. +func (pm *Manager) GetAll() []Producer { + pm.mu.Lock() + defer pm.mu.Unlock() + producers := make([]Producer, len(pm.producers)) + i := 0 + for producer := range pm.producers { + producers[i] = producer + i++ + } + return producers +} diff --git a/vendor/go.opencensus.io/metric/metricproducer/producer.go b/vendor/go.opencensus.io/metric/metricproducer/producer.go new file mode 100644 index 0000000000..6cee9ed178 --- /dev/null +++ b/vendor/go.opencensus.io/metric/metricproducer/producer.go @@ -0,0 +1,28 @@ +// Copyright 2019, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package metricproducer + +import ( + "go.opencensus.io/metric/metricdata" +) + +// Producer is a source of metrics. +type Producer interface { + // Read should return the current values of all metrics supported by this + // metric provider. + // The returned metrics should be unique for each combination of name and + // resource. + Read() []*metricdata.Metric +} diff --git a/vendor/go.opencensus.io/resource/resource.go b/vendor/go.opencensus.io/resource/resource.go new file mode 100644 index 0000000000..b1764e1d3b --- /dev/null +++ b/vendor/go.opencensus.io/resource/resource.go @@ -0,0 +1,164 @@ +// Copyright 2018, OpenCensus Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package resource provides functionality for resource, which capture +// identifying information about the entities for which signals are exported. +package resource + +import ( + "context" + "fmt" + "os" + "regexp" + "sort" + "strconv" + "strings" +) + +// Environment variables used by FromEnv to decode a resource. +const ( + EnvVarType = "OC_RESOURCE_TYPE" + EnvVarLabels = "OC_RESOURCE_LABELS" +) + +// Resource describes an entity about which identifying information and metadata is exposed. +// For example, a type "k8s.io/container" may hold labels describing the pod name and namespace. +type Resource struct { + Type string + Labels map[string]string +} + +// EncodeLabels encodes a labels map to a string as provided via the OC_RESOURCE_LABELS environment variable. +func EncodeLabels(labels map[string]string) string { + sortedKeys := make([]string, 0, len(labels)) + for k := range labels { + sortedKeys = append(sortedKeys, k) + } + sort.Strings(sortedKeys) + + s := "" + for i, k := range sortedKeys { + if i > 0 { + s += "," + } + s += k + "=" + strconv.Quote(labels[k]) + } + return s +} + +var labelRegex = regexp.MustCompile(`^\s*([[:ascii:]]{1,256}?)=("[[:ascii:]]{0,256}?")\s*,`) + +// DecodeLabels decodes a serialized label map as used in the OC_RESOURCE_LABELS variable. +// A list of labels of the form `="",="",...` is accepted. +// Domain names and paths are accepted as label keys. +// Most users will want to use FromEnv instead. +func DecodeLabels(s string) (map[string]string, error) { + m := map[string]string{} + // Ensure a trailing comma, which allows us to keep the regex simpler + s = strings.TrimRight(strings.TrimSpace(s), ",") + "," + + for len(s) > 0 { + match := labelRegex.FindStringSubmatch(s) + if len(match) == 0 { + return nil, fmt.Errorf("invalid label formatting, remainder: %s", s) + } + v := match[2] + if v == "" { + v = match[3] + } else { + var err error + if v, err = strconv.Unquote(v); err != nil { + return nil, fmt.Errorf("invalid label formatting, remainder: %s, err: %s", s, err) + } + } + m[match[1]] = v + + s = s[len(match[0]):] + } + return m, nil +} + +// FromEnv is a detector that loads resource information from the OC_RESOURCE_TYPE +// and OC_RESOURCE_labelS environment variables. +func FromEnv(context.Context) (*Resource, error) { + res := &Resource{ + Type: strings.TrimSpace(os.Getenv(EnvVarType)), + } + labels := strings.TrimSpace(os.Getenv(EnvVarLabels)) + if labels == "" { + return res, nil + } + var err error + if res.Labels, err = DecodeLabels(labels); err != nil { + return nil, err + } + return res, nil +} + +var _ Detector = FromEnv + +// merge resource information from b into a. In case of a collision, a takes precedence. +func merge(a, b *Resource) *Resource { + if a == nil { + return b + } + if b == nil { + return a + } + res := &Resource{ + Type: a.Type, + Labels: map[string]string{}, + } + if res.Type == "" { + res.Type = b.Type + } + for k, v := range b.Labels { + res.Labels[k] = v + } + // Labels from resource a overwrite labels from resource b. + for k, v := range a.Labels { + res.Labels[k] = v + } + return res +} + +// Detector attempts to detect resource information. +// If the detector cannot find resource information, the returned resource is nil but no +// error is returned. +// An error is only returned on unexpected failures. +type Detector func(context.Context) (*Resource, error) + +// MultiDetector returns a Detector that calls all input detectors in order and +// merges each result with the previous one. In case a type of label key is already set, +// the first set value is takes precedence. +// It returns on the first error that a sub-detector encounters. +func MultiDetector(detectors ...Detector) Detector { + return func(ctx context.Context) (*Resource, error) { + return detectAll(ctx, detectors...) + } +} + +// detectall calls all input detectors sequentially an merges each result with the previous one. +// It returns on the first error that a sub-detector encounters. +func detectAll(ctx context.Context, detectors ...Detector) (*Resource, error) { + var res *Resource + for _, d := range detectors { + r, err := d(ctx) + if err != nil { + return nil, err + } + res = merge(res, r) + } + return res, nil +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/LICENSE b/vendor/go.opentelemetry.io/otel/bridge/opencensus/LICENSE new file mode 100644 index 0000000000..f1aee0f110 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/LICENSE @@ -0,0 +1,231 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/README.md b/vendor/go.opentelemetry.io/otel/bridge/opencensus/README.md new file mode 100644 index 0000000000..f80f8d7a37 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/README.md @@ -0,0 +1,3 @@ +# OpenTelemetry/OpenCensus Bridge + +[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/bridge/opencensus)](https://pkg.go.dev/go.opentelemetry.io/otel/bridge/opencensus) diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/config.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/config.go new file mode 100644 index 0000000000..ddd8e58a5f --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/config.go @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" + +import ( + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" +) + +const scopeName = "go.opentelemetry.io/otel/bridge/opencensus" + +// newTraceConfig returns a config configured with options. +func newTraceConfig(options []TraceOption) traceConfig { + conf := traceConfig{tp: otel.GetTracerProvider()} + for _, o := range options { + conf = o.apply(conf) + } + return conf +} + +type traceConfig struct { + tp trace.TracerProvider +} + +// TraceOption applies a configuration option value to an OpenCensus bridge +// Tracer. +type TraceOption interface { + apply(traceConfig) traceConfig +} + +// traceOptionFunc applies a set of options to a config. +type traceOptionFunc func(traceConfig) traceConfig + +// apply returns a config with option(s) applied. +func (o traceOptionFunc) apply(conf traceConfig) traceConfig { + return o(conf) +} + +// WithTracerProvider specifies a tracer provider to use for creating a tracer. +func WithTracerProvider(tp trace.TracerProvider) TraceOption { + return traceOptionFunc(func(conf traceConfig) traceConfig { + conf.tp = tp + return conf + }) +} + +type metricConfig struct{} + +// MetricOption applies a configuration option value to an OpenCensus bridge +// MetricProducer. +type MetricOption interface { + apply(metricConfig) metricConfig +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/doc.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/doc.go new file mode 100644 index 0000000000..0f5d4abb8c --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/doc.go @@ -0,0 +1,48 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package opencensus provides a migration bridge from OpenCensus to +// OpenTelemetry for metrics and traces. The bridge incorporates metrics and +// traces from OpenCensus into the OpenTelemetry SDK, combining them with +// metrics and traces from OpenTelemetry instrumentation. +// +// # Migration Guide +// +// For most applications, it would be difficult to migrate an application +// from OpenCensus to OpenTelemetry all-at-once. Libraries used by the +// application may still be using OpenCensus, and the application itself may +// have many lines of instrumentation. +// +// Bridges help in this situation by allowing your application to have "mixed" +// instrumentation, while incorporating all instrumentation into a single +// export path. To migrate with bridges, a user would: +// +// 1. Configure the OpenTelemetry SDK for metrics and traces, with the OpenTelemetry exporters matching to your current OpenCensus exporters. +// 2. Install this OpenCensus bridge, which sends OpenCensus telemetry to your new OpenTelemetry exporters. +// 3. Over time, migrate your instrumentation from OpenCensus to OpenTelemetry. +// 4. Once all instrumentation is migrated, remove the OpenCensus bridge. +// +// With this approach, you can migrate your telemetry, including in dependent +// libraries over time without disruption. +// +// # Warnings +// +// Installing a metric or tracing bridge will cause OpenCensus telemetry to be +// exported by OpenTelemetry exporters. Since OpenCensus telemetry uses globals, +// installing a bridge will result in telemetry collection from _all_ libraries +// that use OpenCensus, including some you may not expect, such as the +// telemetry exporter itself. +// +// # Limitations +// +// There are known limitations to the trace bridge: +// +// - The NewContext method of the OpenCensus Tracer cannot embed an OpenCensus +// Span in a context unless that Span was created by that Tracer. +// - Conversion of custom OpenCensus Samplers to OpenTelemetry is not +// implemented, and An error will be sent to the OpenTelemetry ErrorHandler. +// +// There are known limitations to the metric bridge: +// - GaugeDistribution-typed metrics are dropped +// - Histogram's SumOfSquaredDeviation field is dropped +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/handler.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/handler.go new file mode 100644 index 0000000000..5bf1650408 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/handler.go @@ -0,0 +1,11 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package internal provides internal functionality for the opencensus package. +package internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" + +import "go.opentelemetry.io/otel" + +// Handle is the package level function to handle errors. It can be +// overwritten for testing. +var Handle = otel.Handle diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/attributes.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/attributes.go new file mode 100644 index 0000000000..4179f5cfb7 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/attributes.go @@ -0,0 +1,48 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package oc2otel provides conversion from OpenCensus to OpenTelemetry. +package oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + +import ( + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/attribute" +) + +func Attributes(attr []octrace.Attribute) []attribute.KeyValue { + otelAttr := make([]attribute.KeyValue, len(attr)) + for i, a := range attr { + otelAttr[i] = attribute.KeyValue{ + Key: attribute.Key(a.Key()), + Value: AttributeValue(a.Value()), + } + } + return otelAttr +} + +func AttributesFromMap(attr map[string]any) []attribute.KeyValue { + otelAttr := make([]attribute.KeyValue, 0, len(attr)) + for k, v := range attr { + otelAttr = append(otelAttr, attribute.KeyValue{ + Key: attribute.Key(k), + Value: AttributeValue(v), + }) + } + return otelAttr +} + +func AttributeValue(ocval any) attribute.Value { + switch v := ocval.(type) { + case bool: + return attribute.BoolValue(v) + case int64: + return attribute.Int64Value(v) + case float64: + return attribute.Float64Value(v) + case string: + return attribute.StringValue(v) + default: + return attribute.StringValue("unknown") + } +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/span_context.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/span_context.go new file mode 100644 index 0000000000..2a866f7f8b --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/span_context.go @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + +import ( + "slices" + + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/trace" +) + +func SpanContext(sc octrace.SpanContext) trace.SpanContext { + var traceFlags trace.TraceFlags + if sc.IsSampled() { + traceFlags = trace.FlagsSampled + } + + entries := slices.Clone(sc.Tracestate.Entries()) + slices.Reverse(entries) + + tsOtel := trace.TraceState{} + for _, entry := range entries { + tsOtel, _ = tsOtel.Insert(entry.Key, entry.Value) + } + + return trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: trace.TraceID(sc.TraceID), + SpanID: trace.SpanID(sc.SpanID), + TraceFlags: traceFlags, + TraceState: tsOtel, + }) +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/tracer_start_options.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/tracer_start_options.go new file mode 100644 index 0000000000..e09a90605c --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel/tracer_start_options.go @@ -0,0 +1,35 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package oc2otel // import "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + +import ( + "fmt" + + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/trace" +) + +func StartOptions(optFuncs []octrace.StartOption) ([]trace.SpanStartOption, error) { + var ocOpts octrace.StartOptions + for _, fn := range optFuncs { + fn(&ocOpts) + } + + var otelOpts []trace.SpanStartOption + switch ocOpts.SpanKind { + case octrace.SpanKindClient: + otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindClient)) + case octrace.SpanKindServer: + otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindServer)) + case octrace.SpanKindUnspecified: + otelOpts = append(otelOpts, trace.WithSpanKind(trace.SpanKindUnspecified)) + } + + var err error + if ocOpts.Sampler != nil { + err = fmt.Errorf("unsupported sampler: %v", ocOpts.Sampler) + } + return otelOpts, err +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric/metric.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric/metric.go new file mode 100644 index 0000000000..70ab55bb56 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric/metric.go @@ -0,0 +1,425 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package internal provides internal functionality for the opencensus package. +package internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric" + +import ( + "cmp" + "errors" + "fmt" + "math" + "reflect" + "slices" + "strconv" + + ocmetricdata "go.opencensus.io/metric/metricdata" + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/metric/metricdata" +) + +var ( + errAggregationType = errors.New("unsupported OpenCensus aggregation type") + errMismatchedValueTypes = errors.New("wrong value type for data point") + errNegativeCount = errors.New("distribution or summary count is negative") + errNegativeBucketCount = errors.New("distribution bucket count is negative") + errMismatchedAttributeKeyValues = errors.New("mismatched number of attribute keys and values") + errInvalidExemplarSpanContext = errors.New( + "span context exemplar attachment does not contain an OpenCensus SpanContext", + ) +) + +// ConvertMetrics converts metric data from OpenCensus to OpenTelemetry. +func ConvertMetrics(ocmetrics []*ocmetricdata.Metric) ([]metricdata.Metrics, error) { + otelMetrics := make([]metricdata.Metrics, 0, len(ocmetrics)) + var err error + for _, ocm := range ocmetrics { + if ocm == nil { + continue + } + agg, aggregationErr := convertAggregation(ocm) + if aggregationErr != nil { + err = errors.Join(err, fmt.Errorf("error converting metric %v: %w", ocm.Descriptor.Name, aggregationErr)) + continue + } + otelMetrics = append(otelMetrics, metricdata.Metrics{ + Name: ocm.Descriptor.Name, + Description: ocm.Descriptor.Description, + Unit: string(ocm.Descriptor.Unit), + Data: agg, + }) + } + if err != nil { + return otelMetrics, fmt.Errorf("error converting from OpenCensus to OpenTelemetry: %w", err) + } + return otelMetrics, nil +} + +// convertAggregation produces an aggregation based on the OpenCensus Metric. +func convertAggregation(metric *ocmetricdata.Metric) (metricdata.Aggregation, error) { + labelKeys := metric.Descriptor.LabelKeys + switch metric.Descriptor.Type { + case ocmetricdata.TypeGaugeInt64: + return convertGauge[int64](labelKeys, metric.TimeSeries) + case ocmetricdata.TypeGaugeFloat64: + return convertGauge[float64](labelKeys, metric.TimeSeries) + case ocmetricdata.TypeCumulativeInt64: + return convertSum[int64](labelKeys, metric.TimeSeries) + case ocmetricdata.TypeCumulativeFloat64: + return convertSum[float64](labelKeys, metric.TimeSeries) + case ocmetricdata.TypeCumulativeDistribution: + return convertHistogram(labelKeys, metric.TimeSeries) + case ocmetricdata.TypeSummary: + return convertSummary(labelKeys, metric.TimeSeries) + } + return nil, fmt.Errorf("%w: %q", errAggregationType, metric.Descriptor.Type) +} + +// convertGauge converts an OpenCensus gauge to an OpenTelemetry gauge aggregation. +func convertGauge[N int64 | float64]( + labelKeys []ocmetricdata.LabelKey, + ts []*ocmetricdata.TimeSeries, +) (metricdata.Gauge[N], error) { + points, err := convertNumberDataPoints[N](labelKeys, ts) + return metricdata.Gauge[N]{DataPoints: points}, err +} + +// convertSum converts an OpenCensus cumulative to an OpenTelemetry sum aggregation. +func convertSum[N int64 | float64]( + labelKeys []ocmetricdata.LabelKey, + ts []*ocmetricdata.TimeSeries, +) (metricdata.Sum[N], error) { + points, err := convertNumberDataPoints[N](labelKeys, ts) + // OpenCensus sums are always Cumulative + return metricdata.Sum[N]{DataPoints: points, Temporality: metricdata.CumulativeTemporality, IsMonotonic: true}, err +} + +// convertNumberDataPoints converts OpenCensus TimeSeries to OpenTelemetry DataPoints. +func convertNumberDataPoints[N int64 | float64]( + labelKeys []ocmetricdata.LabelKey, + ts []*ocmetricdata.TimeSeries, +) ([]metricdata.DataPoint[N], error) { + var points []metricdata.DataPoint[N] + var err error + for _, t := range ts { + attrs, attrsErr := convertAttrs(labelKeys, t.LabelValues) + if attrsErr != nil { + err = errors.Join(err, attrsErr) + continue + } + for _, p := range t.Points { + v, ok := p.Value.(N) + if !ok { + err = errors.Join(err, fmt.Errorf("%w: %q", errMismatchedValueTypes, p.Value)) + continue + } + points = append(points, metricdata.DataPoint[N]{ + Attributes: attrs, + StartTime: t.StartTime, + Time: p.Time, + Value: v, + }) + } + } + return points, err +} + +// convertHistogram converts OpenCensus Distribution timeseries to an +// OpenTelemetry Histogram aggregation. +func convertHistogram( + labelKeys []ocmetricdata.LabelKey, + ts []*ocmetricdata.TimeSeries, +) (metricdata.Histogram[float64], error) { + points := make([]metricdata.HistogramDataPoint[float64], 0, len(ts)) + var err error + for _, t := range ts { + attrs, attrsErr := convertAttrs(labelKeys, t.LabelValues) + if attrsErr != nil { + err = errors.Join(err, attrsErr) + continue + } + for _, p := range t.Points { + dist, ok := p.Value.(*ocmetricdata.Distribution) + if !ok { + err = errors.Join(err, fmt.Errorf("%w: %d", errMismatchedValueTypes, p.Value)) + continue + } + bucketCounts, exemplars, bucketErr := convertBuckets(dist.Buckets) + if bucketErr != nil { + err = errors.Join(err, bucketErr) + continue + } + if dist.Count < 0 { + err = errors.Join(err, fmt.Errorf("%w: %d", errNegativeCount, dist.Count)) + continue + } + points = append(points, metricdata.HistogramDataPoint[float64]{ + Attributes: attrs, + StartTime: t.StartTime, + Time: p.Time, + Count: uint64(max(0, dist.Count)), // nolint:gosec // A count should never be negative. + Sum: dist.Sum, + Bounds: dist.BucketOptions.Bounds, + BucketCounts: bucketCounts, + Exemplars: exemplars, + }) + } + } + return metricdata.Histogram[float64]{DataPoints: points, Temporality: metricdata.CumulativeTemporality}, err +} + +// convertBuckets converts from OpenCensus bucket counts to slice of uint64, +// and converts OpenCensus exemplars to OpenTelemetry exemplars. +func convertBuckets(buckets []ocmetricdata.Bucket) ([]uint64, []metricdata.Exemplar[float64], error) { + bucketCounts := make([]uint64, len(buckets)) + exemplars := []metricdata.Exemplar[float64]{} + var err error + for i, bucket := range buckets { + if bucket.Count < 0 { + err = errors.Join(err, fmt.Errorf("%w: %q", errNegativeBucketCount, bucket.Count)) + continue + } + bucketCounts[i] = uint64(max(0, bucket.Count)) // nolint:gosec // A count should never be negative. + + if bucket.Exemplar != nil { + exemplar, exemplarErr := convertExemplar(bucket.Exemplar) + if exemplarErr != nil { + err = errors.Join(err, exemplarErr) + continue + } + exemplars = append(exemplars, exemplar) + } + } + return bucketCounts, exemplars, err +} + +// convertExemplar converts an OpenCensus exemplar to an OpenTelemetry exemplar. +func convertExemplar(ocExemplar *ocmetricdata.Exemplar) (metricdata.Exemplar[float64], error) { + exemplar := metricdata.Exemplar[float64]{ + Value: ocExemplar.Value, + Time: ocExemplar.Timestamp, + } + var err error + for k, v := range ocExemplar.Attachments { + switch k { + case ocmetricdata.AttachmentKeySpanContext: + sc, ok := v.(octrace.SpanContext) + if !ok { + err = errors.Join(err, fmt.Errorf("%w; type: %v", errInvalidExemplarSpanContext, reflect.TypeOf(v))) + continue + } + exemplar.SpanID = sc.SpanID[:] + exemplar.TraceID = sc.TraceID[:] + default: + exemplar.FilteredAttributes = append(exemplar.FilteredAttributes, convertKV(k, v)) + } + } + slices.SortFunc(exemplar.FilteredAttributes, func(a, b attribute.KeyValue) int { + return cmp.Compare(a.Key, b.Key) + }) + return exemplar, err +} + +// convertKV converts an OpenCensus Attachment to an OpenTelemetry KeyValue. +func convertKV(key string, value any) attribute.KeyValue { + switch typedVal := value.(type) { + case bool: + return attribute.Bool(key, typedVal) + case int: + return attribute.Int(key, typedVal) + case int8: + return attribute.Int(key, int(typedVal)) + case int16: + return attribute.Int(key, int(typedVal)) + case int32: + return attribute.Int(key, int(typedVal)) + case int64: + return attribute.Int64(key, typedVal) + case uint: + return uintKV(key, typedVal) + case uint8: + return uintKV(key, uint(typedVal)) + case uint16: + return uintKV(key, uint(typedVal)) + case uint32: + return uintKV(key, uint(typedVal)) + case uintptr: + return uint64KV(key, uint64(typedVal)) + case uint64: + return uint64KV(key, typedVal) + case float32: + return attribute.Float64(key, float64(typedVal)) + case float64: + return attribute.Float64(key, typedVal) + case complex64: + return attribute.String(key, complexToString(typedVal)) + case complex128: + return attribute.String(key, complexToString(typedVal)) + case string: + return attribute.String(key, typedVal) + case []bool: + return attribute.BoolSlice(key, typedVal) + case []int: + return attribute.IntSlice(key, typedVal) + case []int8: + return intSliceKV(key, typedVal) + case []int16: + return intSliceKV(key, typedVal) + case []int32: + return intSliceKV(key, typedVal) + case []int64: + return attribute.Int64Slice(key, typedVal) + case []uint: + return uintSliceKV(key, typedVal) + case []uint8: + return uintSliceKV(key, typedVal) + case []uint16: + return uintSliceKV(key, typedVal) + case []uint32: + return uintSliceKV(key, typedVal) + case []uintptr: + return uintSliceKV(key, typedVal) + case []uint64: + return uintSliceKV(key, typedVal) + case []float32: + floatSlice := make([]float64, len(typedVal)) + for i := range typedVal { + floatSlice[i] = float64(typedVal[i]) + } + return attribute.Float64Slice(key, floatSlice) + case []float64: + return attribute.Float64Slice(key, typedVal) + case []complex64: + return complexSliceKV(key, typedVal) + case []complex128: + return complexSliceKV(key, typedVal) + case []string: + return attribute.StringSlice(key, typedVal) + case fmt.Stringer: + return attribute.Stringer(key, typedVal) + default: + return attribute.String(key, fmt.Sprintf("unhandled attribute value: %+v", value)) + } +} + +func intSliceKV[N int8 | int16 | int32](key string, val []N) attribute.KeyValue { + intSlice := make([]int, len(val)) + for i := range val { + intSlice[i] = int(val[i]) + } + return attribute.IntSlice(key, intSlice) +} + +func uintKV(key string, val uint) attribute.KeyValue { + if val > uint(math.MaxInt) { + return attribute.String(key, strconv.FormatUint(uint64(val), 10)) + } + return attribute.Int(key, int(val)) // nolint: gosec // Overflow checked above. +} + +func uintSliceKV[N uint | uint8 | uint16 | uint32 | uint64 | uintptr](key string, val []N) attribute.KeyValue { + strSlice := make([]string, len(val)) + for i := range val { + strSlice[i] = strconv.FormatUint(uint64(val[i]), 10) + } + return attribute.StringSlice(key, strSlice) +} + +func uint64KV(key string, val uint64) attribute.KeyValue { + const maxInt64 = ^uint64(0) >> 1 + if val > maxInt64 { + return attribute.String(key, strconv.FormatUint(val, 10)) + } + return attribute.Int64(key, int64(val)) // nolint: gosec // Overflow checked above. +} + +func complexSliceKV[N complex64 | complex128](key string, val []N) attribute.KeyValue { + strSlice := make([]string, len(val)) + for i := range val { + strSlice[i] = complexToString(val[i]) + } + return attribute.StringSlice(key, strSlice) +} + +func complexToString[N complex64 | complex128](val N) string { + return strconv.FormatComplex(complex128(val), 'f', -1, 64) +} + +// convertSummary converts OpenCensus Summary timeseries to an +// OpenTelemetry Summary. +func convertSummary(labelKeys []ocmetricdata.LabelKey, ts []*ocmetricdata.TimeSeries) (metricdata.Summary, error) { + points := make([]metricdata.SummaryDataPoint, 0, len(ts)) + var err error + for _, t := range ts { + attrs, attrErr := convertAttrs(labelKeys, t.LabelValues) + if attrErr != nil { + err = errors.Join(err, attrErr) + continue + } + for _, p := range t.Points { + summary, ok := p.Value.(*ocmetricdata.Summary) + if !ok { + err = errors.Join(err, fmt.Errorf("%w: %d", errMismatchedValueTypes, p.Value)) + continue + } + if summary.Count < 0 { + err = errors.Join(err, fmt.Errorf("%w: %d", errNegativeCount, summary.Count)) + continue + } + point := metricdata.SummaryDataPoint{ + Attributes: attrs, + StartTime: t.StartTime, + Time: p.Time, + Count: uint64(max(0, summary.Count)), // nolint:gosec // A count should never be negative. + QuantileValues: convertQuantiles(summary.Snapshot), + Sum: summary.Sum, + } + points = append(points, point) + } + } + return metricdata.Summary{DataPoints: points}, err +} + +// convertQuantiles converts an OpenCensus summary snapshot to +// OpenTelemetry quantiles. +func convertQuantiles(snapshot ocmetricdata.Snapshot) []metricdata.QuantileValue { + quantileValues := make([]metricdata.QuantileValue, 0, len(snapshot.Percentiles)) + for quantile, value := range snapshot.Percentiles { + quantileValues = append(quantileValues, metricdata.QuantileValue{ + // OpenCensus quantiles are range (0-100.0], but OpenTelemetry + // quantiles are range [0.0, 1.0]. + Quantile: quantile / 100.0, + Value: value, + }) + } + slices.SortFunc(quantileValues, func(a, b metricdata.QuantileValue) int { + return cmp.Compare(a.Quantile, b.Quantile) + }) + return quantileValues +} + +// convertAttrs converts from OpenCensus attribute keys and values to an +// OpenTelemetry attribute Set. +func convertAttrs(keys []ocmetricdata.LabelKey, values []ocmetricdata.LabelValue) (attribute.Set, error) { + if len(keys) != len(values) { + return attribute.NewSet(), fmt.Errorf( + "%w: keys(%q) values(%q)", + errMismatchedAttributeKeyValues, + len(keys), + len(values), + ) + } + attrs := []attribute.KeyValue{} + for i, lv := range values { + if !lv.Present { + continue + } + attrs = append(attrs, attribute.KeyValue{ + Key: attribute.Key(keys[i].Key), + Value: attribute.StringValue(lv.Value), + }) + } + return attribute.NewSet(attrs...), nil +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc/span_context.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc/span_context.go new file mode 100644 index 0000000000..2dbf7efd8a --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc/span_context.go @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package otel2oc provides conversions from OpenTelemetry to OpenCensus. +package otel2oc // import "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" + +import ( + octrace "go.opencensus.io/trace" + "go.opencensus.io/trace/tracestate" + + "go.opentelemetry.io/otel/trace" +) + +func SpanContext(sc trace.SpanContext) octrace.SpanContext { + var to octrace.TraceOptions + if sc.IsSampled() { + // OpenCensus doesn't expose functions to directly set sampled + to = 0x1 + } + + entries := make([]tracestate.Entry, 0, sc.TraceState().Len()) + sc.TraceState().Walk(func(key, value string) bool { + entries = append(entries, tracestate.Entry{Key: key, Value: value}) + return true + }) + tsOc, _ := tracestate.New(nil, entries...) + + return octrace.SpanContext{ + TraceID: octrace.TraceID(sc.TraceID()), + SpanID: octrace.SpanID(sc.SpanID()), + TraceOptions: to, + Tracestate: tsOc, + } +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/span.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/span.go new file mode 100644 index 0000000000..4e7e1c35bd --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/span.go @@ -0,0 +1,132 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" + +import ( + "fmt" + + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" +) + +const ( + // MessageSendEvent is the name of the message send event. + MessageSendEvent = "message send" + // MessageReceiveEvent is the name of the message receive event. + MessageReceiveEvent = "message receive" +) + +var ( + // UncompressedKey is used for the uncompressed byte size attribute. + UncompressedKey = attribute.Key("uncompressed byte size") + // CompressedKey is used for the compressed byte size attribute. + CompressedKey = attribute.Key("compressed byte size") +) + +// Span is an OpenCensus SpanInterface wrapper for an OpenTelemetry Span. +type Span struct { + otelSpan trace.Span +} + +// NewSpan returns an OpenCensus Span wrapping an OpenTelemetry Span. +func NewSpan(s trace.Span) *octrace.Span { + return octrace.NewSpan(&Span{otelSpan: s}) +} + +// IsRecordingEvents reports whether events are being recorded for this span. +func (s *Span) IsRecordingEvents() bool { + return s.otelSpan.IsRecording() +} + +// End ends this span. +func (s *Span) End() { + s.otelSpan.End() +} + +// SpanContext returns the SpanContext of this span. +func (s *Span) SpanContext() octrace.SpanContext { + return otel2oc.SpanContext(s.otelSpan.SpanContext()) +} + +// SetName sets the name of this span, if it is recording events. +func (s *Span) SetName(name string) { + s.otelSpan.SetName(name) +} + +// SetStatus sets the status of this span, if it is recording events. +func (s *Span) SetStatus(status octrace.Status) { + s.otelSpan.SetStatus(codes.Code(max(0, status.Code)), status.Message) // nolint:gosec // Overflow checked. +} + +// AddAttributes sets attributes in this span. +func (s *Span) AddAttributes(attributes ...octrace.Attribute) { + s.otelSpan.SetAttributes(oc2otel.Attributes(attributes)...) +} + +// Annotate adds an annotation with attributes to this span. +func (s *Span) Annotate(attributes []octrace.Attribute, str string) { + s.otelSpan.AddEvent(str, trace.WithAttributes(oc2otel.Attributes(attributes)...)) +} + +// Annotatef adds a formatted annotation with attributes to this span. +func (s *Span) Annotatef(attributes []octrace.Attribute, format string, a ...any) { + s.Annotate(attributes, fmt.Sprintf(format, a...)) +} + +// AddMessageSendEvent adds a message send event to this span. +func (s *Span) AddMessageSendEvent(_, uncompressedByteSize, compressedByteSize int64) { + s.otelSpan.AddEvent(MessageSendEvent, + trace.WithAttributes( + attribute.KeyValue{ + Key: UncompressedKey, + Value: attribute.Int64Value(uncompressedByteSize), + }, + attribute.KeyValue{ + Key: CompressedKey, + Value: attribute.Int64Value(compressedByteSize), + }), + ) +} + +// AddMessageReceiveEvent adds a message receive event to this span. +func (s *Span) AddMessageReceiveEvent(_, uncompressedByteSize, compressedByteSize int64) { + s.otelSpan.AddEvent(MessageReceiveEvent, + trace.WithAttributes( + attribute.KeyValue{ + Key: UncompressedKey, + Value: attribute.Int64Value(uncompressedByteSize), + }, + attribute.KeyValue{ + Key: CompressedKey, + Value: attribute.Int64Value(compressedByteSize), + }), + ) +} + +// AddLink adds a link to this span. +// This drops the OpenCensus LinkType because there is no such concept in OpenTelemetry. +func (s *Span) AddLink(l octrace.Link) { + s.otelSpan.AddLink(trace.Link{ + SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: trace.TraceID(l.TraceID), + SpanID: trace.SpanID(l.SpanID), + // We don't know if this was sampled or not. + // Mark it as sampled, since sampled means + // "the caller may have recorded trace data": + // https://www.w3.org/TR/trace-context/#sampled-flag + TraceFlags: trace.FlagsSampled, + }), + Attributes: oc2otel.AttributesFromMap(l.Attributes), + }) +} + +// String prints a string representation of this span. +func (s *Span) String() string { + return "span " + s.otelSpan.SpanContext().SpanID().String() +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/tracer.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/tracer.go new file mode 100644 index 0000000000..db301976bb --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/internal/tracer.go @@ -0,0 +1,69 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "go.opentelemetry.io/otel/bridge/opencensus/internal" + +import ( + "context" + "fmt" + + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + "go.opentelemetry.io/otel/trace" +) + +// Tracer is an OpenCensus Tracer that wraps an OpenTelemetry Tracer. +type Tracer struct { + otelTracer trace.Tracer +} + +// NewTracer returns an OpenCensus Tracer that wraps the OpenTelemetry tracer. +func NewTracer(tracer trace.Tracer) octrace.Tracer { + return &Tracer{otelTracer: tracer} +} + +// StartSpan starts a new child span of the current span in the context. If +// there is no span in the context, it creates a new trace and span. +func (o *Tracer) StartSpan( + ctx context.Context, + name string, + s ...octrace.StartOption, +) (context.Context, *octrace.Span) { + otelOpts, err := oc2otel.StartOptions(s) + if err != nil { + Handle(fmt.Errorf("starting span %q: %w", name, err)) + } + ctx, sp := o.otelTracer.Start(ctx, name, otelOpts...) + return ctx, NewSpan(sp) +} + +// StartSpanWithRemoteParent starts a new child span of the span from the +// given parent. +func (o *Tracer) StartSpanWithRemoteParent( + ctx context.Context, + name string, + parent octrace.SpanContext, + s ...octrace.StartOption, +) (context.Context, *octrace.Span) { + // make sure span context is zeroed out so we use the remote parent + ctx = trace.ContextWithSpan(ctx, nil) + ctx = trace.ContextWithRemoteSpanContext(ctx, oc2otel.SpanContext(parent)) + return o.StartSpan(ctx, name, s...) +} + +// FromContext returns the Span stored in a context. +func (*Tracer) FromContext(ctx context.Context) *octrace.Span { + return NewSpan(trace.SpanFromContext(ctx)) +} + +// NewContext returns a new context with the given Span attached. +func (*Tracer) NewContext(parent context.Context, s *octrace.Span) context.Context { + if otSpan, ok := s.Internal().(*Span); ok { + return trace.ContextWithSpan(parent, otSpan.otelSpan) + } + Handle( + fmt.Errorf("unable to create context with span %q, since it was created using a different tracer", s.String()), + ) + return parent +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/metric.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/metric.go new file mode 100644 index 0000000000..5bf343b916 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/metric.go @@ -0,0 +1,53 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" + +import ( + "context" + + ocmetricdata "go.opencensus.io/metric/metricdata" + "go.opencensus.io/metric/metricproducer" + + internal "go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" +) + +// MetricProducer implements the [go.opentelemetry.io/otel/sdk/metric.Producer] to provide metrics +// from OpenCensus to the OpenTelemetry SDK. +type MetricProducer struct { + manager *metricproducer.Manager +} + +// NewMetricProducer returns a metric.Producer that fetches metrics from +// OpenCensus. +func NewMetricProducer(...MetricOption) *MetricProducer { + return &MetricProducer{ + manager: metricproducer.GlobalManager(), + } +} + +var _ metric.Producer = (*MetricProducer)(nil) + +// Produce fetches metrics from the OpenCensus manager, +// translates them to OpenTelemetry's data model, and returns them. +func (p *MetricProducer) Produce(context.Context) ([]metricdata.ScopeMetrics, error) { + producers := p.manager.GetAll() + data := []*ocmetricdata.Metric{} + for _, ocProducer := range producers { + data = append(data, ocProducer.Read()...) + } + otelmetrics, err := internal.ConvertMetrics(data) + if len(otelmetrics) == 0 { + return nil, err + } + return []metricdata.ScopeMetrics{{ + Scope: instrumentation.Scope{ + Name: scopeName, + Version: Version(), + }, + Metrics: otelmetrics, + }}, err +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/trace.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/trace.go new file mode 100644 index 0000000000..0ff72b9e9c --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/trace.go @@ -0,0 +1,40 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" + +import ( + octrace "go.opencensus.io/trace" + + "go.opentelemetry.io/otel/bridge/opencensus/internal" + "go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel" + "go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc" + "go.opentelemetry.io/otel/trace" +) + +// InstallTraceBridge installs the OpenCensus trace bridge, which overwrites +// the global OpenCensus tracer implementation. Once the bridge is installed, +// spans recorded using OpenCensus are redirected to the OpenTelemetry SDK. +func InstallTraceBridge(opts ...TraceOption) { + octrace.DefaultTracer = newTraceBridge(opts) +} + +func newTraceBridge(opts []TraceOption) octrace.Tracer { + cfg := newTraceConfig(opts) + return internal.NewTracer( + cfg.tp.Tracer(scopeName, trace.WithInstrumentationVersion(Version())), + ) +} + +// OTelSpanContextToOC converts from an OpenTelemetry SpanContext to an +// OpenCensus SpanContext, and handles any incompatibilities with the global +// error handler. +func OTelSpanContextToOC(sc trace.SpanContext) octrace.SpanContext { + return otel2oc.SpanContext(sc) +} + +// OCSpanContextToOTel converts from an OpenCensus SpanContext to an +// OpenTelemetry SpanContext. +func OCSpanContextToOTel(sc octrace.SpanContext) trace.SpanContext { + return oc2otel.SpanContext(sc) +} diff --git a/vendor/go.opentelemetry.io/otel/bridge/opencensus/version.go b/vendor/go.opentelemetry.io/otel/bridge/opencensus/version.go new file mode 100644 index 0000000000..4c5b03698e --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/bridge/opencensus/version.go @@ -0,0 +1,9 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus" + +// Version is the current release version of the opencensus bridge. +func Version() string { + return "1.38.0" +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f35818b7ba..16497eb2ab 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1414,6 +1414,9 @@ go.etcd.io/raft/v3/tracker ## explicit; go 1.13 go.opencensus.io go.opencensus.io/internal +go.opencensus.io/metric/metricdata +go.opencensus.io/metric/metricproducer +go.opencensus.io/resource go.opencensus.io/trace go.opencensus.io/trace/internal go.opencensus.io/trace/tracestate @@ -1455,6 +1458,13 @@ go.opentelemetry.io/otel/semconv/v1.26.0 go.opentelemetry.io/otel/semconv/v1.30.0 go.opentelemetry.io/otel/semconv/v1.37.0 go.opentelemetry.io/otel/semconv/v1.37.0/otelconv +# go.opentelemetry.io/otel/bridge/opencensus v1.38.0 +## explicit; go 1.23.0 +go.opentelemetry.io/otel/bridge/opencensus +go.opentelemetry.io/otel/bridge/opencensus/internal +go.opentelemetry.io/otel/bridge/opencensus/internal/oc2otel +go.opentelemetry.io/otel/bridge/opencensus/internal/ocmetric +go.opentelemetry.io/otel/bridge/opencensus/internal/otel2oc # go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 ## explicit; go 1.23.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc