1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-07-15 01:04:25 +02:00

Add SetStatus, SpanContext and IsRecordingEvent (#12)

* Add span apis.
- SetStatus
- SpanContext
- IsRecordingEvent

* fix formatting.

* use grpc/codes.Code

* change Option to SpanOption

* fix format errors.
This commit is contained in:
rghetia
2019-06-19 10:44:46 -07:00
committed by GitHub
parent 063035e9e0
commit 3c3532fb04
11 changed files with 191 additions and 46 deletions

View File

@ -17,6 +17,9 @@ package core
import (
"context"
"fmt"
"strconv"
"google.golang.org/grpc/codes"
"github.com/open-telemetry/opentelemetry-go/api/unit"
)
@ -132,6 +135,12 @@ const (
DELETE
)
var (
// INVALID_SPAN_CONTEXT is meant for internal use to return invalid span context during error
// conditions.
INVALID_SPAN_CONTEXT = SpanContext{}
)
func (sc SpanContext) HasTraceID() bool {
return sc.TraceIDHigh != 0 || sc.TraceIDLow != 0
}
@ -191,3 +200,44 @@ func (m Measurement) With(id ScopeID) Measurement {
m.ScopeID = id
return m
}
func GrpcCodeToString(s codes.Code) string {
switch c := s; c {
case codes.OK:
return "OK"
case codes.Canceled:
return "CANCELLED"
case codes.Unknown:
return "UNKNOWN"
case codes.InvalidArgument:
return "INVALID_ARGUMENT"
case codes.DeadlineExceeded:
return "DEADLINE_EXCEEDED"
case codes.NotFound:
return "NOT_FOUND"
case codes.AlreadyExists:
return "ALREADY_EXISTS"
case codes.PermissionDenied:
return "PERMISSION_DENIED"
case codes.ResourceExhausted:
return "RESOURCE_EXHAUSTED"
case codes.FailedPrecondition:
return "FAILED_PRECONDITION"
case codes.Aborted:
return "ABORTED"
case codes.OutOfRange:
return "OUT_OF_RANGE"
case codes.Unimplemented:
return "UNIMPLEMENTED"
case codes.Internal:
return "INTERNAL"
case codes.Unavailable:
return "UNAVAILABLE"
case codes.DataLoss:
return "DATA_LOSS"
case codes.Unauthenticated:
return "UNAUTHENTICATED"
default:
return "STATUS_" + strconv.FormatInt(int64(c), 10)
}
}

View File

@ -18,6 +18,8 @@ import (
"context"
"time"
"google.golang.org/grpc/codes"
"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/log"
"github.com/open-telemetry/opentelemetry-go/api/scope"
@ -27,7 +29,7 @@ import (
type (
Tracer interface {
Start(context.Context, string, ...Option) (context.Context, Span)
Start(context.Context, string, ...SpanOption) (context.Context, Span)
WithSpan(
ctx context.Context,
@ -58,17 +60,29 @@ type (
Tracer() Tracer
Finish()
// IsRecordingEvents returns true is the span is active and recording events is enabled.
IsRecordingEvents() bool
// SpancContext returns span context of the span. Return SpanContext is usable
// even after the span is finished.
SpanContext() core.SpanContext
SetStatus(codes.Code)
}
Injector interface {
Inject(core.SpanContext, tag.Map)
}
Option struct {
attribute core.KeyValue
attributes []core.KeyValue
startTime time.Time
reference Reference
// SpanOption apply changes to SpanOptions.
SpanOption func(*SpanOptions)
SpanOptions struct {
attributes []core.KeyValue
startTime time.Time
reference Reference
recordEvent bool
}
Reference struct {
@ -95,7 +109,7 @@ func SetGlobalTracer(t Tracer) {
global.Store(t)
}
func Start(ctx context.Context, name string, opts ...Option) (context.Context, Span) {
func Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) {
return GlobalTracer().Start(ctx, name, opts...)
}
@ -121,38 +135,38 @@ func Inject(ctx context.Context, injector Injector) {
span.Tracer().Inject(ctx, span, injector)
}
func WithStartTime(t time.Time) Option {
return Option{
startTime: t,
func WithStartTime(t time.Time) SpanOption {
return func(o *SpanOptions) {
o.startTime = t
}
}
func WithAttributes(attrs ...core.KeyValue) Option {
return Option{
attributes: attrs,
func WithAttributes(attrs ...core.KeyValue) SpanOption {
return func(o *SpanOptions) {
o.attributes = attrs
}
}
func WithAttribute(attr core.KeyValue) Option {
return Option{
attribute: attr,
func WithRecordEvents() SpanOption {
return func(o *SpanOptions) {
o.recordEvent = true
}
}
func ChildOf(sc core.SpanContext) Option {
return Option{
reference: Reference{
func ChildOf(sc core.SpanContext) SpanOption {
return func(o *SpanOptions) {
o.reference = Reference{
SpanContext: sc,
RelationshipType: ChildOfRelationship,
},
}
}
}
func FollowsFrom(sc core.SpanContext) Option {
return Option{
reference: Reference{
func FollowsFrom(sc core.SpanContext) SpanOption {
return func(o *SpanOptions) {
o.reference = Reference{
SpanContext: sc,
RelationshipType: FollowsFromRelationship,
},
}
}
}

View File

@ -17,12 +17,44 @@ package trace
import (
"context"
"google.golang.org/grpc/codes"
"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/log"
"github.com/open-telemetry/opentelemetry-go/api/stats"
"github.com/open-telemetry/opentelemetry-go/exporter/observer"
)
// SpancContext returns span context of the span. Return SpanContext is usable
// even after the span is finished.
func (sp *span) SpanContext() core.SpanContext {
if sp == nil {
return core.INVALID_SPAN_CONTEXT
}
return sp.spanContext
}
// IsRecordingEvents returns true is the span is active and recording events is enabled.
func (sp *span) IsRecordingEvents() bool {
return false
}
// SetStatus sets the status of the span.
func (sp *span) SetStatus(status codes.Code) {
if sp == nil {
return
}
sid := sp.ScopeID()
observer.Record(observer.Event{
Type: observer.SET_STATUS,
Scope: sid,
Sequence: sid.EventID,
Status: status,
})
sp.status = status
}
func (sp *span) ScopeID() core.ScopeID {
if sp == nil {
return core.ScopeID{}

View File

@ -19,7 +19,8 @@ import (
"math/rand"
"sync"
"sync/atomic"
"time"
"google.golang.org/grpc/codes"
"github.com/open-telemetry/opentelemetry-go/api/core"
"github.com/open-telemetry/opentelemetry-go/api/log"
@ -35,6 +36,8 @@ type (
lock sync.Mutex
eventID core.EventID
finishOnce sync.Once
recordEvent bool
status codes.Code
}
tracer struct {
@ -93,34 +96,21 @@ func (t *tracer) WithSpan(ctx context.Context, name string, body func(context.Co
return nil
}
func (t *tracer) Start(ctx context.Context, name string, opts ...Option) (context.Context, Span) {
func (t *tracer) Start(ctx context.Context, name string, opts ...SpanOption) (context.Context, Span) {
var child core.SpanContext
child.SpanID = rand.Uint64()
var startTime time.Time
var attributes []core.KeyValue
var reference Reference
o := &SpanOptions{}
for _, opt := range opts {
if !opt.startTime.IsZero() {
startTime = opt.startTime
}
if len(opt.attributes) != 0 {
attributes = append(opt.attributes, attributes...)
}
if opt.attribute.Key != nil {
attributes = append(attributes, opt.attribute)
}
if opt.reference.HasTraceID() {
reference = opt.reference
}
opt(o)
}
var parentScope core.ScopeID
if reference.HasTraceID() {
parentScope = reference.Scope()
if o.reference.HasTraceID() {
parentScope = o.reference.Scope()
} else {
parentScope = Active(ctx).ScopeID()
}
@ -142,10 +132,11 @@ func (t *tracer) Start(ctx context.Context, name string, opts ...Option) (contex
span := &span{
spanContext: child,
tracer: t,
recordEvent: o.recordEvent,
eventID: observer.Record(observer.Event{
Time: startTime,
Time: o.startTime,
Type: observer.START_SPAN,
Scope: scope.New(childScope, attributes...).ScopeID(),
Scope: scope.New(childScope, o.attributes...).ScopeID(),
Context: ctx,
Parent: parentScope,
String: name,