Skip to content

Commit

Permalink
Update documentation for otel/oteltest (#1248)
Browse files Browse the repository at this point in the history
* Fix lint issues in `otel/oteltest`

Add documentation to exported functions, types, and methods that had
none.

Update existing documentation to wrap consistently and fix grammatical
errors.

* Update oteltest package documentation
  • Loading branch information
MrAlias committed Oct 13, 2020
1 parent 396dd60 commit 5c21e88
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 29 deletions.
15 changes: 15 additions & 0 deletions oteltest/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func newConfig(opts ...Option) config {
return conf
}

// Option applies an option to a config.
type Option interface {
Apply(*config)
}
Expand All @@ -72,6 +73,8 @@ 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) otel.SpanContext) Option {
return spanContextFuncOption{f}
}
Expand All @@ -84,15 +87,23 @@ 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{sr}
}

// SpanRecorder performs operations to record a span as it starts and ends.
type SpanRecorder interface {
// OnStart is called by the Tracer when it starts a Span.
OnStart(span *Span)
// OnEnd is called by the Span when it ends.
OnEnd(span *Span)
}

// StandardSpanRecorder is a SpanRecorder that records all started and ended
// spans in an ordered recording. StandardSpanRecorder is designed to be
// concurrent safe and can by used by multiple goroutines.
type StandardSpanRecorder struct {
startedMu sync.RWMutex
started []*Span
Expand All @@ -101,18 +112,21 @@ type StandardSpanRecorder struct {
done []*Span
}

// OnStart records span as started.
func (ssr *StandardSpanRecorder) OnStart(span *Span) {
ssr.startedMu.Lock()
defer ssr.startedMu.Unlock()
ssr.started = append(ssr.started, span)
}

// OnEnd records span as completed.
func (ssr *StandardSpanRecorder) 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 *StandardSpanRecorder) Started() []*Span {
ssr.startedMu.RLock()
defer ssr.startedMu.RUnlock()
Expand All @@ -123,6 +137,7 @@ func (ssr *StandardSpanRecorder) Started() []*Span {
return started
}

// Completed returns a copy of all ended Spans in the order they were ended.
func (ssr *StandardSpanRecorder) Completed() []*Span {
ssr.doneMu.RLock()
defer ssr.doneMu.RUnlock()
Expand Down
33 changes: 32 additions & 1 deletion oteltest/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Package oteltest provides testing utilities for the otel package.
/*
Package oteltest provides testing utilities for the otel package.
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.StandardSpanRecorder)
tp := oteltest.NewTracerProvider(oteltest.WithSpanRecorder(sr))
*/
package oteltest // import "go.opentelemetry.io/otel/oteltest"
2 changes: 1 addition & 1 deletion oteltest/mock_span.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ func (ms *MockSpan) Tracer() otel.Tracer {
func (ms *MockSpan) AddEvent(ctx context.Context, name string, attrs ...label.KeyValue) {
}

// AddEvent does nothing.
// AddEventWithTimestamp does nothing.
func (ms *MockSpan) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...label.KeyValue) {
}
10 changes: 8 additions & 2 deletions oteltest/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (
"go.opentelemetry.io/otel"
)

// 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

Expand All @@ -29,9 +33,10 @@ type TracerProvider struct {

var _ otel.TracerProvider = (*TracerProvider)(nil)

func NewTracerProvider(opts ...Option) *TracerProvider {
// NewTracerProvider returns a *TracerProvider configured with options.
func NewTracerProvider(options ...Option) *TracerProvider {
return &TracerProvider{
config: newConfig(opts...),
config: newConfig(options...),
tracers: make(map[instrumentation]*Tracer),
}
}
Expand All @@ -40,6 +45,7 @@ type instrumentation struct {
Name, Version string
}

// Tracer returns an OpenTelemetry Tracer used for testing.
func (p *TracerProvider) Tracer(instName string, opts ...otel.TracerOption) otel.Tracer {
conf := otel.NewTracerConfig(opts...)

Expand Down
62 changes: 37 additions & 25 deletions oteltest/span.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (

var _ otel.Span = (*Span)(nil)

// Span is an OpenTelemetry Span used for testing.
type Span struct {
lock sync.RWMutex
tracer *Tracer
Expand All @@ -51,10 +52,14 @@ type Span struct {
spanKind otel.SpanKind
}

// Tracer returns the Tracer that created s.
func (s *Span) Tracer() otel.Tracer {
return s.tracer
}

// 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 ...otel.SpanOption) {
s.lock.Lock()
defer s.lock.Unlock()
Expand All @@ -75,6 +80,7 @@ func (s *Span) End(opts ...otel.SpanOption) {
}
}

// RecordError records an error as a Span event.
func (s *Span) RecordError(ctx context.Context, err error, opts ...otel.ErrorOption) {
if err == nil || s.ended {
return
Expand Down Expand Up @@ -102,10 +108,12 @@ func (s *Span) RecordError(ctx context.Context, err error, opts ...otel.ErrorOpt
)
}

// AddEvent adds an event to s.
func (s *Span) AddEvent(ctx context.Context, name string, attrs ...label.KeyValue) {
s.AddEventWithTimestamp(ctx, time.Now(), name, attrs...)
}

// AddEventWithTimestamp adds an event that occurred at timestamp to s.
func (s *Span) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, name string, attrs ...label.KeyValue) {
s.lock.Lock()
defer s.lock.Unlock()
Expand All @@ -127,14 +135,17 @@ func (s *Span) AddEventWithTimestamp(ctx context.Context, timestamp time.Time, n
})
}

// IsRecording returns the recording state of s.
func (s *Span) IsRecording() bool {
return true
}

// SpanContext returns the SpanContext of s.
func (s *Span) SpanContext() otel.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()
Expand All @@ -147,6 +158,7 @@ func (s *Span) SetStatus(code codes.Code, msg string) {
s.statusMessage = msg
}

// SetName sets the name of s.
func (s *Span) SetName(name string) {
s.lock.Lock()
defer s.lock.Unlock()
Expand All @@ -158,6 +170,7 @@ func (s *Span) SetName(name string) {
s.name = name
}

// SetAttributes sets attrs as attributes of s.
func (s *Span) SetAttributes(attrs ...label.KeyValue) {
s.lock.Lock()
defer s.lock.Unlock()
Expand All @@ -171,22 +184,22 @@ func (s *Span) SetAttributes(attrs ...label.KeyValue) {
}
}

// Name returns the name most recently set on the Span, either at or after creation time.
// It cannot be change after End has been called on the Span.
// 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 the Span is a root Span and therefore does not have a parent, the returned SpanID will be invalid
// 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() otel.SpanID {
return s.parentSpanID
}

// Attributes returns the attributes set on the Span, 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 the Span.
// 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[label.Key]label.Value {
s.lock.RLock()
defer s.lock.RUnlock()
Expand All @@ -200,14 +213,14 @@ func (s *Span) Attributes() map[label.Key]label.Value {
return attributes
}

// Events returns the events set on the Span.
// Events cannot be changed after End has been called on the Span.
// 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 the Span at creation time.
// If multiple links for the same SpanContext were set, the last link will be used.
// 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() map[otel.SpanContext][]label.KeyValue {
links := make(map[otel.SpanContext][]label.KeyValue)

Expand All @@ -218,40 +231,39 @@ func (s *Span) Links() map[otel.SpanContext][]label.KeyValue {
return links
}

// StartTime returns the time at which the Span was started.
// This will be the wall-clock time unless a specific start time was provided.
// 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 the Span 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.
// 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 the Span has been ended,
// i.e., whether End has been called at least once on the Span.
// 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
}

// Status returns the status most recently set on the Span,
// or codes.OK if no status has been explicitly set.
// It cannot be changed after End has been called on the Span.
// 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 the
// Span or the empty string if no status mesaage was set.
// 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 this span.
// SpanKind returns the span kind of s.
func (s *Span) SpanKind() otel.SpanKind {
return s.spanKind
}
2 changes: 2 additions & 0 deletions oteltest/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type Tracer struct {
config *config
}

// 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 ...otel.SpanOption) (context.Context, otel.Span) {
c := otel.NewSpanConfig(opts...)
startTime := time.Now()
Expand Down

0 comments on commit 5c21e88

Please sign in to comment.