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) { func Error(err error, a ...any) {
if ! ERROR.B { return }
origlog.Println("Error:", err) origlog.Println("Error:", err)
origlog.Println(a...) origlog.Println(a...)
} }

182
flags.go
View File

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

View File

@ -1,12 +1,44 @@
package log 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 ( import (
"os" "os"
"time" "time"
"errors" "errors"
"reflect" "reflect"
origlog "log"
) )
/* /*
@ -19,7 +51,7 @@ func Sleep(a ...any) {
return return
} }
Info("sleep", a[0]) origlog.Println("sleep", a[0])
switch a[0].(type) { switch a[0].(type) {
case int: case int:
@ -27,7 +59,7 @@ func Sleep(a ...any) {
case float64: case float64:
time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond) time.Sleep(time.Duration(a[0].(float64) * 1000) * time.Millisecond)
default: 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 exit("dont like apples") # ok. I'll make a note of that
*/ */
func Exit(a ...any) { func Exit(a ...any) {
Error(errors.New("log.Exit()"), a) Error(errors.New("Exit"), a)
//if (a) { //if (a) {
// os.Exit(a) // os.Exit(a)
//} //}

View File

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

View File

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