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
- type EmitFunc
- type LogEntry
- type Manager
- func (m *Manager) Close() error
- func (m *Manager) GetLogs(pluginID string, count int) []LogEntry
- func (m *Manager) ListStreams() []string
- func (m *Manager) LogDir() string
- func (m *Manager) OnEmit(fn EmitFunc)
- func (m *Manager) SearchLogs(pluginID, pattern string) ([]LogEntry, error)
- func (m *Manager) Stream(pluginID string) *PluginLogStream
- func (m *Manager) Subscribe(pluginID string) int
- func (m *Manager) Unsubscribe(pluginID string) int
- type PluginLogStream
- type RotationOptions
Constants ¶
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 ¶
Close closes all managed log streams, flushing any buffered data. After Close, the Manager should not be used.
func (*Manager) GetLogs ¶
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 ¶
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) OnEmit ¶
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 ¶
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 ¶
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 ¶
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.