D .circleci/config.yml => .circleci/config.yml +0 -13
@@ 1,13 0,0 @@
-version: '2.1'
-
-jobs:
- build:
- docker:
- - image: circleci/golang:1.12
- working_directory: ~/build
- environment:
- GO111MODULE: 'on'
- steps:
- - checkout
- - run: go test -coverprofile=cover.out -covermode=atomic .
- - run: go tool cover -func=cover.out
M README.md => README.md +7 -17
@@ 1,19 1,21 @@
clog
===
-[![GoDoc](https://godoc.org/github.com/Kochava/clog?status.svg)](https://godoc.org/github.com/Kochava/clog)
+[![GoDoc](https://pkg.go.dev/go.spiff.io/clog?status.svg)](https://pkg.go.dev/go.spiff.io/clog)
- go get github.com/Kochava/clog
+ go get go.spiff.io/clog
-clog is a simple package for initializing a [Zap][] logger and attaching it to
-a context, along with functions for logging from the context-attached logger or
-associating new fields to the logger.
+clog is a simple package for attaching a [Zap][] logger to a context, along with
+functions for logging from the context-attached logger or associating new fields
+to the logger.
Generally speaking this is a bad use of the context package, but utility won out
over passing both a context and a logger around all the time. In particular,
this is useful for passing a request-scoped logger through different
http.Handler implementations that otherwise do not support Zap.
+This is a fork of <https://github.com/Kochava/clog>.
+
[Zap]: https://go.uber.org/zap
@@ 22,18 24,6 @@ Usage
A few examples of basic usage follow.
-### Initialize a logger
-
-```go
-// Create a logger at info level with a production configuration.
-level := zap.NewAtomicLevelAt(zap.InfoLevel)
-l, err := clog.New(level, false)
-if err != nil {
- panic(err)
-}
-l.Info("Ready")
-```
-
### Attach a logger to a context
```go
M clog.go => clog.go +0 -98
@@ 1,101 1,3 @@
// Package clog is a convenience package for passing Zap loggers through
// contexts.
package clog
-
-import (
- "os"
- "path"
- "path/filepath"
- "strings"
- "unicode"
-
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-var zeroLevel = zap.AtomicLevel{}
-
-var osGetenv = os.Getenv
-
-var osArg0 = func() string {
- return os.Args[0]
-}
-
-func sanitizeEnvRune(r rune) rune {
- r = unicode.ToUpper(r)
- if r == '_' || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') {
- return r
- }
- return -1
-}
-
-func envPrefix(procname string) string {
- if procname == "" && len(os.Args) > 0 {
- procname = filepath.ToSlash(osArg0())
- }
- procname = filepath.Base(procname)
- if ext := path.Ext(procname); ext != "" {
- procname = procname[:len(procname)-len(ext)]
- }
- procname = strings.Map(sanitizeEnvRune, procname)
- if procname == "" {
- return ""
- }
- return procname + "_"
-}
-
-// GetEnvConfig returns the environment-configured logging level and whether to use JSON and debug
-// logging for procname. If procname is the empty string, os.Args[0] is used instead.
-//
-// If PROCNAME_LOG_MODE is set to "dev" (case-insensitive) then log output will be formatted for
-// reading on a console. Otherwise, logging defaults to a production configuration.
-//
-// If PROCNAME_LOG_LEVEL is set to a valid Zap logging level (info, warn, etc.), then that logging
-// level will be returned. Otherwise, the logging level defaults to zap.InfoLevel for production and
-// zap.DebugLevel for development.
-func GetEnvConfig(procname string) (level zapcore.Level, isDev bool) {
- const devEnvironment = "dev"
- prefix := envPrefix(procname)
- isDev = strings.EqualFold(osGetenv(prefix+"LOG_MODE"), devEnvironment)
- levelText := osGetenv(prefix + "LOG_LEVEL")
- if levelText != "" && level.UnmarshalText([]byte(levelText)) == nil {
- // nop
- } else if isDev {
- level = zap.DebugLevel // development
- } else {
- level = zap.InfoLevel // production
-
- }
- return
-}
-
-// NewFromEnv allocates a new zap.Logger using configuration from the environment.
-// This looks for PROCNAME_LOG_MODE and PROCNAME_LOG_LEVEL to configure the logger.
-// If LOG_MODE is not "dev", the development configuration of Zap is used.
-// Otherwise, logging is configured for production.
-func NewFromEnv(procname string, level zap.AtomicLevel) (*zap.Logger, error) {
- lvl, isDev := GetEnvConfig(procname)
- if level != zeroLevel {
- level.SetLevel(lvl)
- }
- return New(level, isDev)
-}
-
-// New allocates a new zap.Logger using configuration based on the level given and the json and
-// debug parameters, as interpreted by Config.
-func New(level zap.AtomicLevel, isDev bool) (*zap.Logger, error) {
- return Config(level, isDev).Build()
-}
-
-// Config returns a zap.Config based on the level given and the json and debug parameters. If json
-// is true, the config uses a JSON encoder. If debug is true, production limits on logging are
-// removed and the development flag is set to true.
-func Config(level zap.AtomicLevel, isDev bool) (conf zap.Config) {
- if isDev {
- conf = zap.NewDevelopmentConfig()
- } else {
- conf = zap.NewProductionConfig()
- }
- conf.Level = level
- return conf
-}
D clog_test.go => clog_test.go +0 -144
@@ 1,144 0,0 @@
-package clog
-
-import (
- "sync"
- "testing"
-
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-var arg0Lock sync.Mutex
-
-func setArg0(t *testing.T, v string) func() {
- arg0Lock.Lock()
- cur := osArg0
- osArg0 = func() string {
- t.Logf("Requested os.Args[0] (%q)", v)
- return v
- }
- return func() { defer arg0Lock.Unlock(); osArg0 = cur }
-}
-
-var getenvLock sync.Mutex
-
-func setGetenv(t *testing.T, values map[string]string) func() {
- getenvLock.Lock()
- cur := osGetenv
- osGetenv = func(k string) string {
- t.Logf("Requested os.Getenv(%q)", values[k])
- return values[k]
- }
- return func() { defer getenvLock.Unlock(); osGetenv = cur }
-}
-
-func TestEnvPrefix(t *testing.T) {
- cases := []struct {
- In, Want string
- }{
- {"./Foo_", "FOO__"},
- {"./Foo-", "FOO_"},
- {"/usr/sbin/health-checker", "HEALTHCHECKER_"},
- {"/usr/sbin/health_checker", "HEALTH_CHECKER_"},
- {"foo_bar", "FOO_BAR_"},
- }
-
- for _, c := range cases {
- t.Run("ProcnamePass="+c.In, func(t *testing.T) {
- c := c
- want, got := c.Want, envPrefix(c.In)
- if want != got {
- t.Errorf("envPrefix(%q) = %q; want %q", c.In, got, want)
- }
- })
- }
-
- for _, c := range cases {
- c := c
- t.Run("ProcnameArg0="+c.In, func(t *testing.T) {
- defer setArg0(t, c.In)()
- want, got := c.Want, envPrefix("")
- if want != got {
- t.Errorf("envPrefix(%q) = %q; want %q", c.In, got, want)
- }
- })
- }
-
- t.Run("EmptyPass", func(t *testing.T) {
- const (
- in = "/usr/bin/clog-daemon"
- want = "CLOGDAEMON_"
- )
- defer setArg0(t, in)()
- if got := envPrefix(""); want != got {
- t.Errorf("envPrefix(%q) = %q; want %q", in, got, want)
- }
- })
-
- t.Run("NoValues", func(t *testing.T) {
- const (
- in = ""
- want = ""
- )
- defer setArg0(t, in)()
- if got := envPrefix(""); want != got {
- t.Errorf("envPrefix(%q) = %q; want %q", in, got, want)
- }
- })
-}
-
-func TestGetEnvConfig(t *testing.T) {
- type values map[string]string
- cases := []struct {
- Case string
- Arg0 string
- Values values
- Level zapcore.Level
- IsDev bool
- }{
- {
- "Defaults",
- "",
- nil,
- zap.InfoLevel,
- false,
- },
- {
- "EmptyName",
- "",
- values{"LOG_MODE": "dev", "LOG_LEVEL": "warn"},
- zap.WarnLevel,
- true,
- },
- {
- "InvalidLevel",
- "",
- values{"LOG_MODE": "prod", "LOG_LEVEL": "WARNING"},
- zap.InfoLevel,
- false,
- },
- {
- "NamedProc",
- "/usr/local/bin/daemon",
- values{"DAEMON_LOG_MODE": "dev", "DAEMON_LOG_LEVEL": "fatal"},
- zap.FatalLevel,
- true,
- },
- }
-
- for _, c := range cases {
- c := c
- t.Run(c.Case, func(t *testing.T) {
- defer setArg0(t, c.Arg0)()
- defer setGetenv(t, c.Values)()
-
- level, isDev := GetEnvConfig("")
- if level != c.Level {
- t.Errorf("level = %v; want %v", level, c.Level)
- }
- if isDev != c.IsDev {
- t.Errorf("isDev = %t; want %t", isDev, c.IsDev)
- }
- })
- }
-}
M example_test.go => example_test.go +2 -3
@@ 3,14 3,13 @@ package clog_test
import (
"context"
- "github.com/Kochava/clog"
+ "go.spiff.io/clog"
"go.uber.org/zap"
)
func ExampleNew() {
// Create a logger at info level with a production configuration.
- level := zap.NewAtomicLevelAt(zap.InfoLevel)
- l, err := clog.New(level, false)
+ l, err := zap.NewProduction()
if err != nil {
panic(err)
}
M go.mod => go.mod +3 -6
@@ 1,11 1,8 @@
-module github.com/Kochava/clog
+module go.spiff.io/clog
-go 1.12
+go 1.15
require (
github.com/pkg/errors v0.9.1 // indirect
- github.com/stretchr/testify v1.4.0 // indirect
- go.uber.org/atomic v1.3.2 // indirect
- go.uber.org/multierr v1.1.0 // indirect
- go.uber.org/zap v1.9.1
+ go.uber.org/zap v1.16.0
)
M go.sum => go.sum +45 -6
@@ 1,19 1,58 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
-go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
-go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
-go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
-go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
-go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=
+go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
+go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
+go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
D stdlog.go => stdlog.go +0 -77
@@ 1,77 0,0 @@
-package clog
-
-import (
- "fmt"
- "strings"
-
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-// StdLogger is a logger that implements most methods used by "log" stdlib users. Print-ed logs are
-// recorded at Info level.
-type StdLogger struct{ log *zap.Logger }
-
-// NewStdLogger creats a new StdLogger attached to the given zap.Logger. If logger is nil,
-// NewStdLogger returns nil as well.
-func NewStdLogger(logger *zap.Logger) *StdLogger {
- if logger == nil {
- return nil
- }
- return &StdLogger{logger.WithOptions(zap.AddCallerSkip(1))}
-}
-
-// With returns a copy of this StdLogger with additional Zap fields.
-func (l *StdLogger) With(fields ...zapcore.Field) *StdLogger {
- return &StdLogger{l.log.With(fields...)}
-}
-
-// WithOptions returns a copy of this StdLogger with additional Zap options.
-func (l *StdLogger) WithOptions(opts ...zap.Option) *StdLogger {
- return &StdLogger{l.log.WithOptions(opts...)}
-}
-
-// Panic writes a panic-level fmt.Sprint-formatted log message.
-func (l *StdLogger) Panic(args ...interface{}) {
- l.log.Panic(fmt.Sprint(args...))
-}
-
-// Panicln writes a panic-level fmt.Sprintln-formatted log message.
-func (l *StdLogger) Panicln(args ...interface{}) {
- l.log.Panic(strings.TrimSuffix(fmt.Sprintln(args...), "\n"))
-}
-
-// Panicf writes a panic-level fmt.Sprintf-formatted log message.
-func (l *StdLogger) Panicf(format string, args ...interface{}) {
- l.log.Panic(fmt.Sprintf(format, args...))
-}
-
-// Fatal writes a fatal-level fmt.Sprint-formatted log message.
-func (l *StdLogger) Fatal(args ...interface{}) {
- l.log.Fatal(fmt.Sprint(args...))
-}
-
-// Fatalln writes a fatal-level fmt.Sprintln-formatted log message.
-func (l *StdLogger) Fatalln(args ...interface{}) {
- l.log.Fatal(strings.TrimSuffix(fmt.Sprintln(args...), "\n"))
-}
-
-// Fatalf writes a fatal-level fmt.Sprintf-formatted log message.
-func (l *StdLogger) Fatalf(format string, args ...interface{}) {
- l.log.Fatal(fmt.Sprintf(format, args...))
-}
-
-// Print writes an info-level fmt.Sprint-formatted log message.
-func (l *StdLogger) Print(args ...interface{}) {
- l.log.Info(fmt.Sprint(args...))
-}
-
-// Println writes an info-level fmt.Sprintln-formatted log message.
-func (l *StdLogger) Println(args ...interface{}) {
- l.log.Info(strings.TrimSuffix(fmt.Sprintln(args...), "\n"))
-}
-
-// Printf writes an info-level fmt.Sprintf-formatted log message.
-func (l *StdLogger) Printf(format string, args ...interface{}) {
- l.log.Info(fmt.Sprintf(format, args...))
-}