summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/tracing/tracerprovider.go
blob: 035425ed646972092c468c3da2ae17a1342d550b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package tracing

import (
	"context"
	"fmt"
	"sync"

	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	"go.uber.org/zap"
)

// globalTracerProvider stores global tracer provider and is responsible for graceful shutdown when nobody is using it.
var globalTracerProvider = &tracerProvider{}

type tracerProvider struct {
	mu                     sync.Mutex
	tracerProvider         *sdktrace.TracerProvider
	tracerProvidersCounter int
}

// getTracerProvider create or return an existing global TracerProvider
func (t *tracerProvider) getTracerProvider(opts ...sdktrace.TracerProviderOption) *sdktrace.TracerProvider {
	t.mu.Lock()
	defer t.mu.Unlock()

	t.tracerProvidersCounter++

	if t.tracerProvider == nil {
		t.tracerProvider = sdktrace.NewTracerProvider(
			opts...,
		)
	}

	return t.tracerProvider
}

// cleanupTracerProvider gracefully shutdown a TracerProvider
func (t *tracerProvider) cleanupTracerProvider(logger *zap.Logger) error {
	t.mu.Lock()
	defer t.mu.Unlock()

	if t.tracerProvidersCounter > 0 {
		t.tracerProvidersCounter--
	}

	if t.tracerProvidersCounter == 0 {
		if t.tracerProvider != nil {
			// tracerProvider.ForceFlush SHOULD be invoked according to https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#forceflush
			if err := t.tracerProvider.ForceFlush(context.Background()); err != nil {
				logger.Error("forcing flush", zap.Error(err))
			}

			// tracerProvider.Shutdown MUST be invoked according to https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#shutdown
			if err := t.tracerProvider.Shutdown(context.Background()); err != nil {
				return fmt.Errorf("tracerProvider shutdown error: %w", err)
			}
		}

		t.tracerProvider = nil
	}

	return nil
}