Moved package log to logging

This commit is contained in:
bwilliams committed 2026-10-09 09:30:02 +01:00
1 parent da81e6ccd9
commit dd26976f76
3 files changed
+13 -11

No files matched your search

+123
View File
@@ -0,0 +1,123 @@
/*
Copyright © 2026 Craig Williams <craig@avsdev.uk>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package logging
import (
"log/slog"
"os"
"reflect"
"unsafe"
"github.com/lmittmann/tint"
)
// ---------- Standard log handling (terminal or file based) ----------
var logLevel slog.LevelVar
var fileLogger *os.File
// Set the logging to a particular level, quietly
func SetLevel(level slog.Level) {
logLevel.Set(level)
}
// Enable debug level logging
func EnableDebug() {
if logLevel.Level() > slog.LevelDebug {
logLevel.Set(slog.LevelDebug)
slog.Debug("Debug logging enabled")
}
}
func LogToFile(logfile string) error {
if fileLogger != nil {
(*fileLogger).Close()
}
// Open the log file
fileLogger, err := os.OpenFile(logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return err
}
opts := &slog.HandlerOptions{
Level: &logLevel,
}
handler := slog.NewJSONHandler(fileLogger, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
return nil
}
func Shutdown() error {
var err error = nil
if fileLogger != nil {
err = (*fileLogger).Close()
fileLogger = nil
}
return err
}
func LogToTerminal() {
opts := &tint.Options{
Level: &logLevel,
TimeFormat: "*",
}
handler := tint.NewTextHandler(os.Stdout, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
}
func IsJSONHandler(h slog.Handler) bool {
val := reflect.ValueOf(h)
// Ensure we are working with a pointer to a struct (*JSONHandler or *TextHandler or derived)
if val.Kind() != reflect.Pointer || val.Elem().Kind() != reflect.Struct {
return false
}
// Both JSONHandler and TextHandler wrap an unexported field named 'commonHandler'
commonHandlerField := val.Elem().FieldByName("commonHandler")
if !commonHandlerField.IsValid() {
return false
}
// Get the underlying *commonHandler struct pointer
// commonHandlerField is unexported, so we must use unsafe to bypass Go's safety checks
ptr := reflect.NewAt(
commonHandlerField.Type().Elem(),
unsafe.Pointer(commonHandlerField.Pointer()),
)
// Find the unexported 'json' boolean field inside commonHandler
jsonField := ptr.Elem().FieldByName("json")
if !jsonField.IsValid() {
return false
}
// Read the boolean value using unsafe
return *(*bool)(unsafe.Pointer(jsonField.UnsafeAddr()))
}
func IsFileLogger() bool {
return fileLogger != nil
}
func IsDebugEnabled() bool {
return logLevel.Level() <= slog.LevelDebug
}