ref: pass tracer to plugin factory func (#93701)
* ref: pass tracer to plugin factory func * fix: add tracer to coreplugin * test: fix test, generate wire * test: ignore trace field in loader_test * ref: pass tracer as dependency, don't store in plugin * ref: wrap tracer with tracer provider to satisfy WithTracerProvider * ref: use otel trace.Tracer type for tracer
This commit is contained in:
@@ -3,7 +3,8 @@ package backendplugin
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// PluginFactoryFunc is a function type for creating a Plugin.
|
||||
type PluginFactoryFunc func(pluginID string, logger log.Logger, env func() []string) (Plugin, error)
|
||||
type PluginFactoryFunc func(pluginID string, logger log.Logger, tracer trace.Tracer, env func() []string) (Plugin, error)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
@@ -24,7 +25,7 @@ type corePlugin struct {
|
||||
|
||||
// New returns a new backendplugin.PluginFactoryFunc for creating a core (built-in) backendplugin.Plugin.
|
||||
func New(opts backend.ServeOpts) backendplugin.PluginFactoryFunc {
|
||||
return func(pluginID string, logger log.Logger, _ func() []string) (backendplugin.Plugin, error) {
|
||||
return func(pluginID string, logger log.Logger, _ trace.Tracer, _ func() []string) (backendplugin.Plugin, error) {
|
||||
return &corePlugin{
|
||||
pluginID: pluginID,
|
||||
logger: logger,
|
||||
|
||||
@@ -8,13 +8,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin/coreplugin"
|
||||
"github.com/grafana/grafana/pkg/plugins/log"
|
||||
"github.com/grafana/grafana/pkg/plugins/manager/fakes"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCorePlugin(t *testing.T) {
|
||||
t.Run("New core plugin with empty opts should return expected values", func(t *testing.T) {
|
||||
factory := coreplugin.New(backend.ServeOpts{})
|
||||
p, err := factory("plugin", log.New("test"), nil)
|
||||
p, err := factory("plugin", log.New("test"), fakes.InitializeNoopTracerForTest(), nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NoError(t, p.Start(context.Background()))
|
||||
@@ -47,7 +48,7 @@ func TestCorePlugin(t *testing.T) {
|
||||
return nil
|
||||
}),
|
||||
})
|
||||
p, err := factory("plugin", log.New("test"), nil)
|
||||
p, err := factory("plugin", log.New("test"), fakes.InitializeNoopTracerForTest(), nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, p)
|
||||
require.NoError(t, p.Start(context.Background()))
|
||||
|
||||
@@ -254,7 +254,7 @@ func NewPlugin(pluginID string, cfg *setting.Cfg, httpClientProvider *httpclient
|
||||
if backendFactory == nil {
|
||||
return nil, ErrCorePluginNotFound
|
||||
}
|
||||
bp, err := backendFactory(p.ID, p.Logger(), nil)
|
||||
bp, err := backendFactory(p.ID, p.Logger(), tracer, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/grpcplugin"
|
||||
goplugin "github.com/hashicorp/go-plugin"
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
trace "go.opentelemetry.io/otel/trace"
|
||||
"go.opentelemetry.io/otel/trace/embedded"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
@@ -40,7 +42,20 @@ var pluginSet = map[int]goplugin.PluginSet{
|
||||
},
|
||||
}
|
||||
|
||||
func newClientConfig(executablePath string, args []string, env []string, skipHostEnvVars bool, logger log.Logger,
|
||||
type clientTracerProvider struct {
|
||||
tracer trace.Tracer
|
||||
embedded.TracerProvider
|
||||
}
|
||||
|
||||
func (ctp *clientTracerProvider) Tracer(instrumentationName string, opts ...trace.TracerOption) trace.Tracer {
|
||||
return ctp.tracer
|
||||
}
|
||||
|
||||
func newClientTracerProvider(tracer trace.Tracer) trace.TracerProvider {
|
||||
return &clientTracerProvider{tracer: tracer}
|
||||
}
|
||||
|
||||
func newClientConfig(executablePath string, args []string, env []string, skipHostEnvVars bool, logger log.Logger, tracer trace.Tracer,
|
||||
versionedPlugins map[int]goplugin.PluginSet) *goplugin.ClientConfig {
|
||||
// We can ignore gosec G201 here, since the dynamic part of executablePath comes from the plugin definition
|
||||
// nolint:gosec
|
||||
@@ -55,7 +70,13 @@ func newClientConfig(executablePath string, args []string, env []string, skipHos
|
||||
Logger: logWrapper{Logger: logger},
|
||||
AllowedProtocols: []goplugin.Protocol{goplugin.ProtocolGRPC},
|
||||
GRPCDialOptions: []grpc.DialOption{
|
||||
grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
|
||||
// https://github.com/grafana/app-platform-wg/issues/140
|
||||
// external plugins are loaded before k8s API server
|
||||
// configures the tracing service thus failing to
|
||||
// record trace span in the middleware.
|
||||
// With code below we are passing the same tracer that k8s API server
|
||||
// uses so that middleware is configured with tracer.
|
||||
grpc.WithStatsHandler(otelgrpc.NewClientHandler(otelgrpc.WithTracerProvider(newClientTracerProvider(tracer)))),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
trace "go.opentelemetry.io/otel/trace"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/genproto/pluginv2"
|
||||
@@ -44,6 +45,7 @@ type ProtoClientOpts struct {
|
||||
ExecutableArgs []string
|
||||
Env []string
|
||||
Logger log.Logger
|
||||
Tracer trace.Tracer
|
||||
}
|
||||
|
||||
func NewProtoClient(opts ProtoClientOpts) (ProtoClient, error) {
|
||||
@@ -56,6 +58,7 @@ func NewProtoClient(opts ProtoClientOpts) (ProtoClient, error) {
|
||||
versionedPlugins: pluginSet,
|
||||
},
|
||||
opts.Logger,
|
||||
opts.Tracer,
|
||||
func() []string { return opts.Env },
|
||||
)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
trace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/process"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
@@ -37,17 +38,17 @@ const (
|
||||
|
||||
// newPlugin allocates and returns a new gRPC (external) backendplugin.Plugin.
|
||||
func newPlugin(descriptor PluginDescriptor) backendplugin.PluginFactoryFunc {
|
||||
return func(pluginID string, logger log.Logger, env func() []string) (backendplugin.Plugin, error) {
|
||||
return newGrpcPlugin(descriptor, logger, env), nil
|
||||
return func(pluginID string, logger log.Logger, tracer trace.Tracer, env func() []string) (backendplugin.Plugin, error) {
|
||||
return newGrpcPlugin(descriptor, logger, tracer, env), nil
|
||||
}
|
||||
}
|
||||
|
||||
func newGrpcPlugin(descriptor PluginDescriptor, logger log.Logger, env func() []string) *grpcPlugin {
|
||||
func newGrpcPlugin(descriptor PluginDescriptor, logger log.Logger, tracer trace.Tracer, env func() []string) *grpcPlugin {
|
||||
return &grpcPlugin{
|
||||
descriptor: descriptor,
|
||||
logger: logger,
|
||||
clientFactory: func() *plugin.Client {
|
||||
return plugin.NewClient(newClientConfig(descriptor.executablePath, descriptor.executableArgs, env(), descriptor.skipHostEnvVars, logger, descriptor.versionedPlugins))
|
||||
return plugin.NewClient(newClientConfig(descriptor.executablePath, descriptor.executableArgs, env(), descriptor.skipHostEnvVars, logger, tracer, descriptor.versionedPlugins))
|
||||
},
|
||||
state: pluginStateNotStarted,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user