Plugins: Add tracing to pipeline (#115448)

This commit is contained in:
Todd Treece
2025-12-17 09:08:17 -05:00
committed by GitHub
parent af85563527
commit 33e53db53a
13 changed files with 168 additions and 13 deletions
@@ -3,11 +3,16 @@ package bootstrap
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/plugins/manager/signature"
"github.com/grafana/grafana/pkg/plugins/pluginassets"
"github.com/grafana/grafana/pkg/semconv"
)
// Bootstrapper is responsible for the Bootstrap stage of the plugin loader pipeline.
@@ -34,6 +39,7 @@ type Bootstrap struct {
constructStep ConstructFunc
decorateSteps []DecorateFunc
log log.Logger
tracer trace.Tracer
}
type Opts struct {
@@ -55,14 +61,21 @@ func New(cfg *config.PluginManagementCfg, opts Opts) *Bootstrap {
constructStep: opts.ConstructFunc,
decorateSteps: opts.DecorateFuncs,
log: log.New("plugins.bootstrap"),
tracer: otel.Tracer("github.com/grafana/grafana/pkg/plugins/manager/pipeline/bootstrap"),
}
}
// Bootstrap will execute the Construct and Decorate steps of the Bootstrap stage.
func (b *Bootstrap) Bootstrap(ctx context.Context, src plugins.PluginSource, found *plugins.FoundBundle) ([]*plugins.Plugin, error) {
pluginClass := src.PluginClass(ctx)
ctx, span := b.tracer.Start(ctx, "bootstrap.Bootstrap", trace.WithAttributes(
semconv.PluginSourceClass(pluginClass),
))
defer span.End()
ps, err := b.constructStep(ctx, src, found)
if err != nil {
return nil, err
return nil, tracing.Error(span, err)
}
if len(b.decorateSteps) == 0 {
@@ -76,7 +89,7 @@ func (b *Bootstrap) Bootstrap(ctx context.Context, src plugins.PluginSource, fou
ip, err = decorate(ctx, p)
if err != nil {
b.log.Error("Could not decorate plugin", "pluginId", p.ID, "error", err)
return nil, err
return nil, tracing.Error(span, err)
}
}
bootstrappedPlugins = append(bootstrappedPlugins, ip)
@@ -3,6 +3,11 @@ package discovery
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
@@ -26,6 +31,7 @@ type FilterFunc func(ctx context.Context, class plugins.Class, bundles []*plugin
type Discovery struct {
filterSteps []FilterFunc
log log.Logger
tracer trace.Tracer
}
type Opts struct {
@@ -41,29 +47,37 @@ func New(_ *config.PluginManagementCfg, opts Opts) *Discovery {
return &Discovery{
filterSteps: opts.FilterFuncs,
log: log.New("plugins.discovery"),
tracer: otel.Tracer("github.com/grafana/grafana/pkg/plugins/manager/pipeline/discovery"),
}
}
// Discover will execute the Filter step of the Discovery stage.
func (d *Discovery) Discover(ctx context.Context, src plugins.PluginSource) ([]*plugins.FoundBundle, error) {
pluginClass := src.PluginClass(ctx)
ctx, span := d.tracer.Start(ctx, "discovery.Discover", trace.WithAttributes(
attribute.String("grafana.plugins.class", string(pluginClass)),
))
defer span.End()
ctxLogger := d.log.FromContext(ctx)
// Use the source's own Discover method
found, err := src.Discover(ctx)
if err != nil {
d.log.Warn("Discovery source failed", "class", src.PluginClass(ctx), "error", err)
return nil, err
ctxLogger.Warn("Discovery source failed", "class", pluginClass, "error", err)
return nil, tracing.Error(span, err)
}
d.log.Debug("Found plugins", "class", src.PluginClass(ctx), "count", len(found))
ctxLogger.Debug("Found plugins", "class", pluginClass, "count", len(found))
// Apply filtering steps
result := found
for _, filter := range d.filterSteps {
result, err = filter(ctx, src.PluginClass(ctx), result)
if err != nil {
return nil, err
return nil, tracing.Error(span, err)
}
}
d.log.Debug("Discovery complete", "class", src.PluginClass(ctx), "found", len(found), "filtered", len(result))
ctxLogger.Debug("Discovery complete", "class", pluginClass, "found", len(found), "filtered", len(result))
return result, nil
}
@@ -3,9 +3,14 @@ package initialization
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/semconv"
)
// Initializer is responsible for the Initialization stage of the plugin loader pipeline.
@@ -20,6 +25,7 @@ type Initialize struct {
cfg *config.PluginManagementCfg
initializeSteps []InitializeFunc
log log.Logger
tracer trace.Tracer
}
type Opts struct {
@@ -36,11 +42,17 @@ func New(cfg *config.PluginManagementCfg, opts Opts) *Initialize {
cfg: cfg,
initializeSteps: opts.InitializeFuncs,
log: log.New("plugins.initialization"),
tracer: otel.Tracer("github.com/grafana/grafana/pkg/plugins/manager/pipeline/initialization"),
}
}
// Initialize will execute the Initialize steps of the Initialization stage.
func (i *Initialize) Initialize(ctx context.Context, ps *plugins.Plugin) (*plugins.Plugin, error) {
ctx, span := i.tracer.Start(ctx, "initialization.Initialize", trace.WithAttributes(
semconv.GrafanaPluginId(ps.ID),
))
defer span.End()
if len(i.initializeSteps) == 0 {
return ps, nil
}
@@ -51,7 +63,7 @@ func (i *Initialize) Initialize(ctx context.Context, ps *plugins.Plugin) (*plugi
ip, err = init(ctx, ps)
if err != nil {
i.log.Error("Could not initialize plugin", "pluginId", ps.ID, "error", err)
return nil, err
return nil, tracing.Error(span, err)
}
}
@@ -3,9 +3,14 @@ package termination
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/semconv"
)
// Terminator is responsible for the Termination stage of the plugin loader pipeline.
@@ -20,6 +25,7 @@ type Terminate struct {
cfg *config.PluginManagementCfg
terminateSteps []TerminateFunc
log log.Logger
tracer trace.Tracer
}
type Opts struct {
@@ -36,14 +42,20 @@ func New(cfg *config.PluginManagementCfg, opts Opts) (*Terminate, error) {
cfg: cfg,
terminateSteps: opts.TerminateFuncs,
log: log.New("plugins.termination"),
tracer: otel.Tracer("github.com/grafana/grafana/pkg/plugins/manager/pipeline/termination"),
}, nil
}
// Terminate will execute the Terminate steps of the Termination stage.
func (t *Terminate) Terminate(ctx context.Context, p *plugins.Plugin) (*plugins.Plugin, error) {
ctx, span := t.tracer.Start(ctx, "termination.Terminate", trace.WithAttributes(
semconv.GrafanaPluginId(p.ID),
))
defer span.End()
for _, terminate := range t.terminateSteps {
if err := terminate(ctx, p); err != nil {
return nil, err
return nil, tracing.Error(span, err)
}
}
return p, nil
@@ -3,9 +3,14 @@ package validation
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/trace"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/config"
"github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/semconv"
)
// Validator is responsible for the Validation stage of the plugin loader pipeline.
@@ -20,6 +25,7 @@ type Validate struct {
cfg *config.PluginManagementCfg
validateSteps []ValidateFunc
log log.Logger
tracer trace.Tracer
}
type Opts struct {
@@ -36,11 +42,17 @@ func New(cfg *config.PluginManagementCfg, opts Opts) *Validate {
cfg: cfg,
validateSteps: opts.ValidateFuncs,
log: log.New("plugins.validation"),
tracer: otel.Tracer("github.com/grafana/grafana/pkg/plugins/manager/pipeline/validation"),
}
}
// Validate will execute the Validate steps of the Validation stage.
func (v *Validate) Validate(ctx context.Context, ps *plugins.Plugin) error {
ctx, span := v.tracer.Start(ctx, "validation.Validate", trace.WithAttributes(
semconv.GrafanaPluginId(ps.ID),
))
defer span.End()
if len(v.validateSteps) == 0 {
return nil
}
@@ -49,7 +61,7 @@ func (v *Validate) Validate(ctx context.Context, ps *plugins.Plugin) error {
err := validate(ctx, ps)
if err != nil {
v.log.Error("Plugin validation failed", "pluginId", ps.ID, "error", err)
return err
return tracing.Error(span, err)
}
}