1// Copyright 2019, OpenTelemetry Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package trace 16 17import ( 18 "context" 19 20 "go.opentelemetry.io/otel/api/core" 21 apitrace "go.opentelemetry.io/otel/api/trace" 22) 23 24type tracer struct { 25 provider *Provider 26 name string 27} 28 29var _ apitrace.Tracer = &tracer{} 30 31func (tr *tracer) Start(ctx context.Context, name string, o ...apitrace.StartOption) (context.Context, apitrace.Span) { 32 var opts apitrace.StartConfig 33 var parent core.SpanContext 34 var remoteParent bool 35 36 //TODO [rghetia] : Add new option for parent. If parent is configured then use that parent. 37 for _, op := range o { 38 op(&opts) 39 } 40 41 if relation := opts.Relation; relation.SpanContext != core.EmptySpanContext() { 42 switch relation.RelationshipType { 43 case apitrace.ChildOfRelationship, apitrace.FollowsFromRelationship: 44 parent = relation.SpanContext 45 remoteParent = true 46 default: 47 // Future relationship types may have different behavior, 48 // e.g., adding a `Link` instead of setting the `parent` 49 } 50 } else if p, ok := apitrace.SpanFromContext(ctx).(*span); ok { 51 p.addChild() 52 parent = p.spanContext 53 } 54 55 spanName := tr.spanNameWithPrefix(name) 56 span := startSpanInternal(tr, spanName, parent, remoteParent, opts) 57 for _, l := range opts.Links { 58 span.addLink(l) 59 } 60 span.SetAttributes(opts.Attributes...) 61 62 span.tracer = tr 63 64 if span.IsRecording() { 65 sps, _ := tr.provider.spanProcessors.Load().(spanProcessorMap) 66 for sp := range sps { 67 sp.OnStart(span.data) 68 } 69 } 70 71 ctx, end := startExecutionTracerTask(ctx, spanName) 72 span.executionTracerTaskEnd = end 73 return apitrace.ContextWithSpan(ctx, span), span 74} 75 76func (tr *tracer) WithSpan(ctx context.Context, name string, body func(ctx context.Context) error) error { 77 ctx, span := tr.Start(ctx, name) 78 defer span.End() 79 80 if err := body(ctx); err != nil { 81 // TODO: set event with boolean attribute for error. 82 return err 83 } 84 return nil 85} 86 87func (tr *tracer) spanNameWithPrefix(name string) string { 88 if tr.name != "" { 89 return tr.name + "/" + name 90 } 91 return name 92} 93