Skip to content

Commit

Permalink
Merge 22d23c7 into fdcdf50
Browse files Browse the repository at this point in the history
  • Loading branch information
deankarn committed May 12, 2019
2 parents fdcdf50 + 22d23c7 commit da61989
Show file tree
Hide file tree
Showing 24 changed files with 983 additions and 173 deletions.
26 changes: 26 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
language: go
go:
- 1.12.5
- tip
matrix:
allow_failures:
- go: tip

notifications:
email:
recipients: dean.karn@gmail.com
on_success: change
on_failure: always

before_install:
- go get -u github.com/go-playground/overalls
- go get -u github.com/mattn/goveralls

script:
- make test
- go vet ./...

after_success: |
[ $TRAVIS_GO_VERSION = 1.12.5 ] &&
overalls -project="github.com/go-playground/log" -covermode=count -ignore=.git,examples -debug &&
goveralls -coverprofile=overalls.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## log
<img align="right" src="https://raw.githubusercontent.com/go-playground/log/master/logo.png">![Project status](https://img.shields.io/badge/version-6.4.0-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/log/branches/master/badge.svg)](https://semaphoreci.com/joeybloggs/log)
<img align="right" src="https://raw.githubusercontent.com/go-playground/log/master/logo.png">![Project status](https://img.shields.io/badge/version-7.0.0-green.svg)
[![Build Status](https://travis-ci.org/go-playground/log.svg?branch=master)](https://travis-ci.org/go-playground/log)
[![Coverage Status](https://coveralls.io/repos/github/go-playground/log/badge.svg?branch=master)](https://coveralls.io/github/go-playground/log?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/log)](https://goreportcard.com/report/github.com/go-playground/log)
[![GoDoc](https://godoc.org/github.com/go-playground/log?status.svg)](https://godoc.org/github.com/go-playground/log)
Expand All @@ -18,7 +18,8 @@ Features
- [x] Logger is simple, only logic to create the log entry and send it off to the handlers and they take it from there.
- [x] Ability to specify which log levels get sent to each handler
- [x] Built-in console, syslog, http, HipChat, json and email handlers
- [x] Handlers are simple to write + easy to register
- [x] Handlers are simple to write + easy to register + easy to remove
- [x] Default logger for quick prototyping and cli applications. It is automatically removed when you register one of your own.
- [x] Logger is a singleton ( one of the few instances a singleton is desired ) so the root package registers which handlers are used and any libraries just follow suit.
- [x] Convenient context helpers `GetContext` & `SetContext`
- [x] Works with go-playground/errors extracting types and tags when used with `WithError`, is the default
Expand All @@ -36,7 +37,7 @@ go get -u github.com/go-playground/log

Usage
------
import the log package, setup at least one handler
import the log package, it is recommended to set up at least one handler, but there is a default console logger.
```go
package main

Expand All @@ -48,6 +49,8 @@ import (
)

func main() {
// There is a default logger with the same settings
// once any other logger is registered the default logger is removed.
cLog := console.New(true)
log.AddHandler(cLog, log.AllLevels...)

Expand Down
7 changes: 1 addition & 6 deletions _examples/basic/main.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package main

import (
"errors"

"github.com/go-playground/errors"
"github.com/go-playground/log"
"github.com/go-playground/log/handlers/console"
)

func main() {
cLog := console.New(true)
log.AddHandler(cLog, log.AllLevels...)

// Trace
defer log.WithTrace().Info("time to run")

Expand Down
45 changes: 45 additions & 0 deletions _examples/handler/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"github.com/go-playground/errors"

"github.com/go-playground/log"
"github.com/go-playground/log/handlers/console"
)

func main() {
cLog := console.New(true)
log.AddHandler(cLog, log.AllLevels...)

// Trace
defer log.WithTrace().Info("time to run")

log.Debug("debug")
log.Info("info")
log.Notice("notice")
log.Warn("warn")
log.Error("error")
// log.Panic("panic") // this will panic
log.Alert("alert")
// log.Fatal("fatal") // this will call os.Exit(1)

err := errors.New("the is an error")
// logging with fields can be used with any of the above
log.WithError(err).WithFields(log.F("key", "value")).Info("test info")

// predefined global fields
log.WithDefaultFields(log.Fields{
{"program", "test"},
{"version", "0.1.3"},
}...)

log.WithField("key", "value").Info("testing default fields")

// or request scoped default fields
logger := log.WithFields(
log.F("request", "req"),
log.F("scoped", "sco"),
)

logger.WithField("key", "value").Info("test")
}
17 changes: 17 additions & 0 deletions byte_pool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package log

import "sync"

// BytePool represents a reusable byte pool. It is a centralized global instance for this package and can be accessed by
// calling log.BytePool(). It is intended to be used by Handlers.
type ByteArrayPool struct {
pool *sync.Pool
}

func (p *ByteArrayPool) Get() []byte {
return p.pool.Get().([]byte)
}

func (p *ByteArrayPool) Put(b []byte) {
p.pool.Put(b[:0])
}
147 changes: 147 additions & 0 deletions default_logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package log

import (
"bufio"
"fmt"
"io"
stdlog "log"
"os"
"strconv"

"github.com/go-playground/ansi"
)

const (
space = byte(' ')
equals = byte('=')
newLine = byte('\n')
base10 = 10
v = "%v"
)

var (
defaultLoggerWriter io.Writer = os.Stderr // here for tests only
defaultLoggerTimeFormat = "2006-01-02 15:04:05.000000000Z07:00" // here for tests only
)

// console is an instance of the console logger
type console struct {
colors [8]ansi.EscSeq
writer io.Writer
timestampFormat string
r *io.PipeReader
}

func newDefaultLogger() *console {
c := &console{
colors: [...]ansi.EscSeq{
DebugLevel: ansi.Green,
InfoLevel: ansi.Blue,
NoticeLevel: ansi.LightCyan,
WarnLevel: ansi.LightYellow,
ErrorLevel: ansi.LightRed,
PanicLevel: ansi.Red,
AlertLevel: ansi.Red + ansi.Underline,
FatalLevel: ansi.Red + ansi.Underline + ansi.Blink,
},
writer: defaultLoggerWriter,
timestampFormat: defaultLoggerTimeFormat,
}
done := make(chan struct{})
go c.handleStdLogger(done)
<-done // have to wait, it was running too quickly and some messages can be lost
return c
}

// this will redirect the output of
func (c *console) handleStdLogger(done chan<- struct{}) {
var w *io.PipeWriter
c.r, w = io.Pipe()
stdlog.SetOutput(w)

scanner := bufio.NewScanner(c.r)
go func() {
done <- struct{}{}
}()

for scanner.Scan() {
WithField("stdlog", true).Info(scanner.Text())
}
_ = c.r.Close()
_ = w.Close()
}

// Log handles the log entry
func (c *console) Log(e Entry) {
var i int

b := BytePool().Get()
lvl := e.Level.String()
color := c.colors[e.Level]
b = append(b, e.Timestamp.Format(c.timestampFormat)...)
b = append(b, space)
b = append(b, color...)

for i = 0; i < 6-len(lvl); i++ {
b = append(b, space)
}
b = append(b, lvl...)
b = append(b, ansi.Reset...)
b = append(b, space)
b = append(b, e.Message...)

for _, f := range e.Fields {
b = append(b, space)
b = append(b, color...)
b = append(b, f.Key...)
b = append(b, ansi.Reset...)
b = append(b, equals)

switch t := f.Value.(type) {
case string:
b = append(b, t...)
case int:
b = strconv.AppendInt(b, int64(t), base10)
case int8:
b = strconv.AppendInt(b, int64(t), base10)
case int16:
b = strconv.AppendInt(b, int64(t), base10)
case int32:
b = strconv.AppendInt(b, int64(t), base10)
case int64:
b = strconv.AppendInt(b, t, base10)
case uint:
b = strconv.AppendUint(b, uint64(t), base10)
case uint8:
b = strconv.AppendUint(b, uint64(t), base10)
case uint16:
b = strconv.AppendUint(b, uint64(t), base10)
case uint32:
b = strconv.AppendUint(b, uint64(t), base10)
case uint64:
b = strconv.AppendUint(b, t, base10)
case float32:
b = strconv.AppendFloat(b, float64(t), 'f', -1, 32)
case float64:
b = strconv.AppendFloat(b, t, 'f', -1, 64)
case bool:
b = strconv.AppendBool(b, t)
default:
b = append(b, fmt.Sprintf(v, f.Value)...)
}
}
b = append(b, newLine)
_, _ = c.writer.Write(b)
BytePool().Put(b)
}

// Close cleans up any resources
func (c *console) Close() error {
// reset the output back to original
stdlog.SetOutput(os.Stderr)
// since we reset the output piror to closing we don't have to wait
if c.r != nil {
_ = c.r.Close()
}
return nil
}

0 comments on commit da61989

Please sign in to comment.