You've already forked opentelemetry-go
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:
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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{}
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user