mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-01-20 03:30:02 +02:00
a98bb979df
* Update Tracer API with instrumentation version Add option to the `Provider.Tracer` method to specify the instrumentation version. Update the global, noop, opentracing bridge, and default SDK implementations. This does not propagate the instrumentation library version to the exported span. That is left for a follow-on PR. * Revert trace_test.go This is for the next PR. * Update SDK to include version for default instrumentation If the instrumentation library name is empty and the default instrumentation is uses, include the SDK version. * Update comments and documentation * Remove default instrumentation version
216 lines
5.7 KiB
Go
216 lines
5.7 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
//
|
|
// 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.
|
|
|
|
package trace
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
export "go.opentelemetry.io/otel/sdk/export/trace"
|
|
"go.opentelemetry.io/otel/sdk/instrumentation"
|
|
"go.opentelemetry.io/otel/sdk/resource"
|
|
|
|
apitrace "go.opentelemetry.io/otel/api/trace"
|
|
)
|
|
|
|
const (
|
|
defaultTracerName = "go.opentelemetry.io/otel/sdk/tracer"
|
|
)
|
|
|
|
// batcher contains export.SpanBatcher and its options.
|
|
type batcher struct {
|
|
b export.SpanBatcher
|
|
opts []BatchSpanProcessorOption
|
|
}
|
|
|
|
// ProviderOptions
|
|
type ProviderOptions struct {
|
|
syncers []export.SpanSyncer
|
|
batchers []batcher
|
|
config Config
|
|
}
|
|
|
|
type ProviderOption func(*ProviderOptions)
|
|
|
|
type Provider struct {
|
|
mu sync.Mutex
|
|
namedTracer map[instrumentation.Library]*tracer
|
|
spanProcessors atomic.Value
|
|
config atomic.Value // access atomically
|
|
}
|
|
|
|
var _ apitrace.Provider = &Provider{}
|
|
|
|
// NewProvider creates an instance of trace provider. Optional
|
|
// parameter configures the provider with common options applicable
|
|
// to all tracer instances that will be created by this provider.
|
|
func NewProvider(opts ...ProviderOption) (*Provider, error) {
|
|
o := &ProviderOptions{}
|
|
|
|
for _, opt := range opts {
|
|
opt(o)
|
|
}
|
|
|
|
tp := &Provider{
|
|
namedTracer: make(map[instrumentation.Library]*tracer),
|
|
}
|
|
tp.config.Store(&Config{
|
|
DefaultSampler: AlwaysSample(),
|
|
IDGenerator: defIDGenerator(),
|
|
MaxAttributesPerSpan: DefaultMaxAttributesPerSpan,
|
|
MaxEventsPerSpan: DefaultMaxEventsPerSpan,
|
|
MaxLinksPerSpan: DefaultMaxLinksPerSpan,
|
|
})
|
|
|
|
for _, syncer := range o.syncers {
|
|
ssp := NewSimpleSpanProcessor(syncer)
|
|
tp.RegisterSpanProcessor(ssp)
|
|
}
|
|
|
|
for _, batcher := range o.batchers {
|
|
bsp, err := NewBatchSpanProcessor(batcher.b, batcher.opts...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tp.RegisterSpanProcessor(bsp)
|
|
}
|
|
|
|
tp.ApplyConfig(o.config)
|
|
|
|
return tp, nil
|
|
}
|
|
|
|
// Tracer with the given name. If a tracer for the given name does not exist,
|
|
// it is created first. If the name is empty, DefaultTracerName is used.
|
|
func (p *Provider) Tracer(name string, opts ...apitrace.TracerOption) apitrace.Tracer {
|
|
c := new(apitrace.TracerConfig)
|
|
for _, o := range opts {
|
|
o(c)
|
|
}
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
if name == "" {
|
|
name = defaultTracerName
|
|
}
|
|
il := instrumentation.Library{
|
|
Name: name,
|
|
Version: c.InstrumentationVersion,
|
|
}
|
|
t, ok := p.namedTracer[il]
|
|
if !ok {
|
|
t = &tracer{
|
|
provider: p,
|
|
instrumentationLibrary: il,
|
|
}
|
|
p.namedTracer[il] = t
|
|
}
|
|
return t
|
|
}
|
|
|
|
// RegisterSpanProcessor adds the given SpanProcessor to the list of SpanProcessors
|
|
func (p *Provider) RegisterSpanProcessor(s SpanProcessor) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
new := make(spanProcessorMap)
|
|
if old, ok := p.spanProcessors.Load().(spanProcessorMap); ok {
|
|
for k, v := range old {
|
|
new[k] = v
|
|
}
|
|
}
|
|
new[s] = &sync.Once{}
|
|
p.spanProcessors.Store(new)
|
|
}
|
|
|
|
// UnregisterSpanProcessor removes the given SpanProcessor from the list of SpanProcessors
|
|
func (p *Provider) UnregisterSpanProcessor(s SpanProcessor) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
new := make(spanProcessorMap)
|
|
if old, ok := p.spanProcessors.Load().(spanProcessorMap); ok {
|
|
for k, v := range old {
|
|
new[k] = v
|
|
}
|
|
}
|
|
if stopOnce, ok := new[s]; ok && stopOnce != nil {
|
|
stopOnce.Do(func() {
|
|
s.Shutdown()
|
|
})
|
|
}
|
|
delete(new, s)
|
|
p.spanProcessors.Store(new)
|
|
}
|
|
|
|
// ApplyConfig changes the configuration of the provider.
|
|
// If a field in the configuration is empty or nil then its original value is preserved.
|
|
func (p *Provider) ApplyConfig(cfg Config) {
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
c := *p.config.Load().(*Config)
|
|
if cfg.DefaultSampler != nil {
|
|
c.DefaultSampler = cfg.DefaultSampler
|
|
}
|
|
if cfg.IDGenerator != nil {
|
|
c.IDGenerator = cfg.IDGenerator
|
|
}
|
|
if cfg.MaxEventsPerSpan > 0 {
|
|
c.MaxEventsPerSpan = cfg.MaxEventsPerSpan
|
|
}
|
|
if cfg.MaxAttributesPerSpan > 0 {
|
|
c.MaxAttributesPerSpan = cfg.MaxAttributesPerSpan
|
|
}
|
|
if cfg.MaxLinksPerSpan > 0 {
|
|
c.MaxLinksPerSpan = cfg.MaxLinksPerSpan
|
|
}
|
|
if cfg.Resource != nil {
|
|
c.Resource = cfg.Resource
|
|
}
|
|
p.config.Store(&c)
|
|
}
|
|
|
|
// WithSyncer options appends the syncer to the existing list of Syncers.
|
|
// This option can be used multiple times.
|
|
// The Syncers are wrapped into SimpleSpanProcessors and registered
|
|
// with the provider.
|
|
func WithSyncer(syncer export.SpanSyncer) ProviderOption {
|
|
return func(opts *ProviderOptions) {
|
|
opts.syncers = append(opts.syncers, syncer)
|
|
}
|
|
}
|
|
|
|
// WithBatcher options appends the batcher to the existing list of Batchers.
|
|
// This option can be used multiple times.
|
|
// The Batchers are wrapped into BatchedSpanProcessors and registered
|
|
// with the provider.
|
|
func WithBatcher(b export.SpanBatcher, bopts ...BatchSpanProcessorOption) ProviderOption {
|
|
return func(opts *ProviderOptions) {
|
|
opts.batchers = append(opts.batchers, batcher{b, bopts})
|
|
}
|
|
}
|
|
|
|
// WithConfig option sets the configuration to provider.
|
|
func WithConfig(config Config) ProviderOption {
|
|
return func(opts *ProviderOptions) {
|
|
opts.config = config
|
|
}
|
|
}
|
|
|
|
// WithResource option attaches a resource to the provider.
|
|
// The resource is added to the span when it is started.
|
|
func WithResource(r *resource.Resource) ProviderOption {
|
|
return func(opts *ProviderOptions) {
|
|
opts.config.Resource = r
|
|
}
|
|
}
|