mirror of
https://github.com/navidrome/navidrome.git
synced 2026-08-01 07:21:17 +00:00
feat(plugins): integrate logs
Signed-off-by: Deluan <deluan@navidrome.org>
This commit is contained in:
parent
905cd613f3
commit
415eac5399
@ -230,6 +230,7 @@ type pluginsOptions struct {
|
||||
Folder string
|
||||
CacheSize string
|
||||
AutoReload bool
|
||||
LogLevel string
|
||||
}
|
||||
|
||||
type extAuthOptions struct {
|
||||
|
||||
20
log/log.go
20
log/log.go
@ -88,11 +88,11 @@ func SetLevel(l Level) {
|
||||
}
|
||||
|
||||
func SetLevelString(l string) {
|
||||
level := levelFromString(l)
|
||||
level := ParseLogLevel(l)
|
||||
SetLevel(level)
|
||||
}
|
||||
|
||||
func levelFromString(l string) Level {
|
||||
func ParseLogLevel(l string) Level {
|
||||
envLevel := strings.ToLower(l)
|
||||
var level Level
|
||||
switch envLevel {
|
||||
@ -118,7 +118,7 @@ func SetLogLevels(levels map[string]string) {
|
||||
defer loggerMu.Unlock()
|
||||
logLevels = nil
|
||||
for k, v := range levels {
|
||||
logLevels = append(logLevels, levelPath{path: k, level: levelFromString(v)})
|
||||
logLevels = append(logLevels, levelPath{path: k, level: ParseLogLevel(v)})
|
||||
}
|
||||
sort.Slice(logLevels, func(i, j int) bool {
|
||||
return logLevels[i].path > logLevels[j].path
|
||||
@ -185,31 +185,31 @@ func IsGreaterOrEqualTo(level Level) bool {
|
||||
}
|
||||
|
||||
func Fatal(args ...interface{}) {
|
||||
log(LevelFatal, args...)
|
||||
Log(LevelFatal, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func Error(args ...interface{}) {
|
||||
log(LevelError, args...)
|
||||
Log(LevelError, args...)
|
||||
}
|
||||
|
||||
func Warn(args ...interface{}) {
|
||||
log(LevelWarn, args...)
|
||||
Log(LevelWarn, args...)
|
||||
}
|
||||
|
||||
func Info(args ...interface{}) {
|
||||
log(LevelInfo, args...)
|
||||
Log(LevelInfo, args...)
|
||||
}
|
||||
|
||||
func Debug(args ...interface{}) {
|
||||
log(LevelDebug, args...)
|
||||
Log(LevelDebug, args...)
|
||||
}
|
||||
|
||||
func Trace(args ...interface{}) {
|
||||
log(LevelTrace, args...)
|
||||
Log(LevelTrace, args...)
|
||||
}
|
||||
|
||||
func log(level Level, args ...interface{}) {
|
||||
func Log(level Level, args ...interface{}) {
|
||||
if !shouldLog(level, 3) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -59,9 +59,14 @@ type pluginInstance struct {
|
||||
}
|
||||
|
||||
func (p *pluginInstance) create() (*extism.Plugin, error) {
|
||||
return p.compiled.Instance(context.Background(), extism.PluginInstanceConfig{
|
||||
plugin, err := p.compiled.Instance(context.Background(), extism.PluginInstanceConfig{
|
||||
ModuleConfig: wazero.NewModuleConfig().WithSysWalltime().WithRandSource(rand.Reader),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plugin.SetLogger(extismLogger(p.name))
|
||||
return plugin, nil
|
||||
}
|
||||
|
||||
// GetManager returns a singleton instance of the plugin manager.
|
||||
@ -82,6 +87,13 @@ func (m *Manager) Start(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set extism log level based on plugin-specific config or global log level
|
||||
pluginLogLevel := conf.Server.Plugins.LogLevel
|
||||
if pluginLogLevel == "" {
|
||||
pluginLogLevel = conf.Server.LogLevel
|
||||
}
|
||||
extism.SetLogLevel(toExtismLogLevel(log.ParseLogLevel(pluginLogLevel)))
|
||||
|
||||
m.ctx, m.cancel = context.WithCancel(ctx)
|
||||
|
||||
// Initialize wazero compilation cache for better performance
|
||||
@ -317,6 +329,7 @@ func (m *Manager) loadPlugin(name, wasmPath string) error {
|
||||
return err
|
||||
}
|
||||
defer tempPlugin.Close(m.ctx)
|
||||
tempPlugin.SetLogger(extismLogger(name))
|
||||
|
||||
// Call nd_manifest to get plugin manifest
|
||||
exit, manifestBytes, err := tempPlugin.Call(manifestFunction, nil)
|
||||
@ -348,6 +361,7 @@ func (m *Manager) loadPlugin(name, wasmPath string) error {
|
||||
AllowedHosts: manifest.AllowedHosts(),
|
||||
Timeout: uint64(defaultTimeout.Milliseconds()),
|
||||
}
|
||||
log.Debug(m.ctx, "Loaded plugin", "plugin", name, "name", manifest.Name, "version", manifest.Version, "capabilities", capabilities)
|
||||
|
||||
finalConfig := extism.PluginConfig{
|
||||
EnableWasi: true,
|
||||
@ -483,7 +497,7 @@ func callPluginFunction[I any, O any](ctx context.Context, plugin *pluginInstanc
|
||||
startCall := time.Now()
|
||||
exit, output, err := p.Call(funcName, inputBytes)
|
||||
if err != nil {
|
||||
log.Trace(ctx, "Plugin call failed", "p", 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", time.Since(startCall), "navidromeDuration", startCall.Sub(start), err)
|
||||
return result, fmt.Errorf("plugin call failed: %w", err)
|
||||
}
|
||||
if exit != 0 {
|
||||
@ -493,14 +507,42 @@ func callPluginFunction[I any, O any](ctx context.Context, plugin *pluginInstanc
|
||||
if len(output) > 0 {
|
||||
err = json.Unmarshal(output, &result)
|
||||
if err != nil {
|
||||
log.Trace(ctx, "Plugin call failed", "p", 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", time.Since(startCall), "navidromeDuration", startCall.Sub(start), err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Trace(ctx, "Plugin call succeeded", "p", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall), "navidromeDuration", startCall.Sub(start))
|
||||
log.Trace(ctx, "Plugin call succeeded", "plugin", plugin.name, "function", funcName, "pluginDuration", time.Since(startCall), "navidromeDuration", startCall.Sub(start))
|
||||
return result, err
|
||||
}
|
||||
|
||||
// extismLogger is a helper to log messages from Extism plugins
|
||||
func extismLogger(pluginName string) func(level extism.LogLevel, msg string) {
|
||||
return func(level extism.LogLevel, msg string) {
|
||||
if level == extism.LogLevelOff {
|
||||
return
|
||||
}
|
||||
log.Log(log.ParseLogLevel(level.String()), msg, "plugin", pluginName)
|
||||
}
|
||||
}
|
||||
|
||||
// toExtismLogLevel converts a Navidrome log level to an extism LogLevel
|
||||
func toExtismLogLevel(level log.Level) extism.LogLevel {
|
||||
switch level {
|
||||
case log.LevelTrace:
|
||||
return extism.LogLevelTrace
|
||||
case log.LevelDebug:
|
||||
return extism.LogLevelDebug
|
||||
case log.LevelInfo:
|
||||
return extism.LogLevelInfo
|
||||
case log.LevelWarn:
|
||||
return extism.LogLevelWarn
|
||||
case log.LevelError, log.LevelFatal:
|
||||
return extism.LogLevelError
|
||||
default:
|
||||
return extism.LogLevelInfo
|
||||
}
|
||||
}
|
||||
|
||||
// Verify interface implementations at compile time
|
||||
var (
|
||||
_ agents.PluginLoader = (*Manager)(nil)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user