pluginlog

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package pluginlog manages per-plugin log capture with file persistence, in-memory ring buffering, and callback-based real-time streaming.

Each plugin process's stderr is captured by hashicorp/go-plugin and forwarded via hclog. This package provides an io.Writer per plugin that simultaneously:

  • Persists log lines to a rotated file (e.g., plugin.kubernetes.log)
  • Buffers recent entries in a ring buffer for fast historical access
  • Invokes an optional callback for real-time UI streaming

The Manager exposes Wails-bindable methods ([GetLogs], [ListStreams]) so the Omniview UI can display plugin logs in a log viewer panel.

Example:

mgr, _ := pluginlog.NewManager("/path/to/logs", pluginlog.DefaultRotation())
defer mgr.Close()

w := mgr.Stream("kubernetes")   // io.Writer for hclog
mgr.OnEmit(func(e LogEntry) { ... })  // real-time callback

// Later, from Wails binding:
entries := mgr.GetLogs("kubernetes", 100)

Index

Constants

View Source
const DefaultBufferSize = 5000

DefaultBufferSize is the default ring buffer capacity per plugin.

Variables

This section is empty.

Functions

This section is empty.

Types

type EmitFunc

type EmitFunc func(entry LogEntry)

EmitFunc is called for each log entry. Implementations must be safe for concurrent calls from multiple plugin streams.

type LogEntry

type LogEntry struct {
	Timestamp string `json:"timestamp"`
	PluginID  string `json:"pluginID"`
	Source    string `json:"source"` // "plugin" (from hclog) — extensible
	Level     string `json:"level"`  // "trace" | "debug" | "info" | "warn" | "error"
	Message   string `json:"message"`
}

LogEntry represents a single log line from a plugin process. Field names and JSON tags intentionally match devserver.LogEntry for frontend consistency.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager manages per-plugin log streams with persistence, buffering, and optional real-time emission. It is safe for concurrent use.

Emission is subscription-gated: the emit callback only fires for plugins that have been explicitly subscribed via [Subscribe]. This prevents unnecessary serialization and transport overhead on the Wails event bus when no UI consumer is listening.

Wails-bindable methods: GetLogs, ListStreams, SearchLogs, Subscribe, Unsubscribe.

func NewManager

func NewManager(dir string, opts RotationOptions) (*Manager, error)

NewManager creates a Manager that stores plugin log files in dir. The directory is created if it does not exist.

func (*Manager) Close

func (m *Manager) Close() error

Close closes all managed log streams, flushing any buffered data. After Close, the Manager should not be used.

func (*Manager) GetLogs

func (m *Manager) GetLogs(pluginID string, count int) []LogEntry

GetLogs returns recent log entries for a plugin. If count <= 0, all buffered entries are returned. Entries are in chronological order (oldest first).

This method is designed to be Wails-bound for UI hydration.

func (*Manager) ListStreams

func (m *Manager) ListStreams() []string

ListStreams returns the plugin IDs of all active log streams, sorted alphabetically.

This method is designed to be Wails-bound for UI discovery.

func (*Manager) LogDir

func (m *Manager) LogDir() string

LogDir returns the directory where plugin log files are stored.

func (*Manager) OnEmit

func (m *Manager) OnEmit(fn EmitFunc)

OnEmit registers a callback invoked for every log entry across all plugin streams. Only one callback is active at a time; subsequent calls replace the previous one. Pass nil to disable emission.

This is the integration point for Wails event emission — the caller wraps runtime.EventsEmit in the callback to keep this package free of Wails dependencies.

func (*Manager) SearchLogs

func (m *Manager) SearchLogs(pluginID, pattern string) ([]LogEntry, error)

SearchLogs returns buffered log entries for a plugin whose message matches the given regex pattern. Returns an error if the pattern is invalid.

This method is designed to be Wails-bound for UI search.

func (*Manager) Stream

func (m *Manager) Stream(pluginID string) *PluginLogStream

Stream returns the PluginLogStream for the named plugin, creating it on first call. The returned stream implements io.Writer for use as an hclog Output target.

func (*Manager) Subscribe

func (m *Manager) Subscribe(pluginID string) int

Subscribe registers interest in real-time log emission for a plugin. The emit callback will only fire for plugins with at least one subscriber. Multiple calls increment a reference count — each must be paired with [Unsubscribe]. Returns the current subscriber count for the plugin.

This method is designed to be Wails-bound so the frontend can opt in to real-time log streaming when the user opens a log viewer.

func (*Manager) Unsubscribe

func (m *Manager) Unsubscribe(pluginID string) int

Unsubscribe decrements the subscriber count for a plugin. When the count reaches zero, real-time emission stops for that plugin. Returns the remaining subscriber count (0 means no more emission).

This method is designed to be Wails-bound so the frontend can opt out when the user closes the log viewer.

type PluginLogStream

type PluginLogStream struct {
	// contains filtered or unexported fields
}

PluginLogStream captures log output for a single plugin process. It implements io.Writer so it can be used as the hclog Output target.

Each write is simultaneously persisted to a rotated log file, parsed into a LogEntry, buffered in a ring buffer, and optionally emitted via the Manager's callback.

func (*PluginLogStream) Write

func (s *PluginLogStream) Write(p []byte) (int, error)

Write implements io.Writer. It receives hclog-formatted output, persists it to file, and processes each line into the ring buffer.

hclog output may contain multiple lines per Write call, so we split on newlines and process each independently.

type RotationOptions

type RotationOptions struct {
	MaxSizeMB  int  // maximum size in MB before rotation
	MaxBackups int  // number of old log files to keep
	MaxAgeDays int  // max days to retain old log files
	Compress   bool // compress rotated files with gzip
}

RotationOptions configures log file rotation parameters.

func DefaultRotation

func DefaultRotation() RotationOptions

DefaultRotation returns rotation settings suitable for plugin logs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL