feat(log): Formatted console logging with file output
This commit is contained in:
105
encoder.go
Normal file
105
encoder.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package masterlog
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// getShortFile extracts the filename from a full path
|
||||
func getShortFile(file string) string {
|
||||
for i := len(file) - 1; i >= 0; i-- {
|
||||
if file[i] == '/' {
|
||||
return file[i+1:]
|
||||
}
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
// FormattedEncoder encodes entries in the formatted text format
|
||||
type FormattedEncoder struct {
|
||||
useColors bool
|
||||
}
|
||||
|
||||
// NewFormattedEncoder creates a new FormattedEncoder
|
||||
func NewFormattedEncoder(useColors bool) *FormattedEncoder {
|
||||
return &FormattedEncoder{useColors: useColors}
|
||||
}
|
||||
|
||||
func (e *FormattedEncoder) Encode(entry Entry) ([]byte, error) {
|
||||
// Format: 2022-09-01T10:05:03+01:00 TRC main.go:23 trace message go_version=go1.19 pid=2620043
|
||||
format := entry.Timestamp.Format(time.RFC3339)
|
||||
levelStr := levelNames[entry.Level]
|
||||
shortFile := getShortFile(entry.File)
|
||||
|
||||
var result string
|
||||
if e.useColors {
|
||||
// Timestamp in light gray
|
||||
timestampColor := colorLightGray
|
||||
// Level in its specific color
|
||||
levelColor := levelColors[entry.Level]
|
||||
// File:line in light gray
|
||||
fileColor := colorLightGray
|
||||
// Separator in light gray
|
||||
separator := ">"
|
||||
// Message in white
|
||||
messageColor := colorWhite
|
||||
|
||||
result = fmt.Sprintf("%s%s%s %s%s%s %s%s%s:%d %s%s%s %s%s%s",
|
||||
timestampColor, format, colorReset,
|
||||
levelColor, levelStr, colorReset,
|
||||
fileColor, shortFile, colorReset, entry.Line,
|
||||
fileColor, separator, colorReset,
|
||||
messageColor, entry.Message, colorReset)
|
||||
} else {
|
||||
result = fmt.Sprintf("%s %s %s:%d > %s", format, levelStr, shortFile, entry.Line, entry.Message)
|
||||
}
|
||||
|
||||
// Add fields - first custom fields, then default fields
|
||||
// Custom fields (user-provided)
|
||||
for key, value := range entry.CustomFields {
|
||||
if e.useColors {
|
||||
// Field key in turquoise, value in white
|
||||
result += fmt.Sprintf(" %s%s%s=%s%v%s", colorTurquoise, key, colorReset, colorWhite, value, colorReset)
|
||||
} else {
|
||||
result += fmt.Sprintf(" %s=%v", key, value)
|
||||
}
|
||||
}
|
||||
// Default fields (go_version, pid)
|
||||
for key, value := range entry.DefaultFields {
|
||||
if e.useColors {
|
||||
// Field key in turquoise, value in white
|
||||
result += fmt.Sprintf(" %s%s%s=%s%v%s", colorTurquoise, key, colorReset, colorWhite, value, colorReset)
|
||||
} else {
|
||||
result += fmt.Sprintf(" %s=%v", key, value)
|
||||
}
|
||||
}
|
||||
|
||||
result += "\n"
|
||||
return []byte(result), nil
|
||||
}
|
||||
|
||||
// JSONEncoder encodes entries in JSON format
|
||||
type JSONEncoder struct{}
|
||||
|
||||
func (e *JSONEncoder) Encode(entry Entry) ([]byte, error) {
|
||||
type LogEntry struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Level string `json:"level"`
|
||||
File string `json:"file"`
|
||||
Line int `json:"line"`
|
||||
Message string `json:"message"`
|
||||
Fields map[string]interface{} `json:"fields,omitempty"`
|
||||
}
|
||||
|
||||
logEntry := LogEntry{
|
||||
Timestamp: entry.Timestamp.Format(time.RFC3339),
|
||||
Level: levelNames[entry.Level],
|
||||
File: getShortFile(entry.File),
|
||||
Line: entry.Line,
|
||||
Message: entry.Message,
|
||||
Fields: entry.Fields,
|
||||
}
|
||||
|
||||
return json.Marshal(logEntry)
|
||||
}
|
||||
Reference in New Issue
Block a user