package log /* Handles the on/off flags for things like log.Info() and log.Warn() */ /* The original log flags: log.Ldate: The date in the local time zone: YYYY/MM/DD. log.Ltime: The time in the local time zone: HH:MM:SS. log.Lmicroseconds: Microsecond resolution: HH:MM:SS.microseconds. log.Llongfile: Full file name and line number: /a/b/c/d.go:23. log.Lshortfile: Final file name element and line number: d.go:23. log.LUTC: If Ldate or Ltime is set, use UTC rather than the local time zone. log.Lmsgprefix: Move the "prefix" from the beginning of the line to before the message. log.LstdFlags: Initial values for the standard logger (Ldate | Ltime). can be set this way: myLogger.SetFlags(log.Ldate | log.Ltime) */ import ( "sync" ) var INFO LogFlag var VERBOSE LogFlag var SPEW LogFlag var WARN LogFlag var ERROR LogFlag var PRINTLN LogFlag var always LogFlag // writeMutex protects locks the write process var flagsMutex sync.Mutex type LogFlag struct { b bool orig bool // used as the Default value. set at the time of Registration() name string // TODO: figure out what package is sending the Registration subsystem string // probably should just be forced to be the package name short string // string actually printed on each line desc string } var flags []*LogFlag func init() { full := "go.wit.com/log" short := "gui" INFO.NewFlag("INFO", false, full, short, "Enable log.Info()") SPEW.NewFlag("SPEW", false, full, short, "Enable log.Spew()") WARN.NewFlag("WARN", true, full, short, "Enable log.Warn()") VERBOSE.b = false VERBOSE.name = "VERBOSE" VERBOSE.subsystem = "log" VERBOSE.desc = "Enable log.Verbose()" VERBOSE.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() always.b = true always.subsystem = "log" always.short = "log" always.Register() } // set all the flags func SetAll(b bool) { flagsMutex.Lock() defer flagsMutex.Unlock() for _, f := range flags { f.b = b } } func (f *LogFlag) SetDefault() { f.b = f.orig } // set all the flags func SetDefaults() { flagsMutex.Lock() defer flagsMutex.Unlock() for _, f := range flags { f.b = f.orig } } // 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() for _, f := range flags { Log(always, "ShowFlags() ", "(" + f.subsystem + ")", f.name, "=", f.b, ":", f.desc) } return flags } // TODO, switch to this func ProcessFlags(callback func(*LogFlag)) { flagsMutex.Lock() defer flagsMutex.Unlock() for _, f := range flags { Log(always, "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.orig = f.b if f.short == "" { f.short = f.subsystem } flags = append(flags,f) } func (f *LogFlag) Ok() bool { if f == nil {return false} return true } func (f *LogFlag) Get() bool { if ! f.Ok() {return false} return f.b } func (f *LogFlag) GetName() string { if ! f.Ok() {return ""} return f.name } func (f *LogFlag) GetSubsystem() string { if ! f.Ok() {return ""} return f.subsystem } func (f *LogFlag) GetDesc() string { if ! f.Ok() {return ""} return f.desc } // this is what the current log.SetFlag() function should become func (f *LogFlag) NewFlag(name string, b bool, full, short, desc string) { if f != nil {return} flagsMutex.Lock() defer flagsMutex.Unlock() Info("log.SetFlag() ", full, short, name, true) f = new(LogFlag) f.b = b f.orig = b f.short = short f.subsystem = full f.name = name f.desc = desc 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() Verbose("log.Set() TODO find var:", "(" + subsystem + ")", name, "=", b) for _, f := range flags { Verbose("log.Set() ", "(" + f.subsystem + ")", f.name, "=", f.b, ":", f.desc) if (subsystem == f.subsystem) && (name == f.name) { Verbose("log.Set() FOUND ", f) f.b = b return } } } func Get(subsystem string, name string) bool { flagsMutex.Lock() defer flagsMutex.Unlock() Verbose("log.Get() TODO find var:", "(" + subsystem + ")", name) for _, f := range flags { Verbose("log.Get() ", "(" + f.subsystem + ")", f.name, "=", f.b, ":", f.desc) if (subsystem == f.subsystem) && (name == f.name) { Verbose("log.Get() FOUND ", f) return f.b } } return false }