2020-03-24 07:41:10 +02:00
|
|
|
// Copyright The OpenTelemetry Authors
|
2019-12-05 00:00:35 +02:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2020-11-04 19:10:58 +02:00
|
|
|
package oteltest // import "go.opentelemetry.io/otel/oteltest"
|
2019-12-05 00:00:35 +02:00
|
|
|
|
|
|
|
import (
|
2020-02-28 23:44:53 +02:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
2019-12-05 00:00:35 +02:00
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2021-02-18 19:59:37 +02:00
|
|
|
"go.opentelemetry.io/otel/attribute"
|
2020-08-10 18:17:09 +02:00
|
|
|
"go.opentelemetry.io/otel/codes"
|
2021-04-01 22:07:46 +02:00
|
|
|
"go.opentelemetry.io/otel/semconv"
|
2020-11-07 00:13:31 +02:00
|
|
|
"go.opentelemetry.io/otel/trace"
|
2019-12-05 00:00:35 +02:00
|
|
|
)
|
|
|
|
|
2020-11-07 00:13:31 +02:00
|
|
|
var _ trace.Span = (*Span)(nil)
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// Span is an OpenTelemetry Span used for testing.
|
2019-12-05 00:00:35 +02:00
|
|
|
type Span struct {
|
2020-07-28 19:47:08 +02:00
|
|
|
lock sync.RWMutex
|
2020-03-07 20:38:59 +02:00
|
|
|
tracer *Tracer
|
2020-11-07 00:13:31 +02:00
|
|
|
spanContext trace.SpanContext
|
|
|
|
parentSpanID trace.SpanID
|
2020-03-07 20:38:59 +02:00
|
|
|
ended bool
|
|
|
|
name string
|
|
|
|
startTime time.Time
|
|
|
|
endTime time.Time
|
|
|
|
statusCode codes.Code
|
|
|
|
statusMessage string
|
2021-02-18 19:59:37 +02:00
|
|
|
attributes map[attribute.Key]attribute.Value
|
2020-03-07 20:38:59 +02:00
|
|
|
events []Event
|
2020-12-21 23:11:48 +02:00
|
|
|
links []trace.Link
|
2020-11-07 00:13:31 +02:00
|
|
|
spanKind trace.SpanKind
|
2019-12-05 00:00:35 +02:00
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// Tracer returns the Tracer that created s.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) Tracer() trace.Tracer {
|
2019-12-05 00:00:35 +02:00
|
|
|
return s.tracer
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) End(opts ...trace.SpanOption) {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
if s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-07 00:13:31 +02:00
|
|
|
c := trace.NewSpanConfig(opts...)
|
2019-12-05 00:00:35 +02:00
|
|
|
s.endTime = time.Now()
|
2020-09-03 16:34:36 +02:00
|
|
|
if endTime := c.Timestamp; !endTime.IsZero() {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.endTime = endTime
|
|
|
|
}
|
|
|
|
|
|
|
|
s.ended = true
|
2020-07-28 19:47:08 +02:00
|
|
|
if s.tracer.config.SpanRecorder != nil {
|
|
|
|
s.tracer.config.SpanRecorder.OnEnd(s)
|
|
|
|
}
|
2019-12-05 00:00:35 +02:00
|
|
|
}
|
|
|
|
|
2021-04-01 22:07:46 +02:00
|
|
|
// RecordError records an error as an exception Span event.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) RecordError(err error, opts ...trace.EventOption) {
|
2020-02-28 23:44:53 +02:00
|
|
|
if err == nil || s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
errType := reflect.TypeOf(err)
|
|
|
|
errTypeString := fmt.Sprintf("%s.%s", errType.PkgPath(), errType.Name())
|
|
|
|
if errTypeString == "." {
|
|
|
|
errTypeString = errType.String()
|
|
|
|
}
|
|
|
|
|
2020-11-07 00:13:31 +02:00
|
|
|
opts = append(opts, trace.WithAttributes(
|
2021-04-01 22:07:46 +02:00
|
|
|
semconv.ExceptionTypeKey.String(errTypeString),
|
|
|
|
semconv.ExceptionMessageKey.String(err.Error()),
|
2020-10-16 17:09:27 +02:00
|
|
|
))
|
2020-02-28 23:44:53 +02:00
|
|
|
|
2021-04-01 22:07:46 +02:00
|
|
|
s.AddEvent(semconv.ExceptionEventName, opts...)
|
2019-12-05 00:00:35 +02:00
|
|
|
}
|
|
|
|
|
2020-10-16 17:09:27 +02:00
|
|
|
// AddEvent adds an event to s.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) AddEvent(name string, o ...trace.EventOption) {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
if s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-07 00:13:31 +02:00
|
|
|
c := trace.NewEventConfig(o...)
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2021-02-18 19:59:37 +02:00
|
|
|
var attributes map[attribute.Key]attribute.Value
|
2020-10-16 17:09:27 +02:00
|
|
|
if l := len(c.Attributes); l > 0 {
|
2021-02-18 19:59:37 +02:00
|
|
|
attributes = make(map[attribute.Key]attribute.Value, l)
|
2020-10-16 17:09:27 +02:00
|
|
|
for _, attr := range c.Attributes {
|
|
|
|
attributes[attr.Key] = attr.Value
|
|
|
|
}
|
2019-12-05 00:00:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
s.events = append(s.events, Event{
|
2020-10-16 17:09:27 +02:00
|
|
|
Timestamp: c.Timestamp,
|
2019-12-18 20:13:05 +02:00
|
|
|
Name: name,
|
2019-12-05 00:00:35 +02:00
|
|
|
Attributes: attributes,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// IsRecording returns the recording state of s.
|
2019-12-05 00:00:35 +02:00
|
|
|
func (s *Span) IsRecording() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// SpanContext returns the SpanContext of s.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) SpanContext() trace.SpanContext {
|
2019-12-05 00:00:35 +02:00
|
|
|
return s.spanContext
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// SetStatus sets the status of s in the form of a code and a message.
|
2020-03-07 20:38:59 +02:00
|
|
|
func (s *Span) SetStatus(code codes.Code, msg string) {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
if s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-07 20:38:59 +02:00
|
|
|
s.statusCode = code
|
|
|
|
s.statusMessage = msg
|
2019-12-05 00:00:35 +02:00
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// SetName sets the name of s.
|
2019-12-05 00:00:35 +02:00
|
|
|
func (s *Span) SetName(name string) {
|
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
if s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
s.name = name
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// SetAttributes sets attrs as attributes of s.
|
2021-02-18 19:59:37 +02:00
|
|
|
func (s *Span) SetAttributes(attrs ...attribute.KeyValue) {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
if s.ended {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, attr := range attrs {
|
|
|
|
s.attributes[attr.Key] = attr.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) Name() string { return s.name }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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
|
2019-12-05 00:00:35 +02:00
|
|
|
// (i.e., it will contain all zeroes).
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) ParentSpanID() trace.SpanID { return s.parentSpanID }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2021-02-18 19:59:37 +02:00
|
|
|
func (s *Span) Attributes() map[attribute.Key]attribute.Value {
|
2019-12-05 00:00:35 +02:00
|
|
|
s.lock.RLock()
|
|
|
|
defer s.lock.RUnlock()
|
|
|
|
|
2021-02-18 19:59:37 +02:00
|
|
|
attributes := make(map[attribute.Key]attribute.Value)
|
2019-12-05 00:00:35 +02:00
|
|
|
|
|
|
|
for k, v := range s.attributes {
|
|
|
|
attributes[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
return attributes
|
|
|
|
}
|
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// Events returns the events set on s. Events cannot be changed after End has
|
|
|
|
// been called on s.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) Events() []Event { return s.events }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2020-12-21 23:11:48 +02:00
|
|
|
func (s *Span) Links() []trace.Link { return s.links }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// StartTime returns the time at which s was started. This will be the
|
|
|
|
// wall-clock time unless a specific start time was provided.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) StartTime() time.Time { return s.startTime }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) EndTime() (time.Time, bool) { return s.endTime, s.ended }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// Ended returns whether s has been ended, i.e. whether End has been called at
|
|
|
|
// least once on s.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) Ended() bool { return s.ended }
|
2019-12-05 00:00:35 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// 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.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) StatusCode() codes.Code { return s.statusCode }
|
2020-03-07 20:38:59 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// StatusMessage returns the status message most recently set on s or the
|
|
|
|
// empty string if no status message was set.
|
2020-10-16 17:09:27 +02:00
|
|
|
func (s *Span) StatusMessage() string { return s.statusMessage }
|
2020-07-30 01:06:20 +02:00
|
|
|
|
2020-10-13 21:27:53 +02:00
|
|
|
// SpanKind returns the span kind of s.
|
2020-11-07 00:13:31 +02:00
|
|
|
func (s *Span) SpanKind() trace.SpanKind { return s.spanKind }
|