[bugfix] Downstep otel to fix freebsd compile issue (#1773)

https://github.com/open-telemetry/opentelemetry-go/issues/4076
This commit is contained in:
tobi 2023-05-12 14:55:18 +02:00 committed by GitHub
commit b47661f033
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
70 changed files with 1097 additions and 3138 deletions

View file

@ -70,8 +70,8 @@ const (
// returned.
func firstInt(defaultValue int, keys ...string) int {
for _, key := range keys {
value := os.Getenv(key)
if value == "" {
value, ok := os.LookupEnv(key)
if !ok {
continue
}
@ -88,10 +88,10 @@ func firstInt(defaultValue int, keys ...string) int {
}
// IntEnvOr returns the int value of the environment variable with name key if
// it exists, it is not empty, and the value is an int. Otherwise, defaultValue is returned.
// it exists and the value is an int. Otherwise, defaultValue is returned.
func IntEnvOr(key string, defaultValue int) int {
value := os.Getenv(key)
if value == "" {
value, ok := os.LookupEnv(key)
if !ok {
return defaultValue
}

View file

@ -14,7 +14,16 @@
package internal // import "go.opentelemetry.io/otel/sdk/internal"
import "time"
import (
"fmt"
"time"
"go.opentelemetry.io/otel"
)
// UserAgent is the user agent to be added to the outgoing
// requests from the exporters.
var UserAgent = fmt.Sprintf("opentelemetry-go/%s", otel.Version())
// MonotonicEndTime returns the end time at present
// but offset from start, monotonically.

View file

@ -18,7 +18,6 @@ import (
"context"
"errors"
"fmt"
"strings"
)
var (
@ -46,65 +45,28 @@ type Detector interface {
// Detect calls all input detectors sequentially and merges each result with the previous one.
// It returns the merged error too.
func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) {
r := new(Resource)
return r, detect(ctx, r, detectors)
}
// detect runs all detectors using ctx and merges the result into res. This
// assumes res is allocated and not nil, it will panic otherwise.
func detect(ctx context.Context, res *Resource, detectors []Detector) error {
var (
r *Resource
errs detectErrs
err error
)
var autoDetectedRes *Resource
var errInfo []string
for _, detector := range detectors {
if detector == nil {
continue
}
r, err = detector.Detect(ctx)
res, err := detector.Detect(ctx)
if err != nil {
errs = append(errs, err)
errInfo = append(errInfo, err.Error())
if !errors.Is(err, ErrPartialResource) {
continue
}
}
r, err = Merge(res, r)
autoDetectedRes, err = Merge(autoDetectedRes, res)
if err != nil {
errs = append(errs, err)
errInfo = append(errInfo, err.Error())
}
*res = *r
}
if len(errs) == 0 {
return nil
var aggregatedError error
if len(errInfo) > 0 {
aggregatedError = fmt.Errorf("detecting resources: %s", errInfo)
}
return errs
}
type detectErrs []error
func (e detectErrs) Error() string {
errStr := make([]string, len(e))
for i, err := range e {
errStr[i] = fmt.Sprintf("* %s", err)
}
format := "%d errors occurred detecting resource:\n\t%s"
return fmt.Sprintf(format, len(e), strings.Join(errStr, "\n\t"))
}
func (e detectErrs) Unwrap() error {
switch len(e) {
case 0:
return nil
case 1:
return e[0]
}
return e[1:]
}
func (e detectErrs) Is(target error) bool {
return len(e) != 0 && errors.Is(e[0], target)
return autoDetectedRes, aggregatedError
}

View file

@ -20,8 +20,8 @@ import (
"os"
"path/filepath"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
)
@ -62,7 +62,7 @@ func (telemetrySDK) Detect(context.Context) (*Resource, error) {
semconv.SchemaURL,
semconv.TelemetrySDKName("opentelemetry"),
semconv.TelemetrySDKLanguageGo,
semconv.TelemetrySDKVersion(sdk.Version()),
semconv.TelemetrySDKVersion(otel.Version()),
), nil
}

View file

@ -71,11 +71,6 @@ func WithHost() Option {
return WithDetectors(host{})
}
// WithHostID adds host ID information to the configured resource.
func WithHostID() Option {
return WithDetectors(hostIDDetector{})
}
// WithTelemetrySDK adds TelemetrySDK version info to the configured resource.
func WithTelemetrySDK() Option {
return WithDetectors(telemetrySDK{})

View file

@ -1,120 +0,0 @@
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
import (
"context"
"errors"
"strings"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
)
type hostIDProvider func() (string, error)
var defaultHostIDProvider hostIDProvider = platformHostIDReader.read
var hostID = defaultHostIDProvider
type hostIDReader interface {
read() (string, error)
}
type fileReader func(string) (string, error)
type commandExecutor func(string, ...string) (string, error)
// hostIDReaderBSD implements hostIDReader.
type hostIDReaderBSD struct {
execCommand commandExecutor
readFile fileReader
}
// read attempts to read the machine-id from /etc/hostid. If not found it will
// execute `kenv -q smbios.system.uuid`. If neither location yields an id an
// error will be returned.
func (r *hostIDReaderBSD) read() (string, error) {
if result, err := r.readFile("/etc/hostid"); err == nil {
return strings.TrimSpace(result), nil
}
if result, err := r.execCommand("kenv", "-q", "smbios.system.uuid"); err == nil {
return strings.TrimSpace(result), nil
}
return "", errors.New("host id not found in: /etc/hostid or kenv")
}
// hostIDReaderDarwin implements hostIDReader.
type hostIDReaderDarwin struct {
execCommand commandExecutor
}
// read executes `ioreg -rd1 -c "IOPlatformExpertDevice"` and parses host id
// from the IOPlatformUUID line. If the command fails or the uuid cannot be
// parsed an error will be returned.
func (r *hostIDReaderDarwin) read() (string, error) {
result, err := r.execCommand("ioreg", "-rd1", "-c", "IOPlatformExpertDevice")
if err != nil {
return "", err
}
lines := strings.Split(result, "\n")
for _, line := range lines {
if strings.Contains(line, "IOPlatformUUID") {
parts := strings.Split(line, " = ")
if len(parts) == 2 {
return strings.Trim(parts[1], "\""), nil
}
break
}
}
return "", errors.New("could not parse IOPlatformUUID")
}
type hostIDReaderLinux struct {
readFile fileReader
}
// read attempts to read the machine-id from /etc/machine-id followed by
// /var/lib/dbus/machine-id. If neither location yields an ID an error will
// be returned.
func (r *hostIDReaderLinux) read() (string, error) {
if result, err := r.readFile("/etc/machine-id"); err == nil {
return strings.TrimSpace(result), nil
}
if result, err := r.readFile("/var/lib/dbus/machine-id"); err == nil {
return strings.TrimSpace(result), nil
}
return "", errors.New("host id not found in: /etc/machine-id or /var/lib/dbus/machine-id")
}
type hostIDDetector struct{}
// Detect returns a *Resource containing the platform specific host id.
func (hostIDDetector) Detect(ctx context.Context) (*Resource, error) {
hostID, err := hostID()
if err != nil {
return nil, err
}
return NewWithAttributes(
semconv.SchemaURL,
semconv.HostID(hostID),
), nil
}

View file

@ -1,23 +0,0 @@
// 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.
//go:build dragonfly || freebsd || netbsd || openbsd || solaris
// +build dragonfly freebsd netbsd openbsd solaris
package resource // import "go.opentelemetry.io/otel/sdk/resource"
var platformHostIDReader hostIDReader = &hostIDReaderBSD{
execCommand: execCommand,
readFile: readFile,
}

View file

@ -1,19 +0,0 @@
// 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 resource // import "go.opentelemetry.io/otel/sdk/resource"
var platformHostIDReader hostIDReader = &hostIDReaderDarwin{
execCommand: execCommand,
}

View file

@ -1,29 +0,0 @@
// 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.
//go:build bsd || darwin
package resource // import "go.opentelemetry.io/otel/sdk/resource"
import "os/exec"
func execCommand(name string, arg ...string) (string, error) {
cmd := exec.Command(name, arg...)
b, err := cmd.Output()
if err != nil {
return "", err
}
return string(b), nil
}

View file

@ -1,22 +0,0 @@
// 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.
//go:build linux
// +build linux
package resource // import "go.opentelemetry.io/otel/sdk/resource"
var platformHostIDReader hostIDReader = &hostIDReaderLinux{
readFile: readFile,
}

View file

@ -1,28 +0,0 @@
// 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.
//go:build bsd || linux
package resource // import "go.opentelemetry.io/otel/sdk/resource"
import "os"
func readFile(filename string) (string, error) {
b, err := os.ReadFile(filename)
if err != nil {
return "", nil
}
return string(b), nil
}

View file

@ -1,36 +0,0 @@
// 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.
// +build !darwin
// +build !dragonfly
// +build !freebsd
// +build !linux
// +build !netbsd
// +build !openbsd
// +build !solaris
// +build !windows
package resource // import "go.opentelemetry.io/otel/sdk/resource"
// hostIDReaderUnsupported is a placeholder implementation for operating systems
// for which this project currently doesn't support host.id
// attribute detection. See build tags declaration early on this file
// for a list of unsupported OSes.
type hostIDReaderUnsupported struct{}
func (*hostIDReaderUnsupported) read() (string, error) {
return "<unknown>", nil
}
var platformHostIDReader hostIDReader = &hostIDReaderUnsupported{}

View file

@ -1,48 +0,0 @@
// 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.
//go:build windows
// +build windows
package resource // import "go.opentelemetry.io/otel/sdk/resource"
import (
"golang.org/x/sys/windows/registry"
)
// implements hostIDReader
type hostIDReaderWindows struct{}
// read reads MachineGuid from the windows registry key:
// SOFTWARE\Microsoft\Cryptography
func (*hostIDReaderWindows) read() (string, error) {
k, err := registry.OpenKey(
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`,
registry.QUERY_VALUE|registry.WOW64_64KEY,
)
if err != nil {
return "", err
}
defer k.Close()
guid, _, err := k.GetStringValue("MachineGuid")
if err != nil {
return "", err
}
return guid, nil
}
var platformHostIDReader hostIDReader = &hostIDReaderWindows{}

View file

@ -17,6 +17,7 @@ package resource // import "go.opentelemetry.io/otel/sdk/resource"
import (
"context"
"errors"
"fmt"
"sync"
"go.opentelemetry.io/otel"
@ -50,8 +51,17 @@ func New(ctx context.Context, opts ...Option) (*Resource, error) {
cfg = opt.apply(cfg)
}
r := &Resource{schemaURL: cfg.schemaURL}
return r, detect(ctx, r, cfg.detectors)
resource, err := Detect(ctx, cfg.detectors...)
var err2 error
resource, err2 = Merge(resource, &Resource{schemaURL: cfg.schemaURL})
if err == nil {
err = err2
} else if err2 != nil {
err = fmt.Errorf("detecting resources: %s", []string{err.Error(), err2.Error()})
}
return resource, err
}
// NewWithAttributes creates a resource from attrs and associates the resource with a

View file

@ -91,7 +91,7 @@ var _ SpanProcessor = (*batchSpanProcessor)(nil)
// NewBatchSpanProcessor creates a new SpanProcessor that will send completed
// span batches to the exporter with the supplied options.
//
// If the exporter is nil, the span processor will perform no action.
// If the exporter is nil, the span processor will preform no action.
func NewBatchSpanProcessor(exporter SpanExporter, options ...BatchSpanProcessorOption) SpanProcessor {
maxQueueSize := env.BatchSpanProcessorMaxQueueSize(DefaultMaxQueueSize)
maxExportBatchSize := env.BatchSpanProcessorMaxExportBatchSize(DefaultMaxExportBatchSize)

View file

@ -75,9 +75,8 @@ func (cfg tracerProviderConfig) MarshalLog() interface{} {
type TracerProvider struct {
mu sync.Mutex
namedTracer map[instrumentation.Scope]*tracer
spanProcessors atomic.Pointer[spanProcessorStates]
isShutdown atomic.Bool
spanProcessors atomic.Value
isShutdown bool
// These fields are not protected by the lock mu. They are assumed to be
// immutable after creation of the TracerProvider.
@ -120,11 +119,11 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
}
global.Info("TracerProvider created", "config", o)
spss := make(spanProcessorStates, 0, len(o.processors))
spss := spanProcessorStates{}
for _, sp := range o.processors {
spss = append(spss, newSpanProcessorState(sp))
}
tp.spanProcessors.Store(&spss)
tp.spanProcessors.Store(spss)
return tp
}
@ -137,11 +136,10 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
//
// This method is safe to be called concurrently.
func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
// This check happens before the mutex is acquired to avoid deadlocking if Tracer() is called from within Shutdown().
if p.isShutdown.Load() {
return trace.NewNoopTracerProvider().Tracer(name, opts...)
}
c := trace.NewTracerConfig(opts...)
p.mu.Lock()
defer p.mu.Unlock()
if name == "" {
name = defaultTracerName
}
@ -150,74 +148,44 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T
Version: c.InstrumentationVersion(),
SchemaURL: c.SchemaURL(),
}
t, ok := func() (trace.Tracer, bool) {
p.mu.Lock()
defer p.mu.Unlock()
// Must check the flag after acquiring the mutex to avoid returning a valid tracer if Shutdown() ran
// after the first check above but before we acquired the mutex.
if p.isShutdown.Load() {
return trace.NewNoopTracerProvider().Tracer(name, opts...), true
}
t, ok := p.namedTracer[is]
if !ok {
t = &tracer{
provider: p,
instrumentationScope: is,
}
p.namedTracer[is] = t
}
return t, ok
}()
t, ok := p.namedTracer[is]
if !ok {
// This code is outside the mutex to not hold the lock while calling third party logging code:
// - That code may do slow things like I/O, which would prolong the duration the lock is held,
// slowing down all tracing consumers.
// - Logging code may be instrumented with tracing and deadlock because it could try
// acquiring the same non-reentrant mutex.
global.Info("Tracer created", "name", name, "version", is.Version, "schemaURL", is.SchemaURL)
t = &tracer{
provider: p,
instrumentationScope: is,
}
p.namedTracer[is] = t
global.Info("Tracer created", "name", name, "version", c.InstrumentationVersion(), "schemaURL", c.SchemaURL())
}
return t
}
// RegisterSpanProcessor adds the given SpanProcessor to the list of SpanProcessors.
func (p *TracerProvider) RegisterSpanProcessor(sp SpanProcessor) {
// This check prevents calls during a shutdown.
if p.isShutdown.Load() {
return
}
p.mu.Lock()
defer p.mu.Unlock()
// This check prevents calls after a shutdown.
if p.isShutdown.Load() {
if p.isShutdown {
return
}
current := p.getSpanProcessors()
newSPS := make(spanProcessorStates, 0, len(current)+1)
newSPS = append(newSPS, current...)
newSPS := spanProcessorStates{}
newSPS = append(newSPS, p.spanProcessors.Load().(spanProcessorStates)...)
newSPS = append(newSPS, newSpanProcessorState(sp))
p.spanProcessors.Store(&newSPS)
p.spanProcessors.Store(newSPS)
}
// UnregisterSpanProcessor removes the given SpanProcessor from the list of SpanProcessors.
func (p *TracerProvider) UnregisterSpanProcessor(sp SpanProcessor) {
// This check prevents calls during a shutdown.
if p.isShutdown.Load() {
return
}
p.mu.Lock()
defer p.mu.Unlock()
// This check prevents calls after a shutdown.
if p.isShutdown.Load() {
if p.isShutdown {
return
}
old := p.getSpanProcessors()
old := p.spanProcessors.Load().(spanProcessorStates)
if len(old) == 0 {
return
}
spss := make(spanProcessorStates, len(old))
copy(spss, old)
spss := spanProcessorStates{}
spss = append(spss, old...)
// stop the span processor if it is started and remove it from the list
var stopOnce *spanProcessorState
@ -241,13 +209,13 @@ func (p *TracerProvider) UnregisterSpanProcessor(sp SpanProcessor) {
spss[len(spss)-1] = nil
spss = spss[:len(spss)-1]
p.spanProcessors.Store(&spss)
p.spanProcessors.Store(spss)
}
// ForceFlush immediately exports all spans that have not yet been exported for
// all the registered span processors.
func (p *TracerProvider) ForceFlush(ctx context.Context) error {
spss := p.getSpanProcessors()
spss := p.spanProcessors.Load().(spanProcessorStates)
if len(spss) == 0 {
return nil
}
@ -268,21 +236,18 @@ func (p *TracerProvider) ForceFlush(ctx context.Context) error {
// Shutdown shuts down TracerProvider. All registered span processors are shut down
// in the order they were registered and any held computational resources are released.
// After Shutdown is called, all methods are no-ops.
func (p *TracerProvider) Shutdown(ctx context.Context) error {
// This check prevents deadlocks in case of recursive shutdown.
if p.isShutdown.Load() {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
// This check prevents calls after a shutdown has already been done concurrently.
if !p.isShutdown.CompareAndSwap(false, true) { // did toggle?
spss := p.spanProcessors.Load().(spanProcessorStates)
if len(spss) == 0 {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
p.isShutdown = true
var retErr error
for _, sps := range p.getSpanProcessors() {
for _, sps := range spss {
select {
case <-ctx.Done():
return ctx.Err()
@ -302,14 +267,10 @@ func (p *TracerProvider) Shutdown(ctx context.Context) error {
}
}
}
p.spanProcessors.Store(&spanProcessorStates{})
p.spanProcessors.Store(spanProcessorStates{})
return retErr
}
func (p *TracerProvider) getSpanProcessors() spanProcessorStates {
return *(p.spanProcessors.Load())
}
// TracerProviderOption configures a TracerProvider.
type TracerProviderOption interface {
apply(tracerProviderConfig) tracerProviderConfig

View file

@ -19,13 +19,12 @@ import (
"sync"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/internal/global"
)
// simpleSpanProcessor is a SpanProcessor that synchronously sends all
// completed Spans to a trace.Exporter immediately.
type simpleSpanProcessor struct {
exporterMu sync.Mutex
exporterMu sync.RWMutex
exporter SpanExporter
stopOnce sync.Once
}
@ -44,8 +43,6 @@ func NewSimpleSpanProcessor(exporter SpanExporter) SpanProcessor {
ssp := &simpleSpanProcessor{
exporter: exporter,
}
global.Warn("SimpleSpanProcessor is not recommended for production use, consider using BatchSpanProcessor instead.")
return ssp
}
@ -54,8 +51,8 @@ func (ssp *simpleSpanProcessor) OnStart(context.Context, ReadWriteSpan) {}
// OnEnd immediately exports a ReadOnlySpan.
func (ssp *simpleSpanProcessor) OnEnd(s ReadOnlySpan) {
ssp.exporterMu.Lock()
defer ssp.exporterMu.Unlock()
ssp.exporterMu.RLock()
defer ssp.exporterMu.RUnlock()
if ssp.exporter != nil && s.SpanContext().TraceFlags().IsSampled() {
if err := ssp.exporter.ExportSpans(context.Background(), []ReadOnlySpan{s}); err != nil {

View file

@ -302,7 +302,7 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {
// most a length of limit. Each string slice value is truncated in this fashion
// (the slice length itself is unaffected).
//
// No truncation is performed for a negative limit.
// No truncation is perfromed for a negative limit.
func truncateAttr(limit int, attr attribute.KeyValue) attribute.KeyValue {
if limit < 0 {
return attr
@ -410,7 +410,7 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {
}
s.mu.Unlock()
sps := s.tracer.provider.getSpanProcessors()
sps := s.tracer.provider.spanProcessors.Load().(spanProcessorStates)
if len(sps) == 0 {
return
}

View file

@ -38,7 +38,7 @@ type SpanExporter interface {
// must never be done outside of a new major release.
// Shutdown notifies the exporter of a pending halt to operations. The
// exporter is expected to perform any cleanup or synchronization it
// exporter is expected to preform any cleanup or synchronization it
// requires while honoring all timeouts and cancellations contained in
// the passed context.
Shutdown(ctx context.Context) error

View file

@ -62,11 +62,11 @@ type SpanProcessor interface {
type spanProcessorState struct {
sp SpanProcessor
state sync.Once
state *sync.Once
}
func newSpanProcessorState(sp SpanProcessor) *spanProcessorState {
return &spanProcessorState{sp: sp}
return &spanProcessorState{sp: sp, state: &sync.Once{}}
}
type spanProcessorStates []*spanProcessorState

View file

@ -51,7 +51,7 @@ func (tr *tracer) Start(ctx context.Context, name string, options ...trace.SpanS
s := tr.newSpan(ctx, name, &config)
if rw, ok := s.(ReadWriteSpan); ok && s.IsRecording() {
sps := tr.provider.getSpanProcessors()
sps := tr.provider.spanProcessors.Load().(spanProcessorStates)
for _, sp := range sps {
sp.sp.OnStart(ctx, rw)
}

View file

@ -1,20 +0,0 @@
// 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 sdk // import "go.opentelemetry.io/otel/sdk"
// Version is the current release version of the OpenTelemetry SDK in use.
func Version() string {
return "1.15.1"
}