fix: don't record metrics for plugin calls that aren't implemented at all

Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
Deluan 2026-01-12 23:46:38 -05:00
parent 2006474507
commit 57d606450e
4 changed files with 17 additions and 16 deletions

View File

@ -79,6 +79,7 @@ var _ = Describe("SchedulerService", Ordered, func() {
plugins: make(map[string]*plugin),
ds: dataStore,
subsonicRouter: http.NotFoundHandler(),
metrics: noopMetricsRecorder{},
}
err = manager.Start(GinkgoT().Context())
Expect(err).ToNot(HaveOccurred())

View File

@ -71,6 +71,7 @@ var _ = Describe("WebSocketService", Ordered, func() {
plugins: make(map[string]*plugin),
ds: dataStore,
subsonicRouter: http.NotFoundHandler(),
metrics: noopMetricsRecorder{},
}
err = manager.Start(GinkgoT().Context())
Expect(err).ToNot(HaveOccurred())

View File

@ -59,42 +59,35 @@ func callPluginFunction[I any, O any](ctx context.Context, plugin *plugin, funcN
startCall := time.Now()
exit, output, err := p.CallWithContext(ctx, funcName, inputBytes)
elapsed := time.Since(startCall)
if err != nil {
elapsed := time.Since(startCall).Milliseconds()
// If context was cancelled, return that error instead of the plugin error
if ctx.Err() != nil {
log.Debug(ctx, "Plugin call cancelled", "plugin", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall))
log.Debug(ctx, "Plugin call cancelled", "plugin", plugin.name, "function", funcName, "pluginDuration", elapsed)
return result, ctx.Err()
}
if plugin.metrics != nil {
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, false, elapsed)
}
log.Trace(ctx, "Plugin call failed", "plugin", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall), "navidromeDuration", startCall.Sub(start), err)
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, false, elapsed.Milliseconds())
log.Trace(ctx, "Plugin call failed", "plugin", plugin.name, "function", funcName, "pluginDuration", elapsed, "navidromeDuration", startCall.Sub(start), err)
return result, fmt.Errorf("plugin call failed: %w", err)
}
if exit != 0 {
elapsed := time.Since(startCall).Milliseconds()
if plugin.metrics != nil {
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, false, elapsed)
}
if exit == notImplementedCode {
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, false, elapsed.Milliseconds())
return result, fmt.Errorf("%w: %s", errNotImplemented, funcName)
}
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, false, elapsed.Milliseconds())
return result, fmt.Errorf("plugin call exited with code %d", exit)
}
if len(output) > 0 {
err = json.Unmarshal(output, &result)
if err != nil {
log.Trace(ctx, "Plugin call failed", "plugin", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall), "navidromeDuration", startCall.Sub(start), err)
log.Trace(ctx, "Plugin call failed", "plugin", plugin.name, "function", funcName, "pluginDuration", elapsed, "navidromeDuration", startCall.Sub(start), err)
}
}
// Record metrics for successful calls (or JSON unmarshal failures)
if plugin.metrics != nil {
elapsed := time.Since(startCall).Milliseconds()
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, err == nil, elapsed)
}
plugin.metrics.RecordPluginRequest(ctx, plugin.name, funcName, err == nil, elapsed.Milliseconds())
log.Trace(ctx, "Plugin call succeeded", "plugin", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall), "navidromeDuration", startCall.Sub(start))
return result, err

View File

@ -3,6 +3,7 @@
package plugins
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
@ -61,7 +62,7 @@ func createTestManager(pluginConfig map[string]map[string]string) (*Manager, str
// and specified plugins. It creates a temp directory, copies the specified plugins, and starts the manager.
// Returns the manager and temp directory path.
func createTestManagerWithPlugins(pluginConfig map[string]map[string]string, plugins ...string) (*Manager, string) {
return createTestManagerWithPluginsAndMetrics(pluginConfig, nil, plugins...)
return createTestManagerWithPluginsAndMetrics(pluginConfig, noopMetricsRecorder{}, plugins...)
}
// createTestManagerWithPluginsAndMetrics creates a new plugin Manager with the given plugin config,
@ -155,3 +156,8 @@ var _ = AfterSuite(func() {
_ = os.RemoveAll(tmpPluginsDir)
}
})
// noopMetricsRecorder is a no-op implementation of PluginMetricsRecorder for tests
type noopMetricsRecorder struct{}
func (noopMetricsRecorder) RecordPluginRequest(context.Context, string, string, bool, int64) {}