@@ -10,8 +10,12 @@ import (
10
10
"sync/atomic"
11
11
12
12
"go.opentelemetry.io/otel"
13
+ "go.opentelemetry.io/otel/attribute"
13
14
"go.opentelemetry.io/otel/internal/global"
15
+ "go.opentelemetry.io/otel/metric"
16
+ metricnoop "go.opentelemetry.io/otel/metric/noop"
14
17
"go.opentelemetry.io/otel/sdk/instrumentation"
18
+ "go.opentelemetry.io/otel/sdk/internal/x"
15
19
"go.opentelemetry.io/otel/sdk/resource"
16
20
"go.opentelemetry.io/otel/trace"
17
21
"go.opentelemetry.io/otel/trace/embedded"
@@ -79,6 +83,12 @@ type TracerProvider struct {
79
83
idGenerator IDGenerator
80
84
spanLimits SpanLimits
81
85
resource * resource.Resource
86
+
87
+ spanCreatedCount metric.Int64Counter
88
+ spanEndedCount metric.Int64Counter
89
+ spanLiveCount metric.Int64UpDownCounter
90
+ sampledAttributes metric.MeasurementOption
91
+ notSampledAttributes metric.MeasurementOption
82
92
}
83
93
84
94
var _ trace.TracerProvider = & TracerProvider {}
@@ -120,9 +130,55 @@ func NewTracerProvider(opts ...TracerProviderOption) *TracerProvider {
120
130
}
121
131
tp .spanProcessors .Store (& spss )
122
132
133
+ tp .configureSelfObservability ()
134
+
123
135
return tp
124
136
}
125
137
138
+ var providerID atomic.Uint64
139
+
140
+ // nextProviderID returns an identifier for this tracerprovider,
141
+ // starting with 0 and incrementing by 1 each time it is called.
142
+ func nextProviderID () int64 {
143
+ return int64 (providerID .Add (1 ) - 1 )
144
+ }
145
+
146
+ func (p * TracerProvider ) configureSelfObservability () {
147
+ mp := otel .GetMeterProvider ()
148
+ if ! x .SelfObservability .Enabled () {
149
+ mp = metric .MeterProvider (metricnoop .NewMeterProvider ())
150
+ }
151
+ meter := mp .Meter (
152
+ selfObsScopeName ,
153
+ metric .WithInstrumentationVersion (version ()),
154
+ )
155
+ componentNameAttr := attribute .String ("otel.sdk.component.name" , fmt .Sprintf ("tracer_provider/%d" , nextProviderID ()))
156
+ p .sampledAttributes = metric .WithAttributes (componentNameAttr , attribute .String ("otel.span.is_sampled" , "true" ))
157
+ p .notSampledAttributes = metric .WithAttributes (componentNameAttr , attribute .String ("otel.span.is_sampled" , "false" ))
158
+ var err error
159
+ p .spanCreatedCount , err = meter .Int64Counter ("otel.sdk.span.created_count" ,
160
+ metric .WithUnit ("{span}" ),
161
+ metric .WithDescription ("The number of spans which have been created." ),
162
+ )
163
+ if err != nil {
164
+ otel .Handle (err )
165
+ }
166
+ p .spanEndedCount , err = meter .Int64Counter ("otel.sdk.span.ended_count" ,
167
+ metric .WithUnit ("{span}" ),
168
+ metric .WithDescription ("The number of created spans for which the end operation was called." ),
169
+ )
170
+ if err != nil {
171
+ otel .Handle (err )
172
+ }
173
+ p .spanLiveCount , err = meter .Int64UpDownCounter ("otel.sdk.span.live_count" ,
174
+ metric .WithUnit ("{span}" ),
175
+ metric .WithDescription ("The number of created spans for which the end operation has not been called yet." ),
176
+ )
177
+ if err != nil {
178
+ otel .Handle (err )
179
+ }
180
+ }
181
+
126
182
// Tracer returns a Tracer with the given name and options. If a Tracer for
127
183
// the given name and options does not exist it is created, otherwise the
128
184
// existing Tracer is returned.
0 commit comments