Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/plugins/log/fake.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package log

import "context"

var _ Logger = (*TestLogger)(nil)

type TestLogger struct {
Expand Down Expand Up @@ -41,6 +43,10 @@ func (f *TestLogger) Error(msg string, ctx ...any) {
f.ErrorLogs.Ctx = ctx
}

func (f *TestLogger) FromContext(_ context.Context) Logger {
return NewTestLogger()
}

type Logs struct {
Calls int
Message string
Expand Down
37 changes: 21 additions & 16 deletions pkg/plugins/log/ifaces.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
package log

import "context"

// Logger is the default logger
type Logger interface {
// New returns a new contextual Logger that has this logger's context plus the given context.
New(ctx ...interface{}) Logger
New(ctx ...any) Logger

// Debug logs a message with debug level and key/value pairs, if any.
Debug(msg string, ctx ...interface{})
Debug(msg string, ctx ...any)

// Info logs a message with info level and key/value pairs, if any.
Info(msg string, ctx ...interface{})
Info(msg string, ctx ...any)

// Warn logs a message with warning level and key/value pairs, if any.
Warn(msg string, ctx ...interface{})
Warn(msg string, ctx ...any)

// Error logs a message with error level and key/value pairs, if any.
Error(msg string, ctx ...interface{})
Error(msg string, ctx ...any)

// FromContext returns a new contextual Logger that has this logger's context plus the given context.
FromContext(ctx context.Context) Logger
}

// PrettyLogger is used primarily to facilitate logging/user feedback for both
// the grafana-cli and the grafana backend when managing plugin installs
type PrettyLogger interface {
Successf(format string, args ...interface{})
Failuref(format string, args ...interface{})

Info(args ...interface{})
Infof(format string, args ...interface{})
Debug(args ...interface{})
Debugf(format string, args ...interface{})
Warn(args ...interface{})
Warnf(format string, args ...interface{})
Error(args ...interface{})
Errorf(format string, args ...interface{})
Successf(format string, args ...any)
Failuref(format string, args ...any)

Info(args ...any)
Infof(format string, args ...any)
Debug(args ...any)
Debugf(format string, args ...any)
Warn(args ...any)
Warnf(format string, args ...any)
Error(args ...any)
Errorf(format string, args ...any)
}
12 changes: 12 additions & 0 deletions pkg/plugins/log/logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package log

import (
"context"

"github.com/grafana/grafana/pkg/infra/log"
)

Expand Down Expand Up @@ -42,3 +44,13 @@ func (d *grafanaInfraLogWrapper) Warn(msg string, ctx ...any) {
func (d *grafanaInfraLogWrapper) Error(msg string, ctx ...any) {
d.l.Error(msg, ctx...)
}

func (d *grafanaInfraLogWrapper) FromContext(ctx context.Context) Logger {
concreteInfraLogger, ok := d.l.FromContext(ctx).(*log.ConcreteLogger)
if !ok {
return d.New()
}
return &grafanaInfraLogWrapper{
l: concreteInfraLogger,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package clientmiddleware

import (
"context"

"github.com/grafana/grafana-plugin-sdk-go/backend"

"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
)

// NewContextualLoggerMiddleware creates a new plugins.ClientMiddleware that adds
// a contextual logger to the request context.
func NewContextualLoggerMiddleware() plugins.ClientMiddleware {
return plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
return &ContextualLoggerMiddleware{
next: next,
}
})
}

type ContextualLoggerMiddleware struct {
next plugins.Client
}

// instrumentContext adds a contextual logger with plugin and request details to the given context.
func instrumentContext(ctx context.Context, endpoint string, pCtx backend.PluginContext) context.Context {
p := []any{"endpoint", endpoint, "pluginId", pCtx.PluginID}
if pCtx.DataSourceInstanceSettings != nil {
p = append(p, "dsName", pCtx.DataSourceInstanceSettings.Name)
p = append(p, "dsUID", pCtx.DataSourceInstanceSettings.UID)
}
if pCtx.User != nil {
p = append(p, "uname", pCtx.User.Login)
}
return log.WithContextualAttributes(ctx, p)
}

func (m *ContextualLoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
ctx = instrumentContext(ctx, endpointQueryData, req.PluginContext)
return m.next.QueryData(ctx, req)
}

func (m *ContextualLoggerMiddleware) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
ctx = instrumentContext(ctx, endpointCallResource, req.PluginContext)
return m.next.CallResource(ctx, req, sender)
}

func (m *ContextualLoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
ctx = instrumentContext(ctx, endpointCheckHealth, req.PluginContext)
return m.next.CheckHealth(ctx, req)
}

func (m *ContextualLoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.CollectMetricsRequest) (*backend.CollectMetricsResult, error) {
ctx = instrumentContext(ctx, endpointCollectMetrics, req.PluginContext)
return m.next.CollectMetrics(ctx, req)
}

func (m *ContextualLoggerMiddleware) SubscribeStream(ctx context.Context, req *backend.SubscribeStreamRequest) (*backend.SubscribeStreamResponse, error) {
return m.next.SubscribeStream(ctx, req)
}

func (m *ContextualLoggerMiddleware) PublishStream(ctx context.Context, req *backend.PublishStreamRequest) (*backend.PublishStreamResponse, error) {
return m.next.PublishStream(ctx, req)
}

func (m *ContextualLoggerMiddleware) RunStream(ctx context.Context, req *backend.RunStreamRequest, sender *backend.StreamSender) error {
return m.next.RunStream(ctx, req, sender)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"time"

"github.com/grafana/grafana-plugin-sdk-go/backend"

"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/plugins"
plog "github.com/grafana/grafana/pkg/plugins/log"
"github.com/grafana/grafana/pkg/setting"
Expand All @@ -33,10 +33,11 @@ type LoggerMiddleware struct {
logger plog.Logger
}

func (m *LoggerMiddleware) logRequest(ctx context.Context, pluginCtx backend.PluginContext, endpoint string, fn func(ctx context.Context) error) error {
func (m *LoggerMiddleware) logRequest(ctx context.Context, fn func(ctx context.Context) error) error {
status := statusOK
start := time.Now()
timeBeforePluginRequest := log.TimeSinceStart(ctx, start)

err := fn(ctx)
if err != nil {
status = statusError
Expand All @@ -48,31 +49,13 @@ func (m *LoggerMiddleware) logRequest(ctx context.Context, pluginCtx backend.Plu
logParams := []any{
"status", status,
"duration", time.Since(start),
"pluginId", pluginCtx.PluginID,
"endpoint", endpoint,
"eventName", "grafana-data-egress",
"time_before_plugin_request", timeBeforePluginRequest,
}

if pluginCtx.User != nil {
logParams = append(logParams, "uname", pluginCtx.User.Login)
}

traceID := tracing.TraceIDFromContext(ctx, false)
if traceID != "" {
logParams = append(logParams, "traceID", traceID)
}

if pluginCtx.DataSourceInstanceSettings != nil {
logParams = append(logParams, "dsName", pluginCtx.DataSourceInstanceSettings.Name)
logParams = append(logParams, "dsUID", pluginCtx.DataSourceInstanceSettings.UID)
}

if status == statusError {
logParams = append(logParams, "error", err)
}

m.logger.Info("Plugin Request Completed", logParams...)
m.logger.FromContext(ctx).Info("Plugin Request Completed", logParams...)
return err
}

Expand All @@ -82,7 +65,7 @@ func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryData
}

var resp *backend.QueryDataResponse
err := m.logRequest(ctx, req.PluginContext, endpointQueryData, func(ctx context.Context) (innerErr error) {
err := m.logRequest(ctx, func(ctx context.Context) (innerErr error) {
resp, innerErr = m.next.QueryData(ctx, req)
return innerErr
})
Expand All @@ -95,7 +78,7 @@ func (m *LoggerMiddleware) CallResource(ctx context.Context, req *backend.CallRe
return m.next.CallResource(ctx, req, sender)
}

err := m.logRequest(ctx, req.PluginContext, endpointCallResource, func(ctx context.Context) (innerErr error) {
err := m.logRequest(ctx, func(ctx context.Context) (innerErr error) {
innerErr = m.next.CallResource(ctx, req, sender)
return innerErr
})
Expand All @@ -109,7 +92,7 @@ func (m *LoggerMiddleware) CheckHealth(ctx context.Context, req *backend.CheckHe
}

var resp *backend.CheckHealthResult
err := m.logRequest(ctx, req.PluginContext, endpointCheckHealth, func(ctx context.Context) (innerErr error) {
err := m.logRequest(ctx, func(ctx context.Context) (innerErr error) {
resp, innerErr = m.next.CheckHealth(ctx, req)
return innerErr
})
Expand All @@ -123,7 +106,7 @@ func (m *LoggerMiddleware) CollectMetrics(ctx context.Context, req *backend.Coll
}

var resp *backend.CollectMetricsResult
err := m.logRequest(ctx, req.PluginContext, endpointCollectMetrics, func(ctx context.Context) (innerErr error) {
err := m.logRequest(ctx, func(ctx context.Context) (innerErr error) {
resp, innerErr = m.next.CollectMetrics(ctx, req)
return innerErr
})
Expand Down
Loading
Loading