initial commit
commit
17a762ffb0
|
|
@ -0,0 +1,63 @@
|
||||||
|
package logb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
cError = iota
|
||||||
|
cWarn
|
||||||
|
cInfo
|
||||||
|
cDebug
|
||||||
|
cVerbose
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ERROR = Level{Level: cError}
|
||||||
|
WARN = Level{Level: cWarn}
|
||||||
|
INFO = Level{Level: cInfo}
|
||||||
|
DEBUG = Level{Level: cDebug}
|
||||||
|
VERBOSE = Level{Level: cVerbose}
|
||||||
|
)
|
||||||
|
|
||||||
|
type Level struct {
|
||||||
|
Level int
|
||||||
|
Lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLevel() *Level {
|
||||||
|
return &Level{
|
||||||
|
Level: cInfo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Level) Set(v Level) {
|
||||||
|
l.Lock.Lock()
|
||||||
|
defer l.Lock.Unlock()
|
||||||
|
l.Level = v.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Level) Get(v Level) int {
|
||||||
|
return l.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Level) Should(v Level) bool {
|
||||||
|
return l.Level >= v.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l Level) String() string {
|
||||||
|
s := "undefined"
|
||||||
|
switch l.Level {
|
||||||
|
case ERROR.Level:
|
||||||
|
s = "ERROR"
|
||||||
|
case WARN.Level:
|
||||||
|
s = "WARN"
|
||||||
|
case INFO.Level:
|
||||||
|
s = "INFO"
|
||||||
|
case DEBUG.Level:
|
||||||
|
s = "DEBUG"
|
||||||
|
case VERBOSE.Level:
|
||||||
|
s = "VERBOSE"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package logb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewLevel(t *testing.T) {
|
||||||
|
NewLevel()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConsts(t *testing.T) {
|
||||||
|
for _, c := range []int{
|
||||||
|
cInfo,
|
||||||
|
cWarn,
|
||||||
|
cError,
|
||||||
|
cDebug,
|
||||||
|
cVerbose,
|
||||||
|
} {
|
||||||
|
l := Level{Level: c}
|
||||||
|
if l.String() == "undefined" {
|
||||||
|
t.Error(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLevelLock(t *testing.T) {
|
||||||
|
l := NewLevel()
|
||||||
|
doLock := &sync.WaitGroup{}
|
||||||
|
doLock.Add(1)
|
||||||
|
didLock := make(chan struct{})
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
doLock.Wait()
|
||||||
|
l.Lock.Lock()
|
||||||
|
didLock <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
l.Lock.Lock()
|
||||||
|
doLock.Done()
|
||||||
|
select {
|
||||||
|
case <-didLock:
|
||||||
|
t.Error("did a lock while locked")
|
||||||
|
case <-time.After(time.Millisecond * 50):
|
||||||
|
l.Lock.Unlock()
|
||||||
|
<-didLock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLevelShould(t *testing.T) {
|
||||||
|
levels := []Level{
|
||||||
|
ERROR,
|
||||||
|
WARN,
|
||||||
|
INFO,
|
||||||
|
DEBUG,
|
||||||
|
VERBOSE,
|
||||||
|
}
|
||||||
|
for i := range levels {
|
||||||
|
okayed := 0
|
||||||
|
for j := range levels {
|
||||||
|
should := levels[i].Should(levels[j])
|
||||||
|
if should {
|
||||||
|
okayed += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if okayed != i+1 {
|
||||||
|
t.Error(levels[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package logb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var level Level = INFO
|
||||||
|
var writer io.Writer = os.Stderr
|
||||||
|
|
||||||
|
func Set(l ...Level) {
|
||||||
|
if len(l) < 1 {
|
||||||
|
l = []Level{INFO}
|
||||||
|
}
|
||||||
|
level.Set(l[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetWriter(w io.Writer) {
|
||||||
|
writer = w
|
||||||
|
}
|
||||||
|
|
||||||
|
func Info(args ...interface{}) {
|
||||||
|
log(INFO, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warn(args ...interface{}) {
|
||||||
|
log(WARN, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Error(args ...interface{}) {
|
||||||
|
log(ERROR, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debug(args ...interface{}) {
|
||||||
|
log(DEBUG, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Verbose(args ...interface{}) {
|
||||||
|
log(VERBOSE, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Infof(form string, args ...interface{}) {
|
||||||
|
logf(INFO, form, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Warnf(form string, args ...interface{}) {
|
||||||
|
logf(WARN, form, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Errorf(form string, args ...interface{}) {
|
||||||
|
logf(ERROR, form, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Debugf(form string, args ...interface{}) {
|
||||||
|
logf(DEBUG, form, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Verbosef(form string, args ...interface{}) {
|
||||||
|
logf(VERBOSE, form, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func log(lvl Level, args ...interface{}) {
|
||||||
|
v := ""
|
||||||
|
if len(args) > 0 {
|
||||||
|
args = append([]interface{}{}, args...)
|
||||||
|
v = fmt.Sprint(args)
|
||||||
|
v = v[1 : len(v)-1]
|
||||||
|
}
|
||||||
|
logf(lvl, "%s", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logf(lvl Level, form string, args ...interface{}) {
|
||||||
|
if !level.Should(lvl) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
form = fmt.Sprintf("[%v] %s\n", lvl.String()[:3], form)
|
||||||
|
fmt.Fprintf(writer, form, args...)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package logb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSet(t *testing.T) {
|
||||||
|
Set()
|
||||||
|
if level != INFO {
|
||||||
|
t.Error(level, INFO)
|
||||||
|
}
|
||||||
|
Set(VERBOSE)
|
||||||
|
if level != VERBOSE {
|
||||||
|
t.Error(level, VERBOSE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogf(t *testing.T) {
|
||||||
|
cases := map[string]struct {
|
||||||
|
foo func(...interface{})
|
||||||
|
in []interface{}
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
"info empty": {
|
||||||
|
foo: Info,
|
||||||
|
in: []interface{}{},
|
||||||
|
out: "[INF] ",
|
||||||
|
},
|
||||||
|
"info args": {
|
||||||
|
foo: Info,
|
||||||
|
in: []interface{}{"hello", "info"},
|
||||||
|
out: "[INF] hello info",
|
||||||
|
},
|
||||||
|
"debug empty": {
|
||||||
|
foo: Debug,
|
||||||
|
in: []interface{}{},
|
||||||
|
out: "[DEB] ",
|
||||||
|
},
|
||||||
|
"debug args": {
|
||||||
|
foo: Debug,
|
||||||
|
in: []interface{}{"hello", "debug"},
|
||||||
|
out: "[DEB] hello debug",
|
||||||
|
},
|
||||||
|
"error empty": {
|
||||||
|
foo: Error,
|
||||||
|
in: []interface{}{},
|
||||||
|
out: "[ERR] ",
|
||||||
|
},
|
||||||
|
"error args": {
|
||||||
|
foo: Error,
|
||||||
|
in: []interface{}{"hello", "error"},
|
||||||
|
out: "[ERR] hello error",
|
||||||
|
},
|
||||||
|
"verbose empty": {
|
||||||
|
foo: Verbose,
|
||||||
|
in: []interface{}{},
|
||||||
|
out: "[VER] ",
|
||||||
|
},
|
||||||
|
"verbose args": {
|
||||||
|
foo: Verbose,
|
||||||
|
in: []interface{}{"hello", "verbose"},
|
||||||
|
out: "[VER] hello verbose",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, c := range cases {
|
||||||
|
w := bytes.NewBuffer(nil)
|
||||||
|
SetWriter(w)
|
||||||
|
Set(VERBOSE)
|
||||||
|
c.foo(c.in...)
|
||||||
|
out := fmt.Sprintf("%s", w.Bytes())
|
||||||
|
if out != c.out+"\n" {
|
||||||
|
t.Errorf("[%s]: %v => %q, want %q", i, c.in, out, c.out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLog(t *testing.T) {
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue