Compare commits

..

No commits in common. "29db278b6aaa209c5b2f8b6a0dbbc4b726a4323e" and "6b25784508180c69076f53b7a4e78f85b367c902" have entirely different histories.

8 changed files with 186 additions and 129 deletions

View File

@ -5,7 +5,6 @@ import (
)
func Error(err error, a ...any) {
if ! ERROR.B { return }
origlog.Println("Error:", err)
origlog.Println(a...)
}

182
flags.go
View File

@ -1,159 +1,109 @@
package log
/*
Handles the on/off flags for things like log.Info() and log.Warn()
*/
import (
"sync"
"errors"
)
var INFO LogFlag
var VERBOSE LogFlag
var SPEW LogFlag
var WARN LogFlag
var ERROR LogFlag
var PRINTLN LogFlag
var INFO bool = true
var WARN bool = true
var ERROR bool = true
// writeMutex protects locks the write process
var flagsMutex sync.Mutex
var VERBOSE bool = false
// var SPEW bool = false
var SPEW LogFlag
type LogFlag struct {
B bool
Default bool // set at the time of Registration()
Name string
Subsystem string
Desc string
}
var registered map[string][]string
var flags []*LogFlag
func init() {
INFO.B = false
INFO.Name = "INFO"
INFO.Subsystem = "log"
INFO.Desc = "Enable log.Info()"
INFO.Register()
registered = make(map[string][]string)
SPEW.B = false
SPEW.Name = "SPEW"
SPEW.Subsystem = "log"
SPEW.Desc = "Enable log.Spew()"
SPEW.Register()
VERBOSE.B = false
VERBOSE.Name = "VERBOSE"
VERBOSE.Subsystem = "log"
VERBOSE.Desc = "Enable log.Verbose()"
VERBOSE.Register()
WARN.B = true
WARN.Name = "WARN"
WARN.Subsystem = "log"
WARN.Desc = "Enable log.Warn()"
WARN.Register()
ERROR.B = true
ERROR.Name = "ERROR"
ERROR.Subsystem = "log"
ERROR.Desc = "Enable log.Error()"
ERROR.Register()
PRINTLN.B = true
PRINTLN.Name = "PRINTLN"
PRINTLN.Subsystem = "log"
PRINTLN.Desc = "Enable log.Println()"
PRINTLN.Register()
// register the default flags used by this log package
registered["log"] = []string{"SPEW","INFO", "WARN", "ERROR", "VERBOSE"}
}
// set all the flags
func SetAll(b bool) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
func All(b bool) {
Set("SPEW", b)
Set("INFO", b)
Set("WARN", b)
Set("ERROR", b)
Set("VERBOSE", b)
for _, f := range flags {
Warn("All() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
f.B = b
}
}
// set all the flags
func SetDefaults() {
flagsMutex.Lock()
defer flagsMutex.Unlock()
for _, f := range flags {
f.B = f.Default
Warn("All() f.B is now", f.B)
}
}
// this bypasses all checks and _always_ logs the info to STDOUT
// is this a bad idea? Probably not....
// TODO: returning []*LogFlag is not safe and access must be locked
// but this is only used by the log debugging window at this time
func ShowFlags() []*LogFlag {
flagsMutex.Lock()
defer flagsMutex.Unlock()
func ListFlags() map[string][]string {
Log(true, "ListFlags() registered =", registered)
for _, f := range flags {
Log(true, "ShowFlags() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
Log(true, "ListFlags() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
}
return flags
return registered
}
// TODO, switch to this
func ProcessFlags(callback func(*LogFlag)) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
for _, f := range flags {
Log(true, "ProcessFlags() run callback(f) here on", f)
callback(f)
}
}
// register a variable name from a subsystem
// inspired by Alex Flint
// set the Default value at the time of registration
func (f *LogFlag) Register() {
flagsMutex.Lock()
defer flagsMutex.Unlock()
Info("log.Register() ", f)
f.Default = f.B
flags = append(flags,f)
}
func (f *LogFlag) Set(b bool) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
Info("Set() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
f.B = b
Info("Set() f.B is now", f.B)
}
func Set(subsystem string, name string, b bool) {
flagsMutex.Lock()
defer flagsMutex.Unlock()
Info("Set() TODO find var:", "(" + subsystem + ")", name, "=", b)
for _, f := range flags {
Log(true, "Set() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
if (subsystem == f.Subsystem) && (name == f.Name) {
Log(true, "Set() FOUND ", f)
f.B = b
return
func Set(flag string, b bool) {
switch flag {
case "INFO":
INFO = b
case "WARN":
WARN = b
case "SPEW":
SPEW.B = b
case "ERROR":
ERROR = b
case "VERBOSE":
VERBOSE = b
default:
Error(errors.New("unknown flag"), "Flag name sent:", flag)
}
}
}
func Get(subsystem string, name string) bool {
flagsMutex.Lock()
defer flagsMutex.Unlock()
Info("Get() TODO find var:", "(" + subsystem + ")", name)
for _, f := range flags {
Log(true, "Get() ", "(" + f.Subsystem + ")", f.Name, "=", f.B, ":", f.Desc)
if (subsystem == f.Subsystem) && (name == f.Name) {
Log(true, "Get() FOUND ", f)
return f.B
}
func Get(flag string) bool {
switch flag {
case "INFO":
return INFO
case "WARN":
return WARN
case "SPEW":
return SPEW.B
case "ERROR":
return ERROR
case "VERBOSE":
return VERBOSE
default:
Error(errors.New("unknown flag"), "Flag name sent:", flag)
}
return false
}
// register a variable name from a subsystem
// inspired by Alex Flint
func (f *LogFlag) Register() {
Info("log.Register() ", f)
flags = append(flags,f)
}
// register a variable name from a subsystem
// this is used for custom log flags
func Register(subsystem string, name string, b *bool) {
Info("log.Register() got subsystem", subsystem, "with name =", name, "bool value =", b)
registered[subsystem] = append(registered[subsystem], name)
}

View File

@ -5,11 +5,11 @@ import (
)
func Info(a ...any) {
if ! INFO.B { return }
if ! INFO { return }
golanglog.Println(a...)
}
func Infof(s string, a ...any) {
if ! INFO.B { return }
if ! INFO { return }
golanglog.Printf(s, a...)
}

80
notes.go Normal file
View File

@ -0,0 +1,80 @@
package log
/*
var argv struct {
Foo string
Bar bool
User string `arg:"env:USER"`
Demo bool `help:"run a demo"`
}
*/
/*
var f1 *os.File
var f2 *os.File
var err error
*/
/* from gocron:
// DefaultLogger is used by Cron if none is specified.
var DefaultLogger Logger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
// DiscardLogger can be used by callers to discard all log messages.
var DiscardLogger Logger = PrintfLogger(log.New(ioutil.Discard, "", 0))
// Logger is the interface used in this package for logging, so that any backend
// can be plugged in. It is a subset of the github.com/go-logr/logr interface.
type Logger interface {
// Info logs routine messages about cron's operation.
Info(msg string, keysAndValues ...interface{})
// Error logs an error condition.
Error(err error, msg string, keysAndValues ...interface{})
}
*/
// fmt.Println(argv.Foo, args.Bar, args.User)
/*
// from: https://github.com/robfig/cron/blob/master/logger.go
log.Println()
log.Println("STDOUT is now at /tmp/guilogfile")
log.Println("STDOUT is now at /tmp/guilogfile")
log.Println()
f1, err = os.OpenFile(outfile, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
// hmm. is there a trick here or must this be in main()
// defer f.Close()
log.SetOutput(f1)
log.Println("This is a test log entry")
*/
/*
func captureSTDOUT() {
f2, _ = os.OpenFile("/tmp/my.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
multiWriter := io.MultiWriter(os.Stderr, f2)
rd, wr, err := os.Pipe()
if err != nil {
os.Exit(1)
}
// overwrite os.Stdout
os.Stderr = wr
go func() {
scanner := bufio.NewScanner(rd)
for scanner.Scan() {
stdoutLine := scanner.Text()
multiWriter.Write([]byte(stdoutLine + "\n"))
}
}()
fmt.Println("foobar")
// hacky sleep to ensure the go routine can write before program exits
time.Sleep(time.Second)
}
*/

View File

@ -18,19 +18,15 @@ package log
so this package appears to work exactly like the original ones
*/
// TODO: fill in the other functions from "log". Is there a way to automagically do that?
import (
origlog "log"
)
func Println(a ...any) {
if ! PRINTLN.B { return }
origlog.Println(a...)
}
func Printf(s string, a ...any) {
if ! PRINTLN.B { return }
origlog.Printf(s, a...)
}

View File

@ -1,12 +1,44 @@
package log
//
// version v1.2
//
// I like things to be easy.
//
// this means all the log settings are in one place. it should allow
// things to be over-ridden externally to the library
// but still allow command line --args to pass debugging settings
//
// I also have a generic sleep() and exit() in here because it's simple
//
// Usage:
//
// log("something", foo, bar)
// var DEBUG bool = true
// log(DEBUG, "something else", someOtherVariable) # if DEBUG == false, return doing nothing
//
// a shortcut for sleep so you don't have to always change the import lines when debugging
/*
I've spent, am spending, too much time thinking about 'logging'. 'log', 'logrus', 'zap', whatever.
I'm not twitter. i don't give a fuck about how many nanoseconds it takes to log. Anyway, this
implementation is probably faster than all of those because you just set one bool to FALSE
and it all stops.
Sometimes I need to capture to stdout, sometimes stdout can't
work because it doesn't exist for the user. This whole thing is a PITA. Then it's spread
over 8 million references in every .go file. I'm tapping out and putting
it in one place. here it is. Also, this makes having debug levels really fucking easy.
You can define whatever level of logging you want from anywhere (command line) etc.
log() # doesn't do anything
log(stuff) # sends it to whatever log you define in a single place. here is the place
*/
import (
"os"
"time"
"errors"
"reflect"
origlog "log"
)
/*
@ -19,7 +51,7 @@ func Sleep(a ...any) {
return
}
Info("sleep", a[0])
origlog.Println("sleep", a[0])
switch a[0].(type) {
case int:
@ -27,7 +59,7 @@ func Sleep(a ...any) {
case float64:
time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond)
default:
Info("sleep a[0], type = ", a[0], reflect.TypeOf(a[0]))
origlog.Println("sleep a[0], type = ", a[0], reflect.TypeOf(a[0]))
}
}
@ -37,7 +69,7 @@ func Sleep(a ...any) {
exit("dont like apples") # ok. I'll make a note of that
*/
func Exit(a ...any) {
Error(errors.New("log.Exit()"), a)
Error(errors.New("Exit"), a)
//if (a) {
// os.Exit(a)
//}

View File

@ -5,6 +5,6 @@ import (
)
func Verbose(a ...any) {
if ! VERBOSE.B { return }
if ! VERBOSE { return }
golanglog.Println(a...)
}

View File

@ -5,6 +5,6 @@ import (
)
func Warn(a ...any) {
if ! WARN.B { return }
if ! WARN { return }
origlog.Println(a...)
}