@@ -5,17 +5,19 @@ import (
5
5
"net/http"
6
6
"net/http/pprof"
7
7
"os"
8
+ "strconv"
8
9
9
10
"go.opentelemetry.io/otel"
10
11
"go.opentelemetry.io/otel/attribute"
11
12
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
12
13
14
+ "github.com/grafana/grafana-plugin-sdk-go/backend/log"
13
15
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
14
16
"github.com/grafana/grafana-plugin-sdk-go/build"
15
17
"github.com/grafana/grafana-plugin-sdk-go/internal/tracerprovider"
16
18
)
17
19
18
- var (
20
+ const (
19
21
// PluginProfilerEnvDeprecated is a deprecated constant for the GF_PLUGINS_PROFILER environment variable used to enable pprof.
20
22
PluginProfilerEnvDeprecated = "GF_PLUGINS_PROFILER"
21
23
// PluginProfilingEnabledEnv is a constant for the GF_PLUGIN_PROFILING_ENABLED environment variable used to enable pprof.
@@ -27,15 +29,33 @@ var (
27
29
PluginProfilingPortEnv = "GF_PLUGIN_PROFILING_PORT" // nolint:gosec
28
30
29
31
// PluginTracingOpenTelemetryOTLPAddressEnv is a constant for the GF_INSTANCE_OTLP_ADDRESS
30
- // environment variable used to specify the OTLP Address .
32
+ // environment variable used to specify the OTLP address .
31
33
PluginTracingOpenTelemetryOTLPAddressEnv = "GF_INSTANCE_OTLP_ADDRESS" // nolint:gosec
32
34
// PluginTracingOpenTelemetryOTLPPropagationEnv is a constant for the GF_INSTANCE_OTLP_PROPAGATION
33
35
// environment variable used to specify the OTLP propagation format.
34
36
PluginTracingOpenTelemetryOTLPPropagationEnv = "GF_INSTANCE_OTLP_PROPAGATION"
35
37
38
+ // PluginTracingSamplerTypeEnv is a constant for the GF_INSTANCE_OTLP_SAMPLER_TYPE
39
+ // environment variable used to specify the OTLP sampler type.
40
+ PluginTracingSamplerTypeEnv = "GF_INSTANCE_OTLP_SAMPLER_TYPE"
41
+
42
+ // PluginTracingSamplerParamEnv is a constant for the GF_INSTANCE_OTLP_SAMPLER_PARAM
43
+ // environment variable used to specify an additional float parameter used by the OTLP sampler,
44
+ // depending on the type.
45
+ PluginTracingSamplerParamEnv = "GF_INSTANCE_OTLP_SAMPLER_PARAM"
46
+
47
+ // PluginTracingSamplerRemoteURL is a constant for the GF_INSTANCE_OTLP_SAMPLER_REMOTE_URL
48
+ // environment variable used to specify the remote url for the sampler type. This is relevant
49
+ // only when GF_INSTANCE_OTLP_SAMPLER_TYPE is "remote".
50
+ PluginTracingSamplerRemoteURL = "GF_INSTANCE_OTLP_SAMPLER_REMOTE_URL"
51
+
36
52
// PluginVersionEnv is a constant for the GF_PLUGIN_VERSION environment variable containing the plugin's version.
37
53
// Deprecated: Use build.GetBuildInfo().Version instead.
38
54
PluginVersionEnv = "GF_PLUGIN_VERSION"
55
+
56
+ // defaultRemoteSamplerServiceName is the default service name passed to the remote sampler when it cannot be
57
+ // determined from the build info.
58
+ defaultRemoteSamplerServiceName = "grafana-plugin"
39
59
)
40
60
41
61
// SetupPluginEnvironment will read the environment variables and apply the
@@ -117,17 +137,17 @@ func getTracerCustomAttributes(pluginID string) []attribute.KeyValue {
117
137
// SetupTracer sets up the global OTEL trace provider and tracer.
118
138
func SetupTracer (pluginID string , tracingOpts tracing.Opts ) error {
119
139
// Set up tracing
120
- tracingCfg := getTracingConfig ()
121
- if tracingCfg .IsEnabled () {
140
+ tracingCfg := getTracingConfig (build . GetBuildInfo )
141
+ if tracingCfg .isEnabled () {
122
142
// Append custom attributes to the default ones
123
143
tracingOpts .CustomAttributes = append (getTracerCustomAttributes (pluginID ), tracingOpts .CustomAttributes ... )
124
144
125
145
// Initialize global tracer provider
126
- tp , err := tracerprovider .NewTracerProvider (tracingCfg .Address , tracingOpts )
146
+ tp , err := tracerprovider .NewTracerProvider (tracingCfg .address , tracingCfg . sampler , tracingOpts )
127
147
if err != nil {
128
148
return fmt .Errorf ("new trace provider: %w" , err )
129
149
}
130
- pf , err := tracerprovider .NewTextMapPropagator (tracingCfg .Propagation )
150
+ pf , err := tracerprovider .NewTextMapPropagator (tracingCfg .propagation )
131
151
if err != nil {
132
152
return fmt .Errorf ("new propagator format: %w" , err )
133
153
}
@@ -136,30 +156,90 @@ func SetupTracer(pluginID string, tracingOpts tracing.Opts) error {
136
156
// Initialize global tracer for plugin developer usage
137
157
tracing .InitDefaultTracer (otel .Tracer (pluginID ))
138
158
}
139
- Logger .Debug ("Tracing" , "enabled" , tracingCfg .IsEnabled (), "propagation" , tracingCfg .Propagation )
159
+
160
+ enabled := tracingCfg .isEnabled ()
161
+ Logger .Debug ("Tracing" , "enabled" , enabled )
162
+ if enabled {
163
+ Logger .Debug (
164
+ "Tracing configuration" ,
165
+ "propagation" , tracingCfg .propagation ,
166
+ "samplerType" , tracingCfg .sampler .SamplerType ,
167
+ "samplerParam" , tracingCfg .sampler .Param ,
168
+ "samplerRemoteURL" , tracingCfg .sampler .Remote .URL ,
169
+ "samplerRemoteServiceName" , tracingCfg .sampler .Remote .ServiceName ,
170
+ )
171
+ }
140
172
return nil
141
173
}
142
174
143
175
// tracingConfig contains the configuration for OTEL tracing.
144
176
type tracingConfig struct {
145
- Address string
146
- Propagation string
177
+ address string
178
+ propagation string
179
+
180
+ sampler tracerprovider.SamplerOptions
147
181
}
148
182
149
- // IsEnabled returns true if OTEL tracing is enabled.
150
- func (c tracingConfig ) IsEnabled () bool {
151
- return c .Address != ""
183
+ // isEnabled returns true if OTEL tracing is enabled.
184
+ func (c tracingConfig ) isEnabled () bool {
185
+ return c .address != ""
152
186
}
153
187
154
188
// getTracingConfig returns a new tracingConfig based on the current environment variables.
155
- func getTracingConfig () tracingConfig {
156
- var otelAddr , otelPropagation string
189
+ func getTracingConfig (buildInfoGetter build.InfoGetter ) tracingConfig {
190
+ var otelAddr , otelPropagation , samplerRemoteURL , samplerParamString string
191
+ var samplerType tracerprovider.SamplerType
192
+ var samplerParam float64
157
193
otelAddr , ok := os .LookupEnv (PluginTracingOpenTelemetryOTLPAddressEnv )
158
194
if ok {
195
+ // Additional OTEL config
159
196
otelPropagation = os .Getenv (PluginTracingOpenTelemetryOTLPPropagationEnv )
197
+
198
+ // Sampling config
199
+ samplerType = tracerprovider .SamplerType (os .Getenv (PluginTracingSamplerTypeEnv ))
200
+ samplerRemoteURL = os .Getenv (PluginTracingSamplerRemoteURL )
201
+ samplerParamString = os .Getenv (PluginTracingSamplerParamEnv )
202
+ var err error
203
+ samplerParam , err = strconv .ParseFloat (samplerParamString , 64 )
204
+ if err != nil {
205
+ // Default value if invalid float is provided is 1.0 (AlwaysSample)
206
+ log .DefaultLogger .Warn (
207
+ "Could not parse sampler param to float, defaulting to 1.0" ,
208
+ "samplerParam" , samplerParamString , "error" , err ,
209
+ )
210
+ samplerParam = 1.0
211
+ }
212
+ }
213
+ var serviceName string
214
+ if samplerType == tracerprovider .SamplerTypeRemote {
215
+ serviceName = remoteSamplerServiceName (buildInfoGetter )
160
216
}
161
217
return tracingConfig {
162
- Address : otelAddr ,
163
- Propagation : otelPropagation ,
218
+ address : otelAddr ,
219
+ propagation : otelPropagation ,
220
+ sampler : tracerprovider.SamplerOptions {
221
+ SamplerType : samplerType ,
222
+ Param : samplerParam ,
223
+ Remote : tracerprovider.RemoteSamplerOptions {
224
+ URL : samplerRemoteURL ,
225
+ ServiceName : serviceName ,
226
+ },
227
+ },
228
+ }
229
+ }
230
+
231
+ // remoteSamplerServiceName returns the service name for the remote tracing sampler.
232
+ // It attempts to get it from the provided buildinfo getter. If unsuccessful or empty,
233
+ // defaultRemoteSamplerServiceName is returned instead.
234
+ func remoteSamplerServiceName (buildInfoGetter build.InfoGetter ) string {
235
+ // Use plugin id as service name, if possible. Otherwise, use a generic default value.
236
+ bi , err := buildInfoGetter .GetInfo ()
237
+ if err != nil {
238
+ log .DefaultLogger .Warn ("Could not get build info for remote sampler service name" , "error" , err )
239
+ return defaultRemoteSamplerServiceName
240
+ }
241
+ if bi .PluginID == "" {
242
+ return defaultRemoteSamplerServiceName
164
243
}
244
+ return bi .PluginID
165
245
}
0 commit comments