mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2024-11-24 08:22:25 +02:00
Remove the deprecated oteltest package (#2234)
Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
This commit is contained in:
parent
486afd347f
commit
9e7812d1fe
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@ -256,16 +256,6 @@ updates:
|
||||
schedule:
|
||||
day: sunday
|
||||
interval: weekly
|
||||
-
|
||||
package-ecosystem: gomod
|
||||
directory: /oteltest
|
||||
labels:
|
||||
- dependencies
|
||||
- go
|
||||
- "Skip Changelog"
|
||||
schedule:
|
||||
day: sunday
|
||||
interval: weekly
|
||||
-
|
||||
package-ecosystem: gomod
|
||||
directory: /internal/tools/semconv-gen
|
||||
|
@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed the deprecated package `go.opentelemetry.io/otel/oteltest`. (#2234)
|
||||
- Removed the deprecated package `go.opentelemetry.io/otel/bridge/opencensus/utils`. (#2233)
|
||||
|
||||
## [1.0.0-RC3] - 2021-09-02
|
||||
|
@ -43,8 +43,6 @@ replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -60,8 +60,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric
|
||||
|
@ -40,8 +40,6 @@ replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -59,8 +59,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
@ -40,8 +40,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -42,8 +42,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -44,8 +44,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -43,8 +43,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -45,8 +45,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -42,8 +42,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -41,8 +41,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -38,8 +38,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -25,8 +25,6 @@ replace go.opentelemetry.io/otel/exporters/otlp => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../../../trace
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric
|
||||
|
@ -27,8 +27,6 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../../../../trace
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus
|
||||
|
@ -23,8 +23,6 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../../../../trace
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus
|
||||
|
@ -21,8 +21,6 @@ replace go.opentelemetry.io/otel/sdk => ../../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../../../trace
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../../../bridge/opencensus
|
||||
|
@ -19,8 +19,6 @@ replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../../../../trace
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../../../../bridge/opencensus
|
||||
|
@ -50,8 +50,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../../../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../../../sdk/export/metric
|
||||
|
@ -54,8 +54,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
@ -46,8 +46,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric
|
||||
|
@ -44,8 +44,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../../sdk/metric
|
||||
|
@ -41,8 +41,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
2
go.mod
2
go.mod
@ -42,8 +42,6 @@ replace go.opentelemetry.io/otel/internal/metric => ./internal/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ./metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ./oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ./sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ./sdk/metric
|
||||
|
@ -48,8 +48,6 @@ replace go.opentelemetry.io/otel/exporters/zipkin => ../../exporters/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/internal/tools => ../tools
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
@ -44,8 +44,6 @@ replace go.opentelemetry.io/otel/sdk => ../../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../../sdk/metric
|
||||
|
@ -32,8 +32,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ./
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../sdk/export/metric
|
||||
|
@ -1,141 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// defaultSpanContextFunc returns the default SpanContextFunc.
|
||||
func defaultSpanContextFunc() func(context.Context) trace.SpanContext {
|
||||
var traceID, spanID uint64 = 1, 1
|
||||
return func(ctx context.Context) trace.SpanContext {
|
||||
var sc trace.SpanContext
|
||||
if current := trace.SpanContextFromContext(ctx); current.IsValid() {
|
||||
sc = current
|
||||
} else {
|
||||
var tid trace.TraceID
|
||||
binary.BigEndian.PutUint64(tid[:], atomic.AddUint64(&traceID, 1))
|
||||
sc = sc.WithTraceID(tid)
|
||||
}
|
||||
var sid trace.SpanID
|
||||
binary.BigEndian.PutUint64(sid[:], atomic.AddUint64(&spanID, 1))
|
||||
return sc.WithSpanID(sid)
|
||||
}
|
||||
}
|
||||
|
||||
type config struct {
|
||||
// SpanContextFunc returns a SpanContext from an parent Context for a
|
||||
// new span.
|
||||
SpanContextFunc func(context.Context) trace.SpanContext
|
||||
|
||||
// SpanRecorder keeps track of spans.
|
||||
SpanRecorder *SpanRecorder
|
||||
}
|
||||
|
||||
func newConfig(opts ...Option) config {
|
||||
conf := config{}
|
||||
for _, opt := range opts {
|
||||
opt.apply(&conf)
|
||||
}
|
||||
if conf.SpanContextFunc == nil {
|
||||
conf.SpanContextFunc = defaultSpanContextFunc()
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
// Option applies an option to a config.
|
||||
type Option interface {
|
||||
apply(*config)
|
||||
}
|
||||
|
||||
type spanContextFuncOption struct {
|
||||
SpanContextFunc func(context.Context) trace.SpanContext
|
||||
}
|
||||
|
||||
func (o spanContextFuncOption) apply(c *config) {
|
||||
c.SpanContextFunc = o.SpanContextFunc
|
||||
}
|
||||
|
||||
// WithSpanContextFunc sets the SpanContextFunc used to generate a new Spans
|
||||
// context from a parent SpanContext.
|
||||
func WithSpanContextFunc(f func(context.Context) trace.SpanContext) Option {
|
||||
return spanContextFuncOption{SpanContextFunc: f}
|
||||
}
|
||||
|
||||
type spanRecorderOption struct {
|
||||
SpanRecorder *SpanRecorder
|
||||
}
|
||||
|
||||
func (o spanRecorderOption) apply(c *config) {
|
||||
c.SpanRecorder = o.SpanRecorder
|
||||
}
|
||||
|
||||
// WithSpanRecorder sets the SpanRecorder to use with the TracerProvider for
|
||||
// testing.
|
||||
func WithSpanRecorder(sr *SpanRecorder) Option {
|
||||
return spanRecorderOption{SpanRecorder: sr}
|
||||
}
|
||||
|
||||
// SpanRecorder performs operations to record a span as it starts and ends.
|
||||
// It is designed to be concurrent safe and can by used by multiple goroutines.
|
||||
type SpanRecorder struct {
|
||||
startedMu sync.RWMutex
|
||||
started []*Span
|
||||
|
||||
doneMu sync.RWMutex
|
||||
done []*Span
|
||||
}
|
||||
|
||||
// OnStart records span as started.
|
||||
func (ssr *SpanRecorder) OnStart(span *Span) {
|
||||
ssr.startedMu.Lock()
|
||||
defer ssr.startedMu.Unlock()
|
||||
ssr.started = append(ssr.started, span)
|
||||
}
|
||||
|
||||
// OnEnd records span as completed.
|
||||
func (ssr *SpanRecorder) OnEnd(span *Span) {
|
||||
ssr.doneMu.Lock()
|
||||
defer ssr.doneMu.Unlock()
|
||||
ssr.done = append(ssr.done, span)
|
||||
}
|
||||
|
||||
// Started returns a copy of all started Spans in the order they were started.
|
||||
func (ssr *SpanRecorder) Started() []*Span {
|
||||
ssr.startedMu.RLock()
|
||||
defer ssr.startedMu.RUnlock()
|
||||
started := make([]*Span, len(ssr.started))
|
||||
for i := range ssr.started {
|
||||
started[i] = ssr.started[i]
|
||||
}
|
||||
return started
|
||||
}
|
||||
|
||||
// Completed returns a copy of all ended Spans in the order they were ended.
|
||||
func (ssr *SpanRecorder) Completed() []*Span {
|
||||
ssr.doneMu.RLock()
|
||||
defer ssr.doneMu.RUnlock()
|
||||
done := make([]*Span, len(ssr.done))
|
||||
for i := range ssr.done {
|
||||
done[i] = ssr.done[i]
|
||||
}
|
||||
return done
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest provides testing utilities for the otel package.
|
||||
|
||||
This package is currently in a Release Candidate phase. Backwards incompatible changes
|
||||
may be introduced prior to v1.0.0, but we believe the current API is ready to stabilize.
|
||||
|
||||
API Validation
|
||||
|
||||
The Harness can be used to validate an implementation of the OpenTelemetry API
|
||||
defined by the `otel` package.
|
||||
|
||||
func TestCustomSDKTracingImplementation(t *testing.T) {
|
||||
yourTraceProvider := NewTracerProvider()
|
||||
subjectFactory := func() otel.Tracer {
|
||||
return yourTraceProvider.Tracer("testing")
|
||||
}
|
||||
|
||||
oteltest.NewHarness(t).TestTracer(subjectFactory)
|
||||
}
|
||||
|
||||
Currently the Harness only provides testing of the trace portion of the
|
||||
OpenTelemetry API.
|
||||
|
||||
Trace Testing
|
||||
|
||||
To test tracing functionality a full testing implementation of the
|
||||
OpenTelemetry tracing API are provided. The provided TracerProvider, Tracer,
|
||||
and Span all implement their related interface and are designed to allow
|
||||
introspection of their state and history. Additionally, a SpanRecorder can be
|
||||
provided to the TracerProvider to record all Spans started and ended by the
|
||||
testing structures.
|
||||
|
||||
sr := new(oteltest.SpanRecorder)
|
||||
tp := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr))
|
||||
|
||||
Deprecated: This package contains an alternate implementation of the
|
||||
OpenTelemetry SDK. This means it will diverge from the one commonly used in
|
||||
real world operations and therefore will not provide adequate testing
|
||||
guarantees for users. Because of this, this package should not be used to test
|
||||
performance or behavior of code running OpenTelemetry. Instead, the
|
||||
SpanRecorder from the go.opentelemetry.io/otel/sdk/trace/tracetest package can
|
||||
be registered with the default SDK (go.opentelemetry.io/otel/sdk/trace) as a
|
||||
SpanProcessor and used to test. This will ensure code will work with the
|
||||
default SDK. If users do not want to include a dependency on the default SDK
|
||||
it is recommended to run integration tests in their own module to isolate the
|
||||
dependency (see go.opentelemetry.io/otel/bridge/opencensus/test as an
|
||||
example).
|
||||
*/
|
||||
package oteltest // import "go.opentelemetry.io/otel/oteltest"
|
@ -1,28 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
// Event encapsulates the properties of calls to AddEvent.
|
||||
type Event struct {
|
||||
Timestamp time.Time
|
||||
Name string
|
||||
Attributes map[attribute.Key]attribute.Value
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
module go.opentelemetry.io/otel/oteltest
|
||||
|
||||
go 1.15
|
||||
|
||||
replace go.opentelemetry.io/otel => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus => ../bridge/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opentracing => ../bridge/opentracing
|
||||
|
||||
replace go.opentelemetry.io/otel/example/jaeger => ../example/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/example/namedtracer => ../example/namedtracer
|
||||
|
||||
replace go.opentelemetry.io/otel/example/opencensus => ../example/opencensus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/otel-collector => ../example/otel-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prom-collector => ../example/prom-collector
|
||||
|
||||
replace go.opentelemetry.io/otel/example/prometheus => ../example/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/example/zipkin => ../example/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/prometheus => ../exporters/prometheus
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/jaeger => ../exporters/jaeger
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/zipkin => ../exporters/zipkin
|
||||
|
||||
replace go.opentelemetry.io/otel/internal/tools => ../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/internal/metric => ../internal/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ./
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../sdk/export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ../sdk/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/trace => ../trace
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.opentelemetry.io/otel v1.0.0-RC3
|
||||
go.opentelemetry.io/otel/trace v1.0.0-RC3
|
||||
)
|
||||
|
||||
replace go.opentelemetry.io/otel/example/passthrough => ../example/passthrough
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlptrace => ../exporters/otlp/otlptrace
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => ../exporters/otlp/otlptrace/otlptracegrpc
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp => ../exporters/otlp/otlptrace/otlptracehttp
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric => ../exporters/otlp/otlpmetric
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc => ../exporters/otlp/otlpmetric/otlpmetricgrpc
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/stdout/stdoutmetric => ../exporters/stdout/stdoutmetric
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/stdout/stdouttrace => ../exporters/stdout/stdouttrace
|
||||
|
||||
replace go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp => ../exporters/otlp/otlpmetric/otlpmetrichttp
|
||||
|
||||
replace go.opentelemetry.io/otel/bridge/opencensus/test => ../bridge/opencensus/test
|
||||
|
||||
replace go.opentelemetry.io/otel/example/fib => ../example/fib
|
@ -1,15 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,34 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/internaltest"
|
||||
)
|
||||
|
||||
// Harness is a testing harness used to test implementations of the
|
||||
// OpenTelemetry API.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
type Harness = internaltest.Harness
|
||||
|
||||
// NewHarness returns an instantiated *Harness using t.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
func NewHarness(t *testing.T) *Harness {
|
||||
return internaltest.NewHarness(t)
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// TracerProvider is a testing TracerProvider. It is an functioning
|
||||
// implementation of an OpenTelemetry TracerProvider and can be configured
|
||||
// with a SpanRecorder that it configure all Tracers it creates to record
|
||||
// their Spans with.
|
||||
type TracerProvider struct {
|
||||
config config
|
||||
|
||||
tracersMu sync.Mutex
|
||||
tracers map[instrumentation]*Tracer
|
||||
}
|
||||
|
||||
var _ trace.TracerProvider = (*TracerProvider)(nil)
|
||||
|
||||
// NewTracerProvider returns a *TracerProvider configured with options.
|
||||
func NewTracerProvider(options ...Option) *TracerProvider {
|
||||
return &TracerProvider{
|
||||
config: newConfig(options...),
|
||||
tracers: make(map[instrumentation]*Tracer),
|
||||
}
|
||||
}
|
||||
|
||||
type instrumentation struct {
|
||||
Name, Version string
|
||||
}
|
||||
|
||||
// Tracer returns an OpenTelemetry Tracer used for testing.
|
||||
func (p *TracerProvider) Tracer(instName string, opts ...trace.TracerOption) trace.Tracer {
|
||||
conf := trace.NewTracerConfig(opts...)
|
||||
|
||||
inst := instrumentation{
|
||||
Name: instName,
|
||||
Version: conf.InstrumentationVersion(),
|
||||
}
|
||||
p.tracersMu.Lock()
|
||||
defer p.tracersMu.Unlock()
|
||||
t, ok := p.tracers[inst]
|
||||
if !ok {
|
||||
t = &Tracer{
|
||||
Name: instName,
|
||||
Version: conf.InstrumentationVersion(),
|
||||
provider: p,
|
||||
}
|
||||
p.tracers[inst] = t
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// DefaultTracer returns a default tracer for testing purposes.
|
||||
func DefaultTracer() trace.Tracer {
|
||||
return NewTracerProvider().Tracer("")
|
||||
}
|
229
oteltest/span.go
229
oteltest/span.go
@ -1,229 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var _ trace.Span = (*Span)(nil)
|
||||
|
||||
// Span is an OpenTelemetry Span used for testing.
|
||||
type Span struct {
|
||||
lock sync.RWMutex
|
||||
tracer *Tracer
|
||||
spanContext trace.SpanContext
|
||||
parentSpanID trace.SpanID
|
||||
ended bool
|
||||
name string
|
||||
startTime time.Time
|
||||
endTime time.Time
|
||||
statusCode codes.Code
|
||||
statusMessage string
|
||||
attributes map[attribute.Key]attribute.Value
|
||||
events []Event
|
||||
links []trace.Link
|
||||
spanKind trace.SpanKind
|
||||
}
|
||||
|
||||
// End ends s. If the Tracer that created s was configured with a
|
||||
// SpanRecorder, that recorder's OnEnd method is called as the final part of
|
||||
// this method.
|
||||
func (s *Span) End(opts ...trace.SpanEndOption) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
c := trace.NewSpanEndConfig(opts...)
|
||||
s.endTime = time.Now()
|
||||
if endTime := c.Timestamp(); !endTime.IsZero() {
|
||||
s.endTime = endTime
|
||||
}
|
||||
|
||||
s.ended = true
|
||||
if s.tracer.provider.config.SpanRecorder != nil {
|
||||
s.tracer.provider.config.SpanRecorder.OnEnd(s)
|
||||
}
|
||||
}
|
||||
|
||||
// RecordError records an error as an exception Span event.
|
||||
func (s *Span) RecordError(err error, opts ...trace.EventOption) {
|
||||
if err == nil || s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
errType := reflect.TypeOf(err)
|
||||
errTypeString := fmt.Sprintf("%s.%s", errType.PkgPath(), errType.Name())
|
||||
if errTypeString == "." {
|
||||
errTypeString = errType.String()
|
||||
}
|
||||
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
semconv.ExceptionTypeKey.String(errTypeString),
|
||||
semconv.ExceptionMessageKey.String(err.Error()),
|
||||
))
|
||||
|
||||
s.AddEvent(semconv.ExceptionEventName, opts...)
|
||||
}
|
||||
|
||||
// AddEvent adds an event to s.
|
||||
func (s *Span) AddEvent(name string, o ...trace.EventOption) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
c := trace.NewEventConfig(o...)
|
||||
|
||||
var attributes map[attribute.Key]attribute.Value
|
||||
if l := len(c.Attributes()); l > 0 {
|
||||
attributes = make(map[attribute.Key]attribute.Value, l)
|
||||
for _, attr := range c.Attributes() {
|
||||
attributes[attr.Key] = attr.Value
|
||||
}
|
||||
}
|
||||
|
||||
s.events = append(s.events, Event{
|
||||
Timestamp: c.Timestamp(),
|
||||
Name: name,
|
||||
Attributes: attributes,
|
||||
})
|
||||
}
|
||||
|
||||
// IsRecording returns the recording state of s.
|
||||
func (s *Span) IsRecording() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// SpanContext returns the SpanContext of s.
|
||||
func (s *Span) SpanContext() trace.SpanContext {
|
||||
return s.spanContext
|
||||
}
|
||||
|
||||
// SetStatus sets the status of s in the form of a code and a message.
|
||||
func (s *Span) SetStatus(code codes.Code, msg string) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
s.statusCode = code
|
||||
s.statusMessage = msg
|
||||
}
|
||||
|
||||
// SetName sets the name of s.
|
||||
func (s *Span) SetName(name string) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
s.name = name
|
||||
}
|
||||
|
||||
// SetAttributes sets attrs as attributes of s.
|
||||
func (s *Span) SetAttributes(attrs ...attribute.KeyValue) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
if s.ended {
|
||||
return
|
||||
}
|
||||
|
||||
for _, attr := range attrs {
|
||||
s.attributes[attr.Key] = attr.Value
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name most recently set on s, either at or after creation
|
||||
// time. It cannot be change after End has been called on s.
|
||||
func (s *Span) Name() string { return s.name }
|
||||
|
||||
// ParentSpanID returns the SpanID of the parent Span. If s is a root Span,
|
||||
// and therefore does not have a parent, the returned SpanID will be invalid
|
||||
// (i.e., it will contain all zeroes).
|
||||
func (s *Span) ParentSpanID() trace.SpanID { return s.parentSpanID }
|
||||
|
||||
// Attributes returns the attributes set on s, either at or after creation
|
||||
// time. If the same attribute key was set multiple times, the last call will
|
||||
// be used. Attributes cannot be changed after End has been called on s.
|
||||
func (s *Span) Attributes() map[attribute.Key]attribute.Value {
|
||||
s.lock.RLock()
|
||||
defer s.lock.RUnlock()
|
||||
|
||||
attributes := make(map[attribute.Key]attribute.Value)
|
||||
|
||||
for k, v := range s.attributes {
|
||||
attributes[k] = v
|
||||
}
|
||||
|
||||
return attributes
|
||||
}
|
||||
|
||||
// Events returns the events set on s. Events cannot be changed after End has
|
||||
// been called on s.
|
||||
func (s *Span) Events() []Event { return s.events }
|
||||
|
||||
// Links returns the links set on s at creation time. If multiple links for
|
||||
// the same SpanContext were set, the last link will be used.
|
||||
func (s *Span) Links() []trace.Link { return s.links }
|
||||
|
||||
// StartTime returns the time at which s was started. This will be the
|
||||
// wall-clock time unless a specific start time was provided.
|
||||
func (s *Span) StartTime() time.Time { return s.startTime }
|
||||
|
||||
// EndTime returns the time at which s was ended if at has been ended, or
|
||||
// false otherwise. If the span has been ended, the returned time will be the
|
||||
// wall-clock time unless a specific end time was provided.
|
||||
func (s *Span) EndTime() (time.Time, bool) { return s.endTime, s.ended }
|
||||
|
||||
// Ended returns whether s has been ended, i.e. whether End has been called at
|
||||
// least once on s.
|
||||
func (s *Span) Ended() bool { return s.ended }
|
||||
|
||||
// StatusCode returns the code of the status most recently set on s, or
|
||||
// codes.OK if no status has been explicitly set. It cannot be changed after
|
||||
// End has been called on s.
|
||||
func (s *Span) StatusCode() codes.Code { return s.statusCode }
|
||||
|
||||
// StatusMessage returns the status message most recently set on s or the
|
||||
// empty string if no status message was set.
|
||||
func (s *Span) StatusMessage() string { return s.statusMessage }
|
||||
|
||||
// SpanKind returns the span kind of s.
|
||||
func (s *Span) SpanKind() trace.SpanKind { return s.spanKind }
|
||||
|
||||
// TracerProvider returns a trace.TracerProvider that can be used to generate
|
||||
// additional Spans on the same telemetry pipeline as the current Span.
|
||||
func (s *Span) TracerProvider() trace.TracerProvider {
|
||||
return s.tracer.provider
|
||||
}
|
@ -1,594 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
ottest "go.opentelemetry.io/otel/internal/internaltest"
|
||||
"go.opentelemetry.io/otel/internal/matchers"
|
||||
|
||||
//nolint:staticcheck
|
||||
"go.opentelemetry.io/otel/oteltest"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
func TestSpan(t *testing.T) {
|
||||
t.Run("#End", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("ends the span", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(subject.Ended()).ToBeFalse()
|
||||
|
||||
_, ok = subject.EndTime()
|
||||
e.Expect(ok).ToBeFalse()
|
||||
|
||||
start := time.Now()
|
||||
|
||||
subject.End()
|
||||
|
||||
end := time.Now()
|
||||
|
||||
e.Expect(subject.Ended()).ToBeTrue()
|
||||
|
||||
endTime, ok := subject.EndTime()
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(endTime).ToBeTemporally(matchers.AfterOrSameTime, start)
|
||||
e.Expect(endTime).ToBeTemporally(matchers.BeforeOrSameTime, end)
|
||||
})
|
||||
|
||||
t.Run("only takes effect the first time it is called", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.End()
|
||||
|
||||
expectedEndTime, ok := subject.EndTime()
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.End()
|
||||
|
||||
endTime, ok := subject.EndTime()
|
||||
e.Expect(ok).ToBeTrue()
|
||||
e.Expect(endTime).ToEqual(expectedEndTime)
|
||||
})
|
||||
|
||||
t.Run("uses the time from WithTimestamp", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
expectedEndTime := time.Now().AddDate(5, 0, 0)
|
||||
subject.End(trace.WithTimestamp(expectedEndTime))
|
||||
|
||||
e.Expect(subject.Ended()).ToBeTrue()
|
||||
|
||||
endTime, ok := subject.EndTime()
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(endTime).ToEqual(expectedEndTime)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#RecordError", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("records an error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
scenarios := []struct {
|
||||
err error
|
||||
typ string
|
||||
msg string
|
||||
}{
|
||||
{
|
||||
err: ottest.NewTestError("test error"),
|
||||
typ: "go.opentelemetry.io/otel/internal/internaltest.TestError",
|
||||
msg: "test error",
|
||||
},
|
||||
{
|
||||
err: errors.New("test error 2"),
|
||||
typ: "*errors.errorString",
|
||||
msg: "test error 2",
|
||||
},
|
||||
}
|
||||
|
||||
for _, s := range scenarios {
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
testTime := time.Now()
|
||||
subject.RecordError(s.err, trace.WithTimestamp(testTime))
|
||||
|
||||
expectedEvents := []oteltest.Event{{
|
||||
Timestamp: testTime,
|
||||
Name: semconv.ExceptionEventName,
|
||||
Attributes: map[attribute.Key]attribute.Value{
|
||||
semconv.ExceptionTypeKey: attribute.StringValue(s.typ),
|
||||
semconv.ExceptionMessageKey: attribute.StringValue(s.msg),
|
||||
},
|
||||
}}
|
||||
e.Expect(subject.Events()).ToEqual(expectedEvents)
|
||||
e.Expect(subject.StatusCode()).ToEqual(codes.Unset)
|
||||
e.Expect(subject.StatusMessage()).ToEqual("")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cannot be set after the span has ended", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.End()
|
||||
subject.RecordError(errors.New("ignored error"))
|
||||
|
||||
e.Expect(len(subject.Events())).ToEqual(0)
|
||||
})
|
||||
|
||||
t.Run("has no effect with nil error", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.RecordError(nil)
|
||||
|
||||
e.Expect(len(subject.Events())).ToEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#IsRecording", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns true", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, subject := tracer.Start(context.Background(), "test")
|
||||
|
||||
e.Expect(subject.IsRecording()).ToBeTrue()
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#SpanContext", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns a valid SpanContext", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, subject := tracer.Start(context.Background(), "test")
|
||||
|
||||
e.Expect(subject.SpanContext().IsValid()).ToBeTrue()
|
||||
})
|
||||
|
||||
t.Run("returns a consistent value", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, subject := tracer.Start(context.Background(), "test")
|
||||
|
||||
e.Expect(subject.SpanContext()).ToEqual(subject.SpanContext())
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#Name", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns the most recently set name on the span", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
originalName := "test"
|
||||
_, span := tracer.Start(context.Background(), originalName)
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(subject.Name()).ToEqual(originalName)
|
||||
|
||||
subject.SetName("in-between")
|
||||
|
||||
newName := "new name"
|
||||
|
||||
subject.SetName(newName)
|
||||
|
||||
e.Expect(subject.Name()).ToEqual(newName)
|
||||
})
|
||||
|
||||
t.Run("cannot be changed after the span has been ended", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
originalName := "test"
|
||||
_, span := tracer.Start(context.Background(), originalName)
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.End()
|
||||
subject.SetName("new name")
|
||||
|
||||
e.Expect(subject.Name()).ToEqual(originalName)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#Attributes", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns an empty map by default", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(subject.Attributes()).ToEqual(map[attribute.Key]attribute.Value{})
|
||||
})
|
||||
|
||||
t.Run("returns the most recently set attributes", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
attr1 := attribute.String("key1", "value1")
|
||||
attr2 := attribute.String("key2", "value2")
|
||||
attr3 := attribute.String("key3", "value3")
|
||||
unexpectedAttr := attr2.Key.String("unexpected")
|
||||
|
||||
subject.SetAttributes(attr1, unexpectedAttr, attr3)
|
||||
subject.SetAttributes(attr2)
|
||||
|
||||
attributes := subject.Attributes()
|
||||
|
||||
e.Expect(attributes[attr1.Key]).ToEqual(attr1.Value)
|
||||
e.Expect(attributes[attr2.Key]).ToEqual(attr2.Value)
|
||||
e.Expect(attributes[attr3.Key]).ToEqual(attr3.Value)
|
||||
})
|
||||
|
||||
t.Run("cannot be changed after the span has been ended", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
expectedAttr := attribute.String("key", "value")
|
||||
subject.SetAttributes(expectedAttr)
|
||||
subject.End()
|
||||
|
||||
unexpectedAttr := expectedAttr.Key.String("unexpected")
|
||||
subject.SetAttributes(unexpectedAttr)
|
||||
subject.End()
|
||||
|
||||
attributes := subject.Attributes()
|
||||
e.Expect(attributes[expectedAttr.Key]).ToEqual(expectedAttr.Value)
|
||||
})
|
||||
|
||||
t.Run("can be used concurrently with setter", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(2)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
subject.SetAttributes(attribute.String("key", "value"))
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
subject.Attributes()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#Links", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns an empty map by default", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(len(subject.Links())).ToEqual(0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#Events", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns an empty slice by default", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(len(subject.Events())).ToEqual(0)
|
||||
})
|
||||
|
||||
t.Run("returns all of the added events", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
event1Name := "event1"
|
||||
event1Attributes := []attribute.KeyValue{
|
||||
attribute.String("event1Attr1", "foo"),
|
||||
attribute.String("event1Attr2", "bar"),
|
||||
}
|
||||
|
||||
event1Start := time.Now()
|
||||
subject.AddEvent(event1Name, trace.WithAttributes(event1Attributes...))
|
||||
event1End := time.Now()
|
||||
|
||||
event2Timestamp := time.Now().AddDate(5, 0, 0)
|
||||
event2Name := "event1"
|
||||
event2Attributes := []attribute.KeyValue{
|
||||
attribute.String("event2Attr", "abc"),
|
||||
}
|
||||
|
||||
subject.AddEvent(event2Name, trace.WithTimestamp(event2Timestamp), trace.WithAttributes(event2Attributes...))
|
||||
|
||||
events := subject.Events()
|
||||
|
||||
e.Expect(len(events)).ToEqual(2)
|
||||
|
||||
event1 := events[0]
|
||||
|
||||
e.Expect(event1.Timestamp).ToBeTemporally(matchers.AfterOrSameTime, event1Start)
|
||||
e.Expect(event1.Timestamp).ToBeTemporally(matchers.BeforeOrSameTime, event1End)
|
||||
e.Expect(event1.Name).ToEqual(event1Name)
|
||||
|
||||
for _, attr := range event1Attributes {
|
||||
e.Expect(event1.Attributes[attr.Key]).ToEqual(attr.Value)
|
||||
}
|
||||
|
||||
event2 := events[1]
|
||||
|
||||
e.Expect(event2.Timestamp).ToEqual(event2Timestamp)
|
||||
e.Expect(event2.Name).ToEqual(event2Name)
|
||||
|
||||
for _, attr := range event2Attributes {
|
||||
e.Expect(event2.Attributes[attr.Key]).ToEqual(attr.Value)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("cannot be changed after the span has been ended", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.AddEvent("test")
|
||||
|
||||
e.Expect(len(subject.Events())).ToEqual(1)
|
||||
|
||||
expectedEvent := subject.Events()[0]
|
||||
|
||||
subject.End()
|
||||
subject.AddEvent("should not occur")
|
||||
|
||||
e.Expect(len(subject.Events())).ToEqual(1)
|
||||
e.Expect(subject.Events()[0]).ToEqual(expectedEvent)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("#Status", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("defaults to OK", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(subject.StatusCode()).ToEqual(codes.Unset)
|
||||
|
||||
subject.End()
|
||||
|
||||
e.Expect(subject.StatusCode()).ToEqual(codes.Unset)
|
||||
})
|
||||
|
||||
statuses := []codes.Code{
|
||||
codes.Unset,
|
||||
codes.Error,
|
||||
codes.Ok,
|
||||
}
|
||||
|
||||
for _, status := range statuses {
|
||||
t.Run("returns the most recently set status on the span", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
subject.SetStatus(codes.Ok, "Ok")
|
||||
subject.SetStatus(status, "Yo!")
|
||||
|
||||
e.Expect(subject.StatusCode()).ToEqual(status)
|
||||
e.Expect(subject.StatusMessage()).ToEqual("Yo!")
|
||||
})
|
||||
|
||||
t.Run("cannot be changed after the span has been ended", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test")
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
originalStatus := codes.Ok
|
||||
|
||||
subject.SetStatus(originalStatus, "OK")
|
||||
subject.End()
|
||||
subject.SetStatus(status, fmt.Sprint(status))
|
||||
|
||||
e.Expect(subject.StatusCode()).ToEqual(originalStatus)
|
||||
e.Expect(subject.StatusMessage()).ToEqual("OK")
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("#SpanKind", func(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("returns the value given at start", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
tracer := tp.Tracer(t.Name())
|
||||
_, span := tracer.Start(context.Background(), "test",
|
||||
trace.WithSpanKind(trace.SpanKindConsumer))
|
||||
|
||||
subject, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
subject.End()
|
||||
|
||||
e.Expect(subject.SpanKind()).ToEqual(trace.SpanKindConsumer)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("can provide a valid TracerProvider", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
sr := new(oteltest.SpanRecorder)
|
||||
tracerA := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr)).Tracer(t.Name())
|
||||
ctx, spanA := tracerA.Start(context.Background(), "span1")
|
||||
|
||||
e.Expect(len(sr.Started())).ToEqual(1)
|
||||
|
||||
_, spanB := spanA.TracerProvider().Tracer("extracted").Start(ctx, "span2")
|
||||
|
||||
spans := sr.Started()
|
||||
|
||||
e.Expect(len(spans)).ToEqual(2)
|
||||
e.Expect(spans[0]).ToEqual(spanA)
|
||||
e.Expect(spans[1]).ToEqual(spanB)
|
||||
})
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
)
|
||||
|
||||
type ctxKeyType string
|
||||
|
||||
// TextMapCarrier provides a testing storage medium to for a
|
||||
// TextMapPropagator. It records all the operations it performs.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
type TextMapCarrier struct {
|
||||
mtx sync.Mutex
|
||||
|
||||
gets []string
|
||||
sets [][2]string
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
// NewTextMapCarrier returns a new *TextMapCarrier populated with data.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
func NewTextMapCarrier(data map[string]string) *TextMapCarrier {
|
||||
copied := make(map[string]string, len(data))
|
||||
for k, v := range data {
|
||||
copied[k] = v
|
||||
}
|
||||
return &TextMapCarrier{data: copied}
|
||||
}
|
||||
|
||||
// Keys returns the keys for which this carrier has a value.
|
||||
func (c *TextMapCarrier) Keys() []string {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
|
||||
result := make([]string, 0, len(c.data))
|
||||
for k := range c.data {
|
||||
result = append(result, k)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Get returns the value associated with the passed key.
|
||||
func (c *TextMapCarrier) Get(key string) string {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
c.gets = append(c.gets, key)
|
||||
return c.data[key]
|
||||
}
|
||||
|
||||
// GotKey tests if c.Get has been called for key.
|
||||
func (c *TextMapCarrier) GotKey(t *testing.T, key string) bool {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
for _, k := range c.gets {
|
||||
if k == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
t.Errorf("TextMapCarrier.Get(%q) has not been called", key)
|
||||
return false
|
||||
}
|
||||
|
||||
// GotN tests if n calls to c.Get have been made.
|
||||
func (c *TextMapCarrier) GotN(t *testing.T, n int) bool {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
if len(c.gets) != n {
|
||||
t.Errorf("TextMapCarrier.Get was called %d times, not %d", len(c.gets), n)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Set stores the key-value pair.
|
||||
func (c *TextMapCarrier) Set(key, value string) {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
c.sets = append(c.sets, [2]string{key, value})
|
||||
c.data[key] = value
|
||||
}
|
||||
|
||||
// SetKeyValue tests if c.Set has been called for the key-value pair.
|
||||
func (c *TextMapCarrier) SetKeyValue(t *testing.T, key, value string) bool {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
var vals []string
|
||||
for _, pair := range c.sets {
|
||||
if key == pair[0] {
|
||||
if value == pair[1] {
|
||||
return true
|
||||
}
|
||||
vals = append(vals, pair[1])
|
||||
}
|
||||
}
|
||||
if len(vals) > 0 {
|
||||
t.Errorf("TextMapCarrier.Set called with %q and %v values, but not %s", key, vals, value)
|
||||
}
|
||||
t.Errorf("TextMapCarrier.Set(%q,%q) has not been called", key, value)
|
||||
return false
|
||||
}
|
||||
|
||||
// SetN tests if n calls to c.Set have been made.
|
||||
func (c *TextMapCarrier) SetN(t *testing.T, n int) bool {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
if len(c.sets) != n {
|
||||
t.Errorf("TextMapCarrier.Set was called %d times, not %d", len(c.sets), n)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Reset zeros out the internal state recording of c.
|
||||
func (c *TextMapCarrier) Reset() {
|
||||
c.mtx.Lock()
|
||||
defer c.mtx.Unlock()
|
||||
|
||||
c.gets = nil
|
||||
c.sets = nil
|
||||
c.data = make(map[string]string)
|
||||
}
|
||||
|
||||
type state struct {
|
||||
Injections uint64
|
||||
Extractions uint64
|
||||
}
|
||||
|
||||
func newState(encoded string) state {
|
||||
if encoded == "" {
|
||||
return state{}
|
||||
}
|
||||
split := strings.SplitN(encoded, ",", 2)
|
||||
injects, _ := strconv.ParseUint(split[0], 10, 64)
|
||||
extracts, _ := strconv.ParseUint(split[1], 10, 64)
|
||||
return state{
|
||||
Injections: injects,
|
||||
Extractions: extracts,
|
||||
}
|
||||
}
|
||||
|
||||
func (s state) String() string {
|
||||
return fmt.Sprintf("%d,%d", s.Injections, s.Extractions)
|
||||
}
|
||||
|
||||
// TextMapPropagator is a propagation.TextMapPropagator used for testing.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
type TextMapPropagator struct {
|
||||
Name string
|
||||
ctxKey ctxKeyType
|
||||
}
|
||||
|
||||
// NewTextMapPropagator returns a new TextMapPropagator for testing.
|
||||
//
|
||||
// Deprecated: this will be removed in the next major release.
|
||||
func NewTextMapPropagator(name string) *TextMapPropagator {
|
||||
return &TextMapPropagator{Name: name, ctxKey: ctxKeyType(name)}
|
||||
}
|
||||
|
||||
func (p *TextMapPropagator) stateFromContext(ctx context.Context) state {
|
||||
if v := ctx.Value(p.ctxKey); v != nil {
|
||||
if s, ok := v.(state); ok {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return state{}
|
||||
}
|
||||
|
||||
func (p *TextMapPropagator) stateFromCarrier(carrier propagation.TextMapCarrier) state {
|
||||
return newState(carrier.Get(p.Name))
|
||||
}
|
||||
|
||||
// Inject set cross-cutting concerns for p from the Context into the carrier.
|
||||
func (p *TextMapPropagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {
|
||||
s := p.stateFromContext(ctx)
|
||||
s.Injections++
|
||||
carrier.Set(p.Name, s.String())
|
||||
}
|
||||
|
||||
// InjectedN tests if p has made n injections to carrier.
|
||||
func (p *TextMapPropagator) InjectedN(t *testing.T, carrier *TextMapCarrier, n int) bool {
|
||||
if actual := p.stateFromCarrier(carrier).Injections; actual != uint64(n) {
|
||||
t.Errorf("TextMapPropagator{%q} injected %d times, not %d", p.Name, actual, n)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Extract reads cross-cutting concerns for p from the carrier into a Context.
|
||||
func (p *TextMapPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context {
|
||||
s := p.stateFromCarrier(carrier)
|
||||
s.Extractions++
|
||||
return context.WithValue(ctx, p.ctxKey, s)
|
||||
}
|
||||
|
||||
// ExtractedN tests if p has made n extractions from the lineage of ctx.
|
||||
// nolint (context is not first arg)
|
||||
func (p *TextMapPropagator) ExtractedN(t *testing.T, ctx context.Context, n int) bool {
|
||||
if actual := p.stateFromContext(ctx).Extractions; actual != uint64(n) {
|
||||
t.Errorf("TextMapPropagator{%q} extracted %d time, not %d", p.Name, actual, n)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Fields returns p.Name as the key who's value is set with Inject.
|
||||
func (p *TextMapPropagator) Fields() []string { return []string{p.Name} }
|
@ -1,133 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
key, value = "test", "true"
|
||||
)
|
||||
|
||||
func TestTextMapCarrierKeys(t *testing.T) {
|
||||
tmc := NewTextMapCarrier(map[string]string{key: value})
|
||||
expected, actual := []string{key}, tmc.Keys()
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("expected tmc.Keys() to be %v but it was %v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextMapCarrierGet(t *testing.T) {
|
||||
tmc := NewTextMapCarrier(map[string]string{key: value})
|
||||
tmc.GotN(t, 0)
|
||||
if got := tmc.Get("empty"); got != "" {
|
||||
t.Errorf("TextMapCarrier.Get returned %q for an empty key", got)
|
||||
}
|
||||
tmc.GotKey(t, "empty")
|
||||
tmc.GotN(t, 1)
|
||||
if got := tmc.Get(key); got != value {
|
||||
t.Errorf("TextMapCarrier.Get(%q) returned %q, want %q", key, got, value)
|
||||
}
|
||||
tmc.GotKey(t, key)
|
||||
tmc.GotN(t, 2)
|
||||
}
|
||||
|
||||
func TestTextMapCarrierSet(t *testing.T) {
|
||||
tmc := NewTextMapCarrier(nil)
|
||||
tmc.SetN(t, 0)
|
||||
tmc.Set(key, value)
|
||||
if got, ok := tmc.data[key]; !ok {
|
||||
t.Errorf("TextMapCarrier.Set(%q,%q) failed to store pair", key, value)
|
||||
} else if got != value {
|
||||
t.Errorf("TextMapCarrier.Set(%q,%q) stored (%q,%q), not (%q,%q)", key, value, key, got, key, value)
|
||||
}
|
||||
tmc.SetKeyValue(t, key, value)
|
||||
tmc.SetN(t, 1)
|
||||
}
|
||||
|
||||
func TestTextMapCarrierReset(t *testing.T) {
|
||||
tmc := NewTextMapCarrier(map[string]string{key: value})
|
||||
tmc.GotN(t, 0)
|
||||
tmc.SetN(t, 0)
|
||||
tmc.Reset()
|
||||
tmc.GotN(t, 0)
|
||||
tmc.SetN(t, 0)
|
||||
if got := tmc.Get(key); got != "" {
|
||||
t.Error("TextMapCarrier.Reset() failed to clear initial data")
|
||||
}
|
||||
tmc.GotN(t, 1)
|
||||
tmc.GotKey(t, key)
|
||||
tmc.Set(key, value)
|
||||
tmc.SetKeyValue(t, key, value)
|
||||
tmc.SetN(t, 1)
|
||||
tmc.Reset()
|
||||
tmc.GotN(t, 0)
|
||||
tmc.SetN(t, 0)
|
||||
if got := tmc.Get(key); got != "" {
|
||||
t.Error("TextMapCarrier.Reset() failed to clear data")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextMapPropagatorInjectExtract(t *testing.T) {
|
||||
name := "testing"
|
||||
ctx := context.Background()
|
||||
carrier := NewTextMapCarrier(map[string]string{name: value})
|
||||
propagator := NewTextMapPropagator(name)
|
||||
|
||||
propagator.Inject(ctx, carrier)
|
||||
// Carrier value overridden with state.
|
||||
if carrier.SetKeyValue(t, name, "1,0") {
|
||||
// Ensure nothing has been extracted yet.
|
||||
propagator.ExtractedN(t, ctx, 0)
|
||||
// Test the injection was counted.
|
||||
propagator.InjectedN(t, carrier, 1)
|
||||
}
|
||||
|
||||
ctx = propagator.Extract(ctx, carrier)
|
||||
v := ctx.Value(ctxKeyType(name))
|
||||
if v == nil {
|
||||
t.Error("TextMapPropagator.Extract failed to extract state")
|
||||
}
|
||||
if s, ok := v.(state); !ok {
|
||||
t.Error("TextMapPropagator.Extract did not extract proper state")
|
||||
} else if s.Extractions != 1 {
|
||||
t.Error("TextMapPropagator.Extract did not increment state.Extractions")
|
||||
}
|
||||
if carrier.GotKey(t, name) {
|
||||
// Test the extraction was counted.
|
||||
propagator.ExtractedN(t, ctx, 1)
|
||||
// Ensure no additional injection was recorded.
|
||||
propagator.InjectedN(t, carrier, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextMapPropagatorFields(t *testing.T) {
|
||||
name := "testing"
|
||||
propagator := NewTextMapPropagator(name)
|
||||
if got := propagator.Fields(); len(got) != 1 {
|
||||
t.Errorf("TextMapPropagator.Fields returned %d fields, want 1", len(got))
|
||||
} else if got[0] != name {
|
||||
t.Errorf("TextMapPropagator.Fields returned %q, want %q", got[0], name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewStateEmpty(t *testing.T) {
|
||||
if want, got := (state{}), newState(""); got != want {
|
||||
t.Errorf("newState(\"\") returned %v, want %v", got, want)
|
||||
}
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest // import "go.opentelemetry.io/otel/oteltest"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var _ trace.Tracer = (*Tracer)(nil)
|
||||
|
||||
// Tracer is an OpenTelemetry Tracer implementation used for testing.
|
||||
type Tracer struct {
|
||||
// Name is the instrumentation name.
|
||||
Name string
|
||||
// Version is the instrumentation version.
|
||||
Version string
|
||||
|
||||
provider *TracerProvider
|
||||
}
|
||||
|
||||
// Start creates a span. If t is configured with a SpanRecorder its OnStart
|
||||
// method will be called after the created Span has been initialized.
|
||||
func (t *Tracer) Start(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
c := trace.NewSpanStartConfig(opts...)
|
||||
startTime := time.Now()
|
||||
if st := c.Timestamp(); !st.IsZero() {
|
||||
startTime = st
|
||||
}
|
||||
|
||||
span := &Span{
|
||||
tracer: t,
|
||||
startTime: startTime,
|
||||
attributes: make(map[attribute.Key]attribute.Value),
|
||||
links: []trace.Link{},
|
||||
spanKind: c.SpanKind(),
|
||||
}
|
||||
|
||||
if c.NewRoot() {
|
||||
span.spanContext = t.provider.config.SpanContextFunc(context.Background())
|
||||
} else {
|
||||
span.spanContext = t.provider.config.SpanContextFunc(ctx)
|
||||
if current := trace.SpanContextFromContext(ctx); current.IsValid() {
|
||||
span.spanContext = span.spanContext.WithTraceID(current.TraceID())
|
||||
span.parentSpanID = current.SpanID()
|
||||
}
|
||||
}
|
||||
|
||||
for _, link := range c.Links() {
|
||||
for i, sl := range span.links {
|
||||
if sl.SpanContext.SpanID() == link.SpanContext.SpanID() &&
|
||||
sl.SpanContext.TraceID() == link.SpanContext.TraceID() &&
|
||||
sl.SpanContext.TraceFlags() == link.SpanContext.TraceFlags() &&
|
||||
sl.SpanContext.TraceState().String() == link.SpanContext.TraceState().String() {
|
||||
span.links[i].Attributes = link.Attributes
|
||||
break
|
||||
}
|
||||
}
|
||||
span.links = append(span.links, link)
|
||||
}
|
||||
|
||||
span.SetName(name)
|
||||
span.SetAttributes(c.Attributes()...)
|
||||
|
||||
if t.provider.config.SpanRecorder != nil {
|
||||
t.provider.config.SpanRecorder.OnStart(span)
|
||||
}
|
||||
return trace.ContextWithSpan(ctx, span), span
|
||||
}
|
@ -1,295 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/internal/internaltest"
|
||||
"go.opentelemetry.io/otel/internal/matchers"
|
||||
|
||||
//nolint:staticcheck
|
||||
"go.opentelemetry.io/otel/oteltest"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
func TestTracer(t *testing.T) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
|
||||
internaltest.NewHarness(t).TestTracer(func() func() trace.Tracer {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
var i uint64
|
||||
return func() trace.Tracer {
|
||||
return tp.Tracer(fmt.Sprintf("tracer %d", atomic.AddUint64(&i, 1)))
|
||||
}
|
||||
}())
|
||||
|
||||
t.Run("#Start", func(t *testing.T) {
|
||||
testTracedSpan(t, func(tracer trace.Tracer, name string) (trace.Span, error) {
|
||||
_, span := tracer.Start(context.Background(), name)
|
||||
|
||||
return span, nil
|
||||
})
|
||||
|
||||
t.Run("uses the start time from WithTimestamp", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
expectedStartTime := time.Now().AddDate(5, 0, 0)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
_, span := subject.Start(context.Background(), "test", trace.WithTimestamp(expectedStartTime))
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(testSpan.StartTime()).ToEqual(expectedStartTime)
|
||||
})
|
||||
|
||||
t.Run("uses the attributes from WithAttributes", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
attr1 := attribute.String("a", "1")
|
||||
attr2 := attribute.String("b", "2")
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
_, span := subject.Start(context.Background(), "test", trace.WithAttributes(attr1, attr2))
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
attributes := testSpan.Attributes()
|
||||
e.Expect(attributes[attr1.Key]).ToEqual(attr1.Value)
|
||||
e.Expect(attributes[attr2.Key]).ToEqual(attr2.Value)
|
||||
})
|
||||
|
||||
t.Run("uses the current span from context as parent", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
parent, parentSpan := subject.Start(context.Background(), "parent")
|
||||
parentSpanContext := parentSpan.SpanContext()
|
||||
|
||||
_, span := subject.Start(parent, "child")
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
childSpanContext := testSpan.SpanContext()
|
||||
e.Expect(childSpanContext.TraceID()).ToEqual(parentSpanContext.TraceID())
|
||||
e.Expect(childSpanContext.SpanID()).NotToEqual(parentSpanContext.SpanID())
|
||||
e.Expect(testSpan.ParentSpanID()).ToEqual(parentSpanContext.SpanID())
|
||||
})
|
||||
|
||||
t.Run("uses the current span from context as parent, even if it is remote", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
ctx, _ := subject.Start(context.Background(), "local grandparent")
|
||||
_, s := subject.Start(ctx, "remote parent")
|
||||
ctx = trace.ContextWithRemoteSpanContext(ctx, s.SpanContext())
|
||||
parentSpanContext := trace.SpanContextFromContext(ctx)
|
||||
|
||||
_, span := subject.Start(ctx, "child")
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
childSpanContext := testSpan.SpanContext()
|
||||
e.Expect(childSpanContext.TraceID()).ToEqual(parentSpanContext.TraceID())
|
||||
e.Expect(childSpanContext.SpanID()).NotToEqual(parentSpanContext.SpanID())
|
||||
e.Expect(testSpan.ParentSpanID()).ToEqual(parentSpanContext.SpanID())
|
||||
})
|
||||
|
||||
t.Run("creates new root when context does not have a current span", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
_, napSpan := subject.Start(context.Background(), "not-a-parent")
|
||||
napSpanContext := napSpan.SpanContext()
|
||||
|
||||
_, span := subject.Start(context.Background(), "child")
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
childSpanContext := testSpan.SpanContext()
|
||||
e.Expect(childSpanContext.TraceID()).NotToEqual(napSpanContext.TraceID())
|
||||
e.Expect(childSpanContext.SpanID()).NotToEqual(napSpanContext.SpanID())
|
||||
e.Expect(testSpan.ParentSpanID().IsValid()).ToBeFalse()
|
||||
})
|
||||
|
||||
t.Run("creates new root when requested, even if context has current span", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
ctx, napSpan := subject.Start(context.Background(), "not-a-parent")
|
||||
napSpanContext := napSpan.SpanContext()
|
||||
_, span := subject.Start(ctx, "child", trace.WithNewRoot())
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
childSpanContext := testSpan.SpanContext()
|
||||
e.Expect(childSpanContext.IsValid()).ToBeTrue()
|
||||
e.Expect(childSpanContext.TraceID()).NotToEqual(napSpanContext.TraceID())
|
||||
e.Expect(childSpanContext.SpanID()).NotToEqual(napSpanContext.SpanID())
|
||||
e.Expect(testSpan.ParentSpanID().IsValid()).ToBeFalse()
|
||||
})
|
||||
|
||||
t.Run("uses the links provided through WithLinks", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
_, span := subject.Start(context.Background(), "link1")
|
||||
link1 := trace.Link{
|
||||
SpanContext: span.SpanContext(),
|
||||
Attributes: []attribute.KeyValue{
|
||||
attribute.String("a", "1"),
|
||||
},
|
||||
}
|
||||
|
||||
_, span = subject.Start(context.Background(), "link2")
|
||||
link2 := trace.Link{
|
||||
SpanContext: span.SpanContext(),
|
||||
Attributes: []attribute.KeyValue{
|
||||
attribute.String("b", "2"),
|
||||
},
|
||||
}
|
||||
|
||||
_, span = subject.Start(context.Background(), "test", trace.WithLinks(link1, link2))
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
links := testSpan.Links()
|
||||
e.Expect(links[0].Attributes).ToEqual(link1.Attributes)
|
||||
e.Expect(links[1].Attributes).ToEqual(link2.Attributes)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func testTracedSpan(t *testing.T, fn func(tracer trace.Tracer, name string) (trace.Span, error)) {
|
||||
tp := oteltest.NewTracerProvider()
|
||||
t.Run("starts a span with the expected name", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
expectedName := "test name"
|
||||
span, err := fn(subject, expectedName)
|
||||
|
||||
e.Expect(err).ToBeNil()
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(testSpan.Name()).ToEqual(expectedName)
|
||||
})
|
||||
|
||||
t.Run("uses the current time as the start time", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
subject := tp.Tracer(t.Name())
|
||||
|
||||
start := time.Now()
|
||||
span, err := fn(subject, "test")
|
||||
end := time.Now()
|
||||
|
||||
e.Expect(err).ToBeNil()
|
||||
|
||||
testSpan, ok := span.(*oteltest.Span)
|
||||
e.Expect(ok).ToBeTrue()
|
||||
|
||||
e.Expect(testSpan.StartTime()).ToBeTemporally(matchers.AfterOrSameTime, start)
|
||||
e.Expect(testSpan.StartTime()).ToBeTemporally(matchers.BeforeOrSameTime, end)
|
||||
})
|
||||
|
||||
t.Run("calls SpanRecorder.OnStart", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
sr := new(oteltest.SpanRecorder)
|
||||
subject := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr)).Tracer(t.Name())
|
||||
subject.Start(context.Background(), "span1")
|
||||
|
||||
e.Expect(len(sr.Started())).ToEqual(1)
|
||||
|
||||
span, err := fn(subject, "span2")
|
||||
e.Expect(err).ToBeNil()
|
||||
|
||||
spans := sr.Started()
|
||||
|
||||
e.Expect(len(spans)).ToEqual(2)
|
||||
e.Expect(spans[1]).ToEqual(span)
|
||||
})
|
||||
|
||||
t.Run("can be run concurrently with another call", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
e := matchers.NewExpecter(t)
|
||||
|
||||
sr := new(oteltest.SpanRecorder)
|
||||
subject := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr)).Tracer(t.Name())
|
||||
|
||||
numSpans := 2
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(numSpans)
|
||||
|
||||
for i := 0; i < numSpans; i++ {
|
||||
go func() {
|
||||
_, err := fn(subject, "test")
|
||||
e.Expect(err).ToBeNil()
|
||||
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
e.Expect(len(sr.Started())).ToEqual(numSpans)
|
||||
})
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// TraceStateFromKeyValues is a convenience function to create a
|
||||
// trace.TraceState from provided key/value pairs. There is no inverse to this
|
||||
// function, returning attributes from a TraceState, because the TraceState,
|
||||
// by definition from the W3C tracecontext specification, stores values as
|
||||
// opaque strings. Therefore, it is not possible to decode the original value
|
||||
// type from TraceState. Be sure to not use this outside of testing purposes.
|
||||
//
|
||||
// Deprecated: use trace.ParseTraceState instead.
|
||||
func TraceStateFromKeyValues(kvs ...attribute.KeyValue) (trace.TraceState, error) {
|
||||
if len(kvs) == 0 {
|
||||
return trace.TraceState{}, nil
|
||||
}
|
||||
|
||||
members := make([]string, len(kvs))
|
||||
for i, kv := range kvs {
|
||||
members[i] = fmt.Sprintf("%s=%s", string(kv.Key), kv.Value.Emit())
|
||||
}
|
||||
return trace.ParseTraceState(strings.Join(members, ","))
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Copyright The OpenTelemetry 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 oteltest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
func TestTraceStateFromKeyValues(t *testing.T) {
|
||||
ts, err := TraceStateFromKeyValues()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 0, ts.Len(), "empty attributes creats zero value TraceState")
|
||||
|
||||
ts, err = TraceStateFromKeyValues(
|
||||
attribute.String("key0", "string"),
|
||||
attribute.Bool("key1", true),
|
||||
attribute.Int64("key2", 1),
|
||||
attribute.Float64("key3", 1.1),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
expected := "key0=string,key1=true,key2=1,key3=1.1"
|
||||
assert.Equal(t, expected, ts.String())
|
||||
}
|
@ -32,8 +32,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../..
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ./
|
||||
|
@ -42,8 +42,6 @@ replace go.opentelemetry.io/otel/sdk => ./
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ./export/metric
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/metric => ./metric
|
||||
|
@ -32,8 +32,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../export/metric
|
||||
|
@ -32,8 +32,6 @@ replace go.opentelemetry.io/otel/internal/tools => ../internal/tools
|
||||
|
||||
replace go.opentelemetry.io/otel/metric => ../metric
|
||||
|
||||
replace go.opentelemetry.io/otel/oteltest => ../oteltest
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk => ../sdk
|
||||
|
||||
replace go.opentelemetry.io/otel/sdk/export/metric => ../sdk/export/metric
|
||||
|
@ -30,7 +30,6 @@ module-sets:
|
||||
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
|
||||
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
|
||||
- go.opentelemetry.io/otel/exporters/stdout/stdouttrace
|
||||
- go.opentelemetry.io/otel/oteltest
|
||||
- go.opentelemetry.io/otel/trace
|
||||
- go.opentelemetry.io/otel/sdk
|
||||
experimental-metrics:
|
||||
|
Loading…
Reference in New Issue
Block a user