ax(batch): replace prose comments with usage examples (AX Principle 2)
Convert "X returns the Y" / "X holds Y" / "X represents Y" style comments to concrete usage examples across database/, logging/, and mining/ packages. Comments now show how to call the function with realistic values instead of restating what the signature already says. Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
parent
c703bd9050
commit
132b69426a
5 changed files with 57 additions and 63 deletions
|
|
@ -40,17 +40,14 @@ var (
|
|||
databaseMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// Config holds database configuration options
|
||||
// database.Config{Enabled: true, Path: "/data/mining.db", RetentionDays: 30}
|
||||
type Config struct {
|
||||
// Enabled determines if database persistence is active
|
||||
Enabled bool `json:"enabled"`
|
||||
// Path is the database file path (optional, uses default if empty)
|
||||
Path string `json:"path,omitempty"`
|
||||
// RetentionDays is how long to keep historical data (default 30)
|
||||
RetentionDays int `json:"retentionDays,omitempty"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Path string `json:"path,omitempty"`
|
||||
RetentionDays int `json:"retentionDays,omitempty"`
|
||||
}
|
||||
|
||||
// defaultConfig returns the default database configuration
|
||||
// configuration := defaultConfig() // Config{Enabled: true, RetentionDays: 30}
|
||||
func defaultConfig() Config {
|
||||
return Config{
|
||||
Enabled: true,
|
||||
|
|
@ -59,7 +56,7 @@ func defaultConfig() Config {
|
|||
}
|
||||
}
|
||||
|
||||
// defaultDBPath returns the default database file path
|
||||
// path, err := defaultDBPath() // "~/.local/share/lethean-desktop/mining.db"
|
||||
func defaultDBPath() (string, error) {
|
||||
dataDir := filepath.Join(xdg.DataHome, "lethean-desktop")
|
||||
if err := os.MkdirAll(dataDir, 0755); err != nil {
|
||||
|
|
@ -110,7 +107,7 @@ func Initialize(config Config) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Close closes the database connection
|
||||
// if err := database.Close(); err != nil { logging.Warn("close failed", ...) }
|
||||
func Close() error {
|
||||
databaseMutex.Lock()
|
||||
defer databaseMutex.Unlock()
|
||||
|
|
@ -132,7 +129,7 @@ func isInitialized() bool {
|
|||
return globalDatabase != nil
|
||||
}
|
||||
|
||||
// createTables creates all required database tables
|
||||
// if err := createTables(); err != nil { return databaseError("create tables", err) }
|
||||
func createTables() error {
|
||||
schema := `
|
||||
-- Hashrate history table for storing miner performance data
|
||||
|
|
@ -175,7 +172,7 @@ func createTables() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Cleanup removes old data based on retention settings
|
||||
// database.Cleanup(30) // remove hashrate rows older than 30 days
|
||||
func Cleanup(retentionDays int) error {
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
|
@ -194,7 +191,7 @@ func Cleanup(retentionDays int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// vacuumDB optimizes the database file size
|
||||
// if err := vacuumDB(); err != nil { logging.Warn("vacuum failed", ...) }
|
||||
func vacuumDB() error {
|
||||
databaseMutex.RLock()
|
||||
defer databaseMutex.RUnlock()
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"forge.lthn.ai/Snider/Mining/pkg/logging"
|
||||
)
|
||||
|
||||
// parseSQLiteTimestamp parses timestamp strings from SQLite which may use various formats.
|
||||
// Logs a warning if parsing fails and returns zero time.
|
||||
// t := parseSQLiteTimestamp("2006-01-02 15:04:05") // time.Time{...}
|
||||
// t := parseSQLiteTimestamp("") // time.Time{} (zero)
|
||||
func parseSQLiteTimestamp(s string) time.Time {
|
||||
if s == "" {
|
||||
return time.Time{}
|
||||
|
|
@ -33,7 +33,8 @@ func parseSQLiteTimestamp(s string) time.Time {
|
|||
return time.Time{}
|
||||
}
|
||||
|
||||
// Resolution indicates the data resolution type
|
||||
// database.ResolutionHigh // "high" — 10-second intervals
|
||||
// database.ResolutionLow // "low" — 1-minute averages
|
||||
type Resolution string
|
||||
|
||||
const (
|
||||
|
|
@ -41,13 +42,13 @@ const (
|
|||
ResolutionLow Resolution = "low" // 1-minute averages
|
||||
)
|
||||
|
||||
// HashratePoint represents a single hashrate measurement
|
||||
// point := database.HashratePoint{Timestamp: time.Now(), Hashrate: 1234}
|
||||
type HashratePoint struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Hashrate int `json:"hashrate"`
|
||||
}
|
||||
|
||||
// dbInsertTimeout is the maximum time to wait for a database insert operation
|
||||
// ctx, cancel := context.WithTimeout(ctx, dbInsertTimeout) // 5s ceiling for INSERT
|
||||
const dbInsertTimeout = 5 * time.Second
|
||||
|
||||
// InsertHashratePoint stores a hashrate measurement in the database.
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// HashrateStore defines the interface for hashrate data persistence.
|
||||
// This interface allows for dependency injection and easier testing.
|
||||
// var store database.HashrateStore = database.DefaultStore()
|
||||
// store.InsertHashratePoint(ctx, "xmrig", "xmrig", point, database.ResolutionHigh)
|
||||
// store.Cleanup(30)
|
||||
type HashrateStore interface {
|
||||
// store.InsertHashratePoint(ctx, "xmrig", "xmrig", HashratePoint{Timestamp: time.Now(), Hashrate: 1234}, ResolutionHigh)
|
||||
InsertHashratePoint(ctx context.Context, minerName, minerType string, point HashratePoint, resolution Resolution) error
|
||||
|
|
@ -29,12 +30,11 @@ type HashrateStore interface {
|
|||
Close() error
|
||||
}
|
||||
|
||||
// defaultStore implements HashrateStore using the global database connection.
|
||||
// This provides backward compatibility while allowing interface-based usage.
|
||||
// store := database.DefaultStore() // wraps the global database connection
|
||||
type defaultStore struct{}
|
||||
|
||||
// DefaultStore returns a HashrateStore that uses the global database connection.
|
||||
// This is useful for gradual migration from package-level functions to interface-based usage.
|
||||
// store := database.DefaultStore()
|
||||
// store.GetHashrateStats("xmrig")
|
||||
func DefaultStore() HashrateStore {
|
||||
return &defaultStore{}
|
||||
}
|
||||
|
|
@ -63,8 +63,7 @@ func (s *defaultStore) Close() error {
|
|||
return Close()
|
||||
}
|
||||
|
||||
// NopStore returns a HashrateStore that does nothing.
|
||||
// Useful for testing or when database is disabled.
|
||||
// store := database.NopStore() // all methods are no-ops; use when database is disabled
|
||||
func NopStore() HashrateStore {
|
||||
return &nopStore{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,21 +10,18 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Level represents the severity of a log message.
|
||||
// if level >= logging.LevelWarn { alertOps() }
|
||||
type Level int
|
||||
|
||||
const (
|
||||
// LevelDebug is the most verbose log level.
|
||||
LevelDebug Level = iota
|
||||
// LevelInfo is for general informational messages.
|
||||
LevelInfo
|
||||
// LevelWarn is for warning messages.
|
||||
LevelWarn
|
||||
// LevelError is for error messages.
|
||||
LevelError
|
||||
LevelDebug Level = iota // logger.SetLevel(logging.LevelDebug)
|
||||
LevelInfo // logger.SetLevel(logging.LevelInfo)
|
||||
LevelWarn // logger.SetLevel(logging.LevelWarn)
|
||||
LevelError // logger.SetLevel(logging.LevelError)
|
||||
)
|
||||
|
||||
// String returns the string representation of the log level.
|
||||
// logging.LevelDebug.String() // "DEBUG"
|
||||
// logging.LevelError.String() // "ERROR"
|
||||
func (l Level) String() string {
|
||||
switch l {
|
||||
case LevelDebug:
|
||||
|
|
@ -40,7 +37,8 @@ func (l Level) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
// Logger provides structured logging with configurable output and level.
|
||||
// logger := logging.New(logging.Config{Level: logging.LevelDebug, Component: "mining"})
|
||||
// logger.Info("started", logging.Fields{"miner": "xmrig"})
|
||||
type Logger struct {
|
||||
mutex sync.Mutex
|
||||
output io.Writer
|
||||
|
|
@ -48,14 +46,14 @@ type Logger struct {
|
|||
component string
|
||||
}
|
||||
|
||||
// Config holds configuration for creating a new Logger.
|
||||
// logging.Config{Output: os.Stderr, Level: logging.LevelInfo, Component: "mining"}
|
||||
type Config struct {
|
||||
Output io.Writer
|
||||
Level Level
|
||||
Component string
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default logger configuration.
|
||||
// config := logging.DefaultConfig() // Output: os.Stderr, Level: LevelInfo
|
||||
func DefaultConfig() Config {
|
||||
return Config{
|
||||
Output: os.Stderr,
|
||||
|
|
@ -66,14 +64,14 @@ func DefaultConfig() Config {
|
|||
|
||||
// New creates a Logger with the given configuration.
|
||||
// logger := logging.New(logging.Config{Output: os.Stderr, Level: logging.LevelInfo, Component: "mining"})
|
||||
func New(cfg Config) *Logger {
|
||||
if cfg.Output == nil {
|
||||
cfg.Output = os.Stderr
|
||||
func New(config Config) *Logger {
|
||||
if config.Output == nil {
|
||||
config.Output = os.Stderr
|
||||
}
|
||||
return &Logger{
|
||||
output: cfg.Output,
|
||||
level: cfg.Level,
|
||||
component: cfg.Component,
|
||||
output: config.Output,
|
||||
level: config.Level,
|
||||
component: config.Component,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +103,7 @@ func (l *Logger) GetLevel() Level {
|
|||
return l.level
|
||||
}
|
||||
|
||||
// Fields represents key-value pairs for structured logging.
|
||||
// logger.Info("started", logging.Fields{"miner": "xmrig", "pool": "pool.lthn.io"})
|
||||
type Fields map[string]interface{}
|
||||
|
||||
// log writes a log message at the specified level.
|
||||
|
|
@ -149,47 +147,47 @@ func (l *Logger) log(level Level, msg string, fields Fields) {
|
|||
fmt.Fprint(l.output, builder.String())
|
||||
}
|
||||
|
||||
// Debug logs a debug message.
|
||||
// logger.Debug("hashrate collected", logging.Fields{"rate": 1234})
|
||||
func (l *Logger) Debug(msg string, fields ...Fields) {
|
||||
l.log(LevelDebug, msg, mergeFields(fields))
|
||||
}
|
||||
|
||||
// Info logs an informational message.
|
||||
// logger.Info("miner started", logging.Fields{"miner": "xmrig"})
|
||||
func (l *Logger) Info(msg string, fields ...Fields) {
|
||||
l.log(LevelInfo, msg, mergeFields(fields))
|
||||
}
|
||||
|
||||
// Warn logs a warning message.
|
||||
// logger.Warn("hashrate drop", logging.Fields{"current": 500, "min": 1000})
|
||||
func (l *Logger) Warn(msg string, fields ...Fields) {
|
||||
l.log(LevelWarn, msg, mergeFields(fields))
|
||||
}
|
||||
|
||||
// Error logs an error message.
|
||||
// logger.Error("miner crashed", logging.Fields{"code": -1, "miner": "xmrig"})
|
||||
func (l *Logger) Error(msg string, fields ...Fields) {
|
||||
l.log(LevelError, msg, mergeFields(fields))
|
||||
}
|
||||
|
||||
// Debugf logs a formatted debug message.
|
||||
// logger.Debugf("collected %d hashrate points for %s", len(points), minerName)
|
||||
func (l *Logger) Debugf(format string, args ...interface{}) {
|
||||
l.log(LevelDebug, fmt.Sprintf(format, args...), nil)
|
||||
}
|
||||
|
||||
// Infof logs a formatted informational message.
|
||||
// logger.Infof("miner %s started on pool %s", minerName, poolURL)
|
||||
func (l *Logger) Infof(format string, args ...interface{}) {
|
||||
l.log(LevelInfo, fmt.Sprintf(format, args...), nil)
|
||||
}
|
||||
|
||||
// Warnf logs a formatted warning message.
|
||||
// logger.Warnf("hashrate %d H/s below minimum %d H/s", current, minimum)
|
||||
func (l *Logger) Warnf(format string, args ...interface{}) {
|
||||
l.log(LevelWarn, fmt.Sprintf(format, args...), nil)
|
||||
}
|
||||
|
||||
// Errorf logs a formatted error message.
|
||||
// logger.Errorf("failed to connect to pool %s: %v", poolURL, err)
|
||||
func (l *Logger) Errorf(format string, args ...interface{}) {
|
||||
l.log(LevelError, fmt.Sprintf(format, args...), nil)
|
||||
}
|
||||
|
||||
// mergeFields combines multiple Fields maps into one.
|
||||
// combined := mergeFields([]Fields{{"a": 1}, {"b": 2}}) // Fields{"a": 1, "b": 2}
|
||||
func mergeFields(fields []Fields) Fields {
|
||||
if len(fields) == 0 {
|
||||
return nil
|
||||
|
|
@ -210,21 +208,22 @@ var (
|
|||
globalMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// SetGlobal sets the global logger instance.
|
||||
// logging.SetGlobal(logging.New(logging.Config{Level: logging.LevelDebug}))
|
||||
func SetGlobal(l *Logger) {
|
||||
globalMutex.Lock()
|
||||
defer globalMutex.Unlock()
|
||||
globalLogger = l
|
||||
}
|
||||
|
||||
// GetGlobal returns the global logger instance.
|
||||
// logger := logging.GetGlobal()
|
||||
// logger.Info("using global logger")
|
||||
func GetGlobal() *Logger {
|
||||
globalMutex.RLock()
|
||||
defer globalMutex.RUnlock()
|
||||
return globalLogger
|
||||
}
|
||||
|
||||
// SetGlobalLevel sets the log level of the global logger.
|
||||
// logging.SetGlobalLevel(logging.LevelDebug) // enable debug logging globally
|
||||
func SetGlobalLevel(level Level) {
|
||||
globalMutex.RLock()
|
||||
defer globalMutex.RUnlock()
|
||||
|
|
@ -273,7 +272,8 @@ func Errorf(format string, args ...interface{}) {
|
|||
GetGlobal().Errorf(format, args...)
|
||||
}
|
||||
|
||||
// ParseLevel parses a string into a log level.
|
||||
// level, err := logging.ParseLevel("DEBUG") // LevelDebug, nil
|
||||
// level, err := logging.ParseLevel("nope") // LevelInfo, error
|
||||
func ParseLevel(s string) (Level, error) {
|
||||
switch strings.ToUpper(s) {
|
||||
case "DEBUG":
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ import (
|
|||
"forge.lthn.ai/Snider/Mining/pkg/logging"
|
||||
)
|
||||
|
||||
// On Windows, syslog is not available. We'll use a dummy implementation
|
||||
// that logs to the standard logger.
|
||||
|
||||
// logToSyslog logs a message to the standard logger, mimicking the syslog function's signature.
|
||||
// logToSyslog("miner started: xmrig") // falls back to logging.Info on Windows
|
||||
func logToSyslog(message string) {
|
||||
logging.Info(message)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue