MM-22273 New auditing system (phase 1) (#13967)

* New auditing API outputting to syslog via TLS

* New config section for specifying remote syslog server IP, port, and cert.

* Legacy audit API retained for access history feature
Этот коммит содержится в:
Doug Lauder
2020-03-12 15:50:21 -04:00
коммит произвёл GitHub
родитель bd1e7f2265
Коммит 4ac0619c90
156 изменённых файлов: 16991 добавлений и 49 удалений

12
vendor/github.com/wiggin77/cfg/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,12 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

5
vendor/github.com/wiggin77/cfg/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,5 @@
language: go
sudo: false
before_script:
- go vet ./...

21
vendor/github.com/wiggin77/cfg/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 wiggin77
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

43
vendor/github.com/wiggin77/cfg/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
# cfg
[![GoDoc](https://godoc.org/github.com/wiggin77/cfg?status.svg)](https://godoc.org/github.com/wiggin77/cfg)
[![Build Status](https://travis-ci.org/wiggin77/cfg.svg?branch=master)](https://travis-ci.org/wiggin77/cfg)
Go package for app configuration. Supports chained configuration sources for multiple levels of defaults.
Includes APIs for loading Linux style configuration files (name/value pairs) or INI files, map based properties,
or easily create new configuration sources (e.g. load from database).
Supports monitoring configuration sources for changes, hot loading properties, and notifying listeners of changes.
## Usage
```Go
config := &cfg.Config{}
defer config.Shutdown() // stops monitoring
// load file via filespec string, os.File
src, err := Config.NewSrcFileFromFilespec("./myfile.conf")
if err != nil {
return err
}
// add src to top of chain, meaning first searched
cfg.PrependSource(src)
// fetch prop 'retries', default to 3 if not found
val := config.Int("retries", 3)
```
See [example](./example_test.go) for more complete example, including listening for configuration changes.
Config API parses the following data types:
| type | method | example property values |
| ------- | ------ | -------- |
| string | Config.String | test, "" |
| int | Config.Int | -1, 77, 0 |
| int64 | Config.Int64 | -9223372036854775, 372036854775808 |
| float64 | Config.Float64 | -77.3456, 95642331.1 |
| bool | Config.Bool | T,t,true,True,1,0,False,false,f,F |
| time.Duration | Config.Duration | "10ms", "2 hours", "5 min" * |
\* Units of measure supported: ms, sec, min, hour, day, week, year.

366
vendor/github.com/wiggin77/cfg/config.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,366 @@
package cfg
import (
"errors"
"fmt"
"strconv"
"strings"
"sync"
"time"
"github.com/wiggin77/cfg/timeconv"
)
// ErrNotFound returned when an operation is attempted on a
// resource that doesn't exist, such as fetching a non-existing
// property name.
var ErrNotFound = errors.New("not found")
type sourceEntry struct {
src Source
props map[string]string
}
// Config provides methods for retrieving property values from one or more
// configuration sources.
type Config struct {
mutexSrc sync.RWMutex
mutexListeners sync.RWMutex
srcs []*sourceEntry
chgListeners []ChangedListener
shutdown chan interface{}
wantPanicOnError bool
}
// PrependSource inserts one or more `Sources` at the beginning of
// the list of sources such that the first source will be the
// source checked first when resolving a property value.
func (config *Config) PrependSource(srcs ...Source) {
arr := config.wrapSources(srcs...)
config.mutexSrc.Lock()
if config.shutdown == nil {
config.shutdown = make(chan interface{})
}
config.srcs = append(arr, config.srcs...)
config.mutexSrc.Unlock()
for _, se := range arr {
if _, ok := se.src.(SourceMonitored); ok {
config.monitor(se)
}
}
}
// AppendSource appends one or more `Sources` at the end of
// the list of sources such that the last source will be the
// source checked last when resolving a property value.
func (config *Config) AppendSource(srcs ...Source) {
arr := config.wrapSources(srcs...)
config.mutexSrc.Lock()
if config.shutdown == nil {
config.shutdown = make(chan interface{})
}
config.srcs = append(config.srcs, arr...)
config.mutexSrc.Unlock()
for _, se := range arr {
if _, ok := se.src.(SourceMonitored); ok {
config.monitor(se)
}
}
}
// wrapSources wraps one or more Source's and returns
// them as an array of `sourceEntry`.
func (config *Config) wrapSources(srcs ...Source) []*sourceEntry {
arr := make([]*sourceEntry, 0, len(srcs))
for _, src := range srcs {
se := &sourceEntry{src: src}
config.reloadProps(se)
arr = append(arr, se)
}
return arr
}
// SetWantPanicOnError sets the flag determining if Config
// should panic when `GetProps` or `GetLastModified` errors
// for a `Source`.
func (config *Config) SetWantPanicOnError(b bool) {
config.mutexSrc.Lock()
config.wantPanicOnError = b
config.mutexSrc.Unlock()
}
// ShouldPanicOnError gets the flag determining if Config
// should panic when `GetProps` or `GetLastModified` errors
// for a `Source`.
func (config *Config) ShouldPanicOnError() (b bool) {
config.mutexSrc.RLock()
b = config.wantPanicOnError
config.mutexSrc.RUnlock()
return b
}
// getProp returns the value of a named property.
// Each `Source` is checked, in the order created by adding via
// `AppendSource` and `PrependSource`, until a value for the
// property is found.
func (config *Config) getProp(name string) (val string, ok bool) {
config.mutexSrc.RLock()
defer config.mutexSrc.RUnlock()
var s string
for _, se := range config.srcs {
if se.props != nil {
if s, ok = se.props[name]; ok {
val = strings.TrimSpace(s)
return
}
}
}
return
}
// String returns the value of the named prop as a string.
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
func (config *Config) String(name string, def string) (val string, err error) {
if v, ok := config.getProp(name); ok {
val = v
err = nil
return
}
err = ErrNotFound
val = def
return
}
// Int returns the value of the named prop as an `int`.
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
//
// See config.String
func (config *Config) Int(name string, def int) (val int, err error) {
var s string
if s, err = config.String(name, ""); err == nil {
var i int64
if i, err = strconv.ParseInt(s, 10, 32); err == nil {
val = int(i)
}
}
if err != nil {
val = def
}
return
}
// Int64 returns the value of the named prop as an `int64`.
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
//
// See config.String
func (config *Config) Int64(name string, def int64) (val int64, err error) {
var s string
if s, err = config.String(name, ""); err == nil {
val, err = strconv.ParseInt(s, 10, 64)
}
if err != nil {
val = def
}
return
}
// Float64 returns the value of the named prop as a `float64`.
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
//
// See config.String
func (config *Config) Float64(name string, def float64) (val float64, err error) {
var s string
if s, err = config.String(name, ""); err == nil {
val, err = strconv.ParseFloat(s, 64)
}
if err != nil {
val = def
}
return
}
// Bool returns the value of the named prop as a `bool`.
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
//
// Supports (t, true, 1, y, yes) for true, and (f, false, 0, n, no) for false,
// all case-insensitive.
//
// See config.String
func (config *Config) Bool(name string, def bool) (val bool, err error) {
var s string
if s, err = config.String(name, ""); err == nil {
switch strings.ToLower(s) {
case "t", "true", "1", "y", "yes":
val = true
case "f", "false", "0", "n", "no":
val = false
default:
err = errors.New("invalid syntax")
}
}
if err != nil {
val = def
}
return
}
// Duration returns the value of the named prop as a `time.Duration`, representing
// a span of time.
//
// Units of measure are supported: ms, sec, min, hour, day, week, year.
// See config.UnitsToMillis for a complete list of units supported.
//
// If the property is not found then the supplied default `def`
// and `ErrNotFound` are returned.
//
// See config.String
func (config *Config) Duration(name string, def time.Duration) (val time.Duration, err error) {
var s string
if s, err = config.String(name, ""); err == nil {
var ms int64
ms, err = timeconv.ParseMilliseconds(s)
val = time.Duration(ms) * time.Millisecond
}
if err != nil {
val = def
}
return
}
// AddChangedListener adds a listener that will receive notifications
// whenever one or more property values change within the config.
func (config *Config) AddChangedListener(l ChangedListener) {
config.mutexListeners.Lock()
defer config.mutexListeners.Unlock()
config.chgListeners = append(config.chgListeners, l)
}
// RemoveChangedListener removes all instances of a ChangedListener.
// Returns `ErrNotFound` if the listener was not present.
func (config *Config) RemoveChangedListener(l ChangedListener) error {
config.mutexListeners.Lock()
defer config.mutexListeners.Unlock()
dest := make([]ChangedListener, 0, len(config.chgListeners))
err := ErrNotFound
// Remove all instances of the listener by
// copying list while filtering.
for _, s := range config.chgListeners {
if s != l {
dest = append(dest, s)
} else {
err = nil
}
}
config.chgListeners = dest
return err
}
// Shutdown can be called to stop monitoring of all config sources.
func (config *Config) Shutdown() {
config.mutexSrc.RLock()
defer config.mutexSrc.RUnlock()
if config.shutdown != nil {
close(config.shutdown)
}
}
// onSourceChanged is called whenever one or more properties of a
// config source has changed.
func (config *Config) onSourceChanged(src SourceMonitored) {
defer func() {
if p := recover(); p != nil {
fmt.Println(p)
}
}()
config.mutexListeners.RLock()
defer config.mutexListeners.RUnlock()
for _, l := range config.chgListeners {
l.ConfigChanged(config, src)
}
}
// monitor periodically checks a config source for changes.
func (config *Config) monitor(se *sourceEntry) {
go func(se *sourceEntry, shutdown <-chan interface{}) {
var src SourceMonitored
var ok bool
if src, ok = se.src.(SourceMonitored); !ok {
return
}
paused := false
last := time.Time{}
freq := src.GetMonitorFreq()
if freq <= 0 {
paused = true
freq = 10
last, _ = src.GetLastModified()
}
timer := time.NewTimer(freq)
for {
select {
case <-timer.C:
if !paused {
if latest, err := src.GetLastModified(); err != nil {
if config.ShouldPanicOnError() {
panic(fmt.Sprintf("error <%v> getting last modified for %v", err, src))
}
} else {
if last.Before(latest) {
last = latest
config.reloadProps(se)
// TODO: calc diff and provide detailed changes
config.onSourceChanged(src)
}
}
}
freq = src.GetMonitorFreq()
if freq <= 0 {
paused = true
freq = 10
} else {
paused = false
}
timer.Reset(freq)
case <-shutdown:
// stop the timer and exit
if !timer.Stop() {
<-timer.C
}
return
}
}
}(se, config.shutdown)
}
// reloadProps causes a Source to reload its properties.
func (config *Config) reloadProps(se *sourceEntry) {
config.mutexSrc.Lock()
defer config.mutexSrc.Unlock()
m, err := se.src.GetProps()
if err != nil {
if config.wantPanicOnError {
panic(fmt.Sprintf("GetProps error for %v", se.src))
}
return
}
se.props = make(map[string]string)
for k, v := range m {
se.props[k] = v
}
}

5
vendor/github.com/wiggin77/cfg/go.mod сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,5 @@
module github.com/wiggin77/cfg
go 1.12
require github.com/wiggin77/merror v1.0.2

2
vendor/github.com/wiggin77/cfg/go.sum сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,2 @@
github.com/wiggin77/merror v1.0.2 h1:V0nH9eFp64ASyaXC+pB5WpvBoCg7NUwvaCSKdzlcHqw=
github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg=

167
vendor/github.com/wiggin77/cfg/ini/ini.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,167 @@
package ini
import (
"fmt"
"io"
"io/ioutil"
"os"
"sync"
"time"
)
// Ini provides parsing and querying of INI format or simple name/value pairs
// such as a simple config file.
// A name/value pair format is just an INI with no sections, and properties can
// be queried using an empty section name.
type Ini struct {
mutex sync.RWMutex
m map[string]*Section
lm time.Time
}
// LoadFromFilespec loads an INI file from string containing path and filename.
func (ini *Ini) LoadFromFilespec(filespec string) error {
f, err := os.Open(filespec)
if err != nil {
return err
}
return ini.LoadFromFile(f)
}
// LoadFromFile loads an INI file from `os.File`.
func (ini *Ini) LoadFromFile(file *os.File) error {
fi, err := file.Stat()
if err != nil {
return err
}
lm := fi.ModTime()
if err := ini.LoadFromReader(file); err != nil {
return err
}
ini.lm = lm
return nil
}
// LoadFromReader loads an INI file from an `io.Reader`.
func (ini *Ini) LoadFromReader(reader io.Reader) error {
data, err := ioutil.ReadAll(reader)
if err != nil {
return err
}
return ini.LoadFromString(string(data))
}
// LoadFromString parses an INI from a string .
func (ini *Ini) LoadFromString(s string) error {
m, err := getSections(s)
if err != nil {
return err
}
ini.mutex.Lock()
ini.m = m
ini.lm = time.Now()
ini.mutex.Unlock()
return nil
}
// GetLastModified returns the last modified timestamp of the
// INI contents.
func (ini *Ini) GetLastModified() time.Time {
return ini.lm
}
// GetSectionNames returns the names of all sections in this INI.
// Note, the returned section names are a snapshot in time, meaning
// other goroutines may change the contents of this INI as soon as
// the method returns.
func (ini *Ini) GetSectionNames() []string {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
arr := make([]string, 0, len(ini.m))
for key := range ini.m {
arr = append(arr, key)
}
return arr
}
// GetKeys returns the names of all keys in the specified section.
// Note, the returned key names are a snapshot in time, meaning other
// goroutines may change the contents of this INI as soon as the
// method returns.
func (ini *Ini) GetKeys(sectionName string) ([]string, error) {
sec, err := ini.getSection(sectionName)
if err != nil {
return nil, err
}
return sec.getKeys(), nil
}
// getSection returns the named section.
func (ini *Ini) getSection(sectionName string) (*Section, error) {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
sec, ok := ini.m[sectionName]
if !ok {
return nil, fmt.Errorf("section '%s' not found", sectionName)
}
return sec, nil
}
// GetFlattenedKeys returns all section names plus keys as one
// flattened array.
func (ini *Ini) GetFlattenedKeys() []string {
ini.mutex.RLock()
defer ini.mutex.RUnlock()
arr := make([]string, 0, len(ini.m)*2)
for _, section := range ini.m {
keys := section.getKeys()
for _, key := range keys {
name := section.GetName()
if name != "" {
key = name + "." + key
}
arr = append(arr, key)
}
}
return arr
}
// GetProp returns the value of the specified key in the named section.
func (ini *Ini) GetProp(section string, key string) (val string, ok bool) {
sec, err := ini.getSection(section)
if err != nil {
return val, false
}
return sec.GetProp(key)
}
// ToMap returns a flattened map of the section name plus keys mapped
// to values.
func (ini *Ini) ToMap() map[string]string {
m := make(map[string]string)
ini.mutex.RLock()
defer ini.mutex.RUnlock()
for _, section := range ini.m {
for _, key := range section.getKeys() {
val, ok := section.GetProp(key)
if ok {
name := section.GetName()
var mapkey string
if name != "" {
mapkey = name + "." + key
} else {
mapkey = key
}
m[mapkey] = val
}
}
}
return m
}

142
vendor/github.com/wiggin77/cfg/ini/parser.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,142 @@
package ini
import (
"fmt"
"strings"
"github.com/wiggin77/merror"
)
// LF is linefeed
const LF byte = 0x0A
// CR is carriage return
const CR byte = 0x0D
// getSections parses an INI formatted string, or string containing just name/value pairs,
// returns map of `Section`'s.
//
// Any name/value pairs appearing before a section name are added to the section named
// with an empty string (""). Also true for Linux-style config files where all props
// are outside a named section.
//
// Any errors encountered are aggregated and returned, along with the partially parsed
// sections.
func getSections(str string) (map[string]*Section, error) {
merr := merror.New()
mapSections := make(map[string]*Section)
lines := buildLineArray(str)
section := newSection("")
for _, line := range lines {
name, ok := parseSection(line)
if ok {
// A section name encountered. Stop processing the current one.
// Don't add the current section to the map if the section name is blank
// and the prop map is empty.
nameCurr := section.GetName()
if nameCurr != "" || section.hasKeys() {
mapSections[nameCurr] = section
}
// Start processing a new section.
section = newSection(name)
} else {
// Parse the property and add to the current section, or ignore if comment.
if k, v, comment, err := parseProp(line); !comment && err == nil {
section.setProp(k, v)
} else if err != nil {
merr.Append(err) // aggregate errors
}
}
}
// If the current section is not empty, add it.
if section.hasKeys() {
mapSections[section.GetName()] = section
}
return mapSections, merr.ErrorOrNil()
}
// buildLineArray parses the given string buffer and creates a list of strings,
// one for each line in the string buffer.
//
// A line is considered to be terminated by any one of a line feed ('\n'),
// a carriage return ('\r'), or a carriage return followed immediately by a
// linefeed.
//
// Lines prefixed with ';' or '#' are considered comments and skipped.
func buildLineArray(str string) []string {
arr := make([]string, 0, 10)
str = str + "\n"
iLen := len(str)
iPos, iBegin := 0, 0
var ch byte
for iPos < iLen {
ch = str[iPos]
if ch == LF || ch == CR {
sub := str[iBegin:iPos]
sub = strings.TrimSpace(sub)
if sub != "" && !strings.HasPrefix(sub, ";") && !strings.HasPrefix(sub, "#") {
arr = append(arr, sub)
}
iPos++
if ch == CR && iPos < iLen && str[iPos] == LF {
iPos++
}
iBegin = iPos
} else {
iPos++
}
}
return arr
}
// parseSection parses the specified string for a section name enclosed in square brackets.
// Returns the section name found, or `ok=false` if `str` is not a section header.
func parseSection(str string) (name string, ok bool) {
str = strings.TrimSpace(str)
if !strings.HasPrefix(str, "[") {
return "", false
}
iCloser := strings.Index(str, "]")
if iCloser == -1 {
return "", false
}
return strings.TrimSpace(str[1:iCloser]), true
}
// parseProp parses the specified string and extracts a key/value pair.
//
// If the string is a comment (prefixed with ';' or '#') then `comment=true`
// and key will be empty.
func parseProp(str string) (key string, val string, comment bool, err error) {
iLen := len(str)
iEqPos := strings.Index(str, "=")
if iEqPos == -1 {
return "", "", false, fmt.Errorf("not a key/value pair:'%s'", str)
}
key = str[0:iEqPos]
key = strings.TrimSpace(key)
if iEqPos+1 < iLen {
val = str[iEqPos+1:]
val = strings.TrimSpace(val)
}
// Check that the key has at least 1 char.
if key == "" {
return "", "", false, fmt.Errorf("key is empty for '%s'", str)
}
// Check if this line is a comment that just happens
// to have an equals sign in it. Not an error, but not a
// useable line either.
if strings.HasPrefix(key, ";") || strings.HasPrefix(key, "#") {
key = ""
val = ""
comment = true
}
return key, val, comment, err
}

109
vendor/github.com/wiggin77/cfg/ini/section.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,109 @@
package ini
import (
"fmt"
"strings"
"sync"
)
// Section represents a section in an INI file. The section has a name, which is
// enclosed in square brackets in the file. The section also has an array of
// key/value pairs.
type Section struct {
name string
props map[string]string
mtx sync.RWMutex
}
func newSection(name string) *Section {
sec := &Section{}
sec.name = name
sec.props = make(map[string]string)
return sec
}
// addLines addes an array of strings containing name/value pairs
// of the format `key=value`.
//func addLines(lines []string) {
// TODO
//}
// GetName returns the name of the section.
func (sec *Section) GetName() (name string) {
sec.mtx.RLock()
name = sec.name
sec.mtx.RUnlock()
return
}
// GetProp returns the value associated with the given key, or
// `ok=false` if key does not exist.
func (sec *Section) GetProp(key string) (val string, ok bool) {
sec.mtx.RLock()
val, ok = sec.props[key]
sec.mtx.RUnlock()
return
}
// SetProp sets the value associated with the given key.
func (sec *Section) setProp(key string, val string) {
sec.mtx.Lock()
sec.props[key] = val
sec.mtx.Unlock()
}
// hasKeys returns true if there are one or more properties in
// this section.
func (sec *Section) hasKeys() (b bool) {
sec.mtx.RLock()
b = len(sec.props) > 0
sec.mtx.RUnlock()
return
}
// getKeys returns an array containing all keys in this section.
func (sec *Section) getKeys() []string {
sec.mtx.RLock()
defer sec.mtx.RUnlock()
arr := make([]string, len(sec.props))
idx := 0
for k := range sec.props {
arr[idx] = k
idx++
}
return arr
}
// combine the given section with this one.
func (sec *Section) combine(sec2 *Section) {
sec.mtx.Lock()
sec2.mtx.RLock()
defer sec.mtx.Unlock()
defer sec2.mtx.RUnlock()
for k, v := range sec2.props {
sec.props[k] = v
}
}
// String returns a string representation of this section.
func (sec *Section) String() string {
return fmt.Sprintf("[%s]\n%s", sec.GetName(), sec.StringPropsOnly())
}
// StringPropsOnly returns a string representation of this section
// without the section header.
func (sec *Section) StringPropsOnly() string {
sec.mtx.RLock()
defer sec.mtx.RUnlock()
sb := &strings.Builder{}
for k, v := range sec.props {
sb.WriteString(k)
sb.WriteString("=")
sb.WriteString(v)
sb.WriteString("\n")
}
return sb.String()
}

11
vendor/github.com/wiggin77/cfg/listener.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,11 @@
package cfg
// ChangedListener interface is for receiving notifications
// when one or more properties within monitored config sources
// (SourceMonitored) have changed values.
type ChangedListener interface {
// Changed is called when one or more properties in a `SourceMonitored` has a
// changed value.
ConfigChanged(cfg *Config, src SourceMonitored)
}

11
vendor/github.com/wiggin77/cfg/nocopy.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,11 @@
package cfg
// noCopy may be embedded into structs which must not be copied
// after the first use.
//
// See https://golang.org/issues/8005#issuecomment-190753527
// for details.
type noCopy struct{}
// Lock is a no-op used by -copylocks checker from `go vet`.
func (*noCopy) Lock() {}

58
vendor/github.com/wiggin77/cfg/source.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,58 @@
package cfg
import (
"sync"
"time"
)
// Source is the interface required for any source of name/value pairs.
type Source interface {
// GetProps fetches all the properties from a source and returns
// them as a map.
GetProps() (map[string]string, error)
}
// SourceMonitored is the interface required for any config source that is
// monitored for changes.
type SourceMonitored interface {
Source
// GetLastModified returns the time of the latest modification to any
// property value within the source. If a source does not support
// modifying properties at runtime then the zero value for `Time`
// should be returned to ensure reload events are not generated.
GetLastModified() (time.Time, error)
// GetMonitorFreq returns the frequency as a `time.Duration` between
// checks for changes to this config source.
//
// Returning zero (or less) will temporarily suspend calls to `GetLastModified`
// and `GetMonitorFreq` will be called every 10 seconds until resumed, after which
// `GetMontitorFreq` will be called at a frequency roughly equal to the `time.Duration`
// returned.
GetMonitorFreq() time.Duration
}
// AbstractSourceMonitor can be embedded in a custom `Source` to provide the
// basic plumbing for monitor frequency.
type AbstractSourceMonitor struct {
mutex sync.RWMutex
freq time.Duration
}
// GetMonitorFreq returns the frequency as a `time.Duration` between
// checks for changes to this config source.
func (asm *AbstractSourceMonitor) GetMonitorFreq() (freq time.Duration) {
asm.mutex.RLock()
freq = asm.freq
asm.mutex.RUnlock()
return
}
// SetMonitorFreq sets the frequency between checks for changes to this config source.
func (asm *AbstractSourceMonitor) SetMonitorFreq(freq time.Duration) {
asm.mutex.Lock()
asm.freq = freq
asm.mutex.Unlock()
}

63
vendor/github.com/wiggin77/cfg/srcfile.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,63 @@
package cfg
import (
"os"
"time"
"github.com/wiggin77/cfg/ini"
)
// SrcFile is a configuration `Source` backed by a file containing
// name/value pairs or INI format.
type SrcFile struct {
AbstractSourceMonitor
ini ini.Ini
file *os.File
}
// NewSrcFileFromFilespec creates a new SrcFile with the specified filespec.
func NewSrcFileFromFilespec(filespec string) (*SrcFile, error) {
file, err := os.Open(filespec)
if err != nil {
return nil, err
}
return NewSrcFile(file)
}
// NewSrcFile creates a new SrcFile with the specified os.File.
func NewSrcFile(file *os.File) (*SrcFile, error) {
sf := &SrcFile{}
sf.freq = time.Minute
sf.file = file
if err := sf.ini.LoadFromFile(file); err != nil {
return nil, err
}
return sf, nil
}
// GetProps fetches all the properties from a source and returns
// them as a map.
func (sf *SrcFile) GetProps() (map[string]string, error) {
lm, err := sf.GetLastModified()
if err != nil {
return nil, err
}
// Check if we need to reload.
if sf.ini.GetLastModified() != lm {
if err := sf.ini.LoadFromFile(sf.file); err != nil {
return nil, err
}
}
return sf.ini.ToMap(), nil
}
// GetLastModified returns the time of the latest modification to any
// property value within the source.
func (sf *SrcFile) GetLastModified() (time.Time, error) {
fi, err := sf.file.Stat()
if err != nil {
return time.Now(), err
}
return fi.ModTime(), nil
}

78
vendor/github.com/wiggin77/cfg/srcmap.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,78 @@
package cfg
import (
"time"
)
// SrcMap is a configuration `Source` backed by a simple map.
type SrcMap struct {
AbstractSourceMonitor
m map[string]string
lm time.Time
}
// NewSrcMap creates an empty `SrcMap`.
func NewSrcMap() *SrcMap {
sm := &SrcMap{}
sm.m = make(map[string]string)
sm.lm = time.Now()
sm.freq = time.Minute
return sm
}
// NewSrcMapFromMap creates a `SrcMap` containing a copy of the
// specified map.
func NewSrcMapFromMap(mapIn map[string]string) *SrcMap {
sm := NewSrcMap()
sm.PutAll(mapIn)
return sm
}
// Put inserts or updates a value in the `SrcMap`.
func (sm *SrcMap) Put(key string, val string) {
sm.mutex.Lock()
sm.m[key] = val
sm.lm = time.Now()
sm.mutex.Unlock()
}
// PutAll inserts a copy of `mapIn` into the `SrcMap`
func (sm *SrcMap) PutAll(mapIn map[string]string) {
sm.mutex.Lock()
defer sm.mutex.Unlock()
for k, v := range mapIn {
sm.m[k] = v
}
sm.lm = time.Now()
}
// GetProps fetches all the properties from a source and returns
// them as a map.
func (sm *SrcMap) GetProps() (m map[string]string, err error) {
sm.mutex.RLock()
m = sm.m
sm.mutex.RUnlock()
return
}
// GetLastModified returns the time of the latest modification to any
// property value within the source. If a source does not support
// modifying properties at runtime then the zero value for `Time`
// should be returned to ensure reload events are not generated.
func (sm *SrcMap) GetLastModified() (last time.Time, err error) {
sm.mutex.RLock()
last = sm.lm
sm.mutex.RUnlock()
return
}
// GetMonitorFreq returns the frequency as a `time.Duration` between
// checks for changes to this config source. Defaults to 1 minute
// unless changed with `SetMonitorFreq`.
func (sm *SrcMap) GetMonitorFreq() (freq time.Duration) {
sm.mutex.RLock()
freq = sm.freq
sm.mutex.RUnlock()
return
}

108
vendor/github.com/wiggin77/cfg/timeconv/parse.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,108 @@
package timeconv
import (
"fmt"
"math"
"regexp"
"strconv"
"strings"
)
// MillisPerSecond is the number of millseconds per second.
const MillisPerSecond int64 = 1000
// MillisPerMinute is the number of millseconds per minute.
const MillisPerMinute int64 = MillisPerSecond * 60
// MillisPerHour is the number of millseconds per hour.
const MillisPerHour int64 = MillisPerMinute * 60
// MillisPerDay is the number of millseconds per day.
const MillisPerDay int64 = MillisPerHour * 24
// MillisPerWeek is the number of millseconds per week.
const MillisPerWeek int64 = MillisPerDay * 7
// MillisPerYear is the approximate number of millseconds per year.
const MillisPerYear int64 = MillisPerDay*365 + int64((float64(MillisPerDay) * 0.25))
// ParseMilliseconds parses a string containing a number plus
// a unit of measure for time and returns the number of milliseconds
// it represents.
//
// Example:
// * "1 second" returns 1000
// * "1 minute" returns 60000
// * "1 hour" returns 3600000
//
// See config.UnitsToMillis for a list of supported units of measure.
func ParseMilliseconds(str string) (int64, error) {
s := strings.TrimSpace(str)
reg := regexp.MustCompile("([0-9\\.\\-+]*)(.*)")
matches := reg.FindStringSubmatch(s)
if matches == nil || len(matches) < 1 || matches[1] == "" {
return 0, fmt.Errorf("invalid syntax - '%s'", s)
}
digits := matches[1]
units := "ms"
if len(matches) > 1 && matches[2] != "" {
units = matches[2]
}
fDigits, err := strconv.ParseFloat(digits, 64)
if err != nil {
return 0, err
}
msPerUnit, err := UnitsToMillis(units)
if err != nil {
return 0, err
}
// Check for overflow.
fms := float64(msPerUnit) * fDigits
if fms > math.MaxInt64 || fms < math.MinInt64 {
return 0, fmt.Errorf("out of range - '%s' overflows", s)
}
ms := int64(fms)
return ms, nil
}
// UnitsToMillis returns the number of milliseconds represented by the specified unit of measure.
//
// Example:
// * "second" returns 1000 <br/>
// * "minute" returns 60000 <br/>
// * "hour" returns 3600000 <br/>
//
// Supported units of measure:
// * "milliseconds", "millis", "ms", "millisecond"
// * "seconds", "sec", "s", "second"
// * "minutes", "mins", "min", "m", "minute"
// * "hours", "h", "hour"
// * "days", "d", "day"
// * "weeks", "w", "week"
// * "years", "y", "year"
func UnitsToMillis(units string) (ms int64, err error) {
u := strings.TrimSpace(units)
u = strings.ToLower(u)
switch u {
case "milliseconds", "millisecond", "millis", "ms":
ms = 1
case "seconds", "second", "sec", "s":
ms = MillisPerSecond
case "minutes", "minute", "mins", "min", "m":
ms = MillisPerMinute
case "hours", "hour", "h":
ms = MillisPerHour
case "days", "day", "d":
ms = MillisPerDay
case "weeks", "week", "w":
ms = MillisPerWeek
case "years", "year", "y":
ms = MillisPerYear
default:
err = fmt.Errorf("invalid syntax - '%s' not a supported unit of measure", u)
}
return
}

36
vendor/github.com/wiggin77/logr/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
debug
dynip
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Output of profiler
*.prof
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
# IntelliJ config
.idea
# log files
*.log
# transient directories
vendor
output
build
app
logs
# test apps
test/cmd/testapp1/testapp1
test/cmd/simple/simple

4
vendor/github.com/wiggin77/logr/.travis.yml сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,4 @@
language: go
sudo: false
go:
- 1.x

21
vendor/github.com/wiggin77/logr/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 wiggin77
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

194
vendor/github.com/wiggin77/logr/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,194 @@
# logr
[![GoDoc](https://godoc.org/github.com/wiggin77/logr?status.svg)](http://godoc.org/github.com/wiggin77/logr)
[![Build Status](https://api.travis-ci.com/wiggin77/logr.svg?branch=master)](https://travis-ci.com/wiggin77/logr)
[![Report Card](https://goreportcard.com/badge/github.com/wiggin77/logr)](https://goreportcard.com/report/github.com/wiggin77/logr)
Logr is a fully asynchronous, contextual logger for Go.
It is very much inspired by [Logrus](https://github.com/sirupsen/logrus) but addresses two issues:
1. Logr is fully asynchronous, meaning that all formatting and writing is done in the background. Latency sensitive applications benefit from not waiting for logging to complete.
2. Logr provides custom filters which provide more flexibility than Trace, Debug, Info... levels. If you need to temporarily increase verbosity of logging while tracking down a problem you can avoid the fire-hose that typically comes from Debug or Trace by using custom filters.
## Concepts
<!-- markdownlint-disable MD033 -->
| entity | description |
| ------ | ----------- |
| Logr | Engine instance typically instantiated once; used to configure logging.<br>```lgr := &Logr{}```|
| Logger | Provides contextual logging via fields; lightweight, can be created once and accessed globally or create on demand.<br>```logger := lgr.NewLogger()```<br>```logger2 := logger.WithField("user", "Sam")```|
| Target | A destination for log items such as console, file, database or just about anything that can be written to. Each target has its own filter/level and formatter, and any number of targets can be added to a Logr. Targets for syslog and any io.Writer are built-in and it is easy to create your own. You can also use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).|
| Filter | Determines which logging calls get written versus filtered out. Also determines which logging calls generate a stack trace.<br>```filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Fatal}```|
| Formatter | Formats the output. Logr includes built-in formatters for JSON and plain text with delimiters. It is easy to create your own formatters or you can also use any [Logrus formatters](https://github.com/sirupsen/logrus#formatters) via a simple [adapter](https://github.com/wiggin77/logrus4logr).<br>```formatter := &format.Plain{Delim: " \| "}```|
## Usage
```go
// Create Logr instance.
lgr := &logr.Logr{}
// Create a filter and formatter. Both can be shared by multiple
// targets.
filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Error}
formatter := &format.Plain{Delim: " | "}
// WriterTarget outputs to any io.Writer
t := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
lgr.AddTarget(t)
// One or more Loggers can be created, shared, used concurrently,
// or created on demand.
logger := lgr.NewLogger().WithField("user", "Sarah")
// Now we can log to the target(s).
logger.Debug("login attempt")
logger.Error("login failed")
// Ensure targets are drained before application exit.
lgr.Shutdown()
```
## Fields
Fields allow for contextual logging, meaning information can be added to log statements without changing the statements themselves. Information can be shared across multiple logging statements thus allowing log analysis tools to group them.
Fields are added via Loggers:
```go
lgr := &Logr{}
// ... add targets ...
logger := lgr.NewLogger().WithFields(logr.Fields{
"user": user,
"role": role})
logger.Info("login attempt")
// ... later ...
logger.Info("login successful")
```
`Logger.WithFields` can be used to create additional Loggers that add more fields.
Logr fields are inspired by and work the same as [Logrus fields](https://github.com/sirupsen/logrus#fields).
## Filters
Logr supports the traditional seven log levels via `logr.StdFilter`: Panic, Fatal, Error, Warning, Info, Debug, and Trace.
```go
// When added to a target, this filter will only allow
// log statements with level severity Warn or higher.
// It will also generate stack traces for Error or higher.
filter := &logr.StdFilter{Lvl: logr.Warn, Stacktrace: logr.Error}
```
Logr also supports custom filters (logr.CustomFilter) which allow fine grained inclusion of log items without turning on the fire-hose.
```go
// create custom levels; use IDs > 10.
LoginLevel := logr.Level{ID: 100, Name: "login ", Stacktrace: false}
LogoutLevel := logr.Level{ID: 101, Name: "logout", Stacktrace: false}
lgr := &logr.Logr{}
// create a custom filter with custom levels.
filter := &logr.CustomFilter{}
filter.Add(LoginLevel, LogoutLevel)
formatter := &format.Plain{Delim: " | "}
tgr := target.NewWriterTarget(filter, formatter, os.StdOut, 1000)
lgr.AddTarget(tgr)
logger := lgr.NewLogger().WithFields(logr.Fields{"user": "Bob", "role": "admin"})
logger.Log(LoginLevel, "this item will get logged")
logger.Debug("won't be logged since Debug wasn't added to custom filter")
```
Both filter types allow you to determine which levels require a stack trace to be output. Note that generating stack traces cannot happen fully asynchronously and thus add latency to the calling goroutine.
## Targets
There are built-in targets for outputting to syslog, file, or any `io.Writer`. More will be added.
You can use any [Logrus hooks](https://github.com/sirupsen/logrus/wiki/Hooks) via a simple [adapter](https://github.com/wiggin77/logrus4logr).
You can create your own target by implementing the [Target](./target.go) interface.
An easier method is to use the [logr.Basic](./target.go) type target and build your functionality on that. Basic handles all the queuing and other plumbing so you only need to implement two methods. Example target that outputs to `io.Writer`:
```go
type Writer struct {
logr.Basic
out io.Writer
}
func NewWriterTarget(filter logr.Filter, formatter logr.Formatter, out io.Writer, maxQueue int) *Writer {
w := &Writer{out: out}
w.Basic.Start(w, w, filter, formatter, maxQueue)
return w
}
// Write will always be called by a single goroutine, so no locking needed.
// Just convert a log record to a []byte using the formatter and output the
// bytes to your sink.
func (w *Writer) Write(rec *logr.LogRec) error {
_, stacktrace := w.IsLevelEnabled(rec.Level())
// take a buffer from the pool to avoid allocations or just allocate a new one.
buf := rec.Logger().Logr().BorrowBuffer()
defer rec.Logger().Logr().ReleaseBuffer(buf)
buf, err := w.Formatter().Format(rec, stacktrace, buf)
if err != nil {
return err
}
_, err = w.out.Write(buf.Bytes())
return err
}
```
## Formatters
Logr has two built-in formatters, one for JSON and the other plain, delimited text.
You can use any [Logrus formatters](https://github.com/sirupsen/logrus#formatters) via a simple [adapter](https://github.com/wiggin77/logrus4logr).
You can create your own formatter by implementing the [Formatter](./formatter.go) interface:
```go
Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error)
```
## Handlers
When creating the Logr instance, you can add several handlers that get called when exceptional events occur:
### ```Logr.OnLoggerError(err error)```
Called any time an internal logging error occurs. For example, this can happen when a target cannot connect to its data sink.
It may be tempting to log this error, however there is a danger that logging this will simply generate another error and so on. If you must log it, use a target and custom level specifically for this event and ensure it cannot generate more errors.
### ```Logr.OnQueueFull func(rec *LogRec, maxQueueSize int) bool```
Called on an attempt to add a log record to a full Logr queue. This generally means the Logr maximum queue size is too small, or at least one target is very slow. Logr maximum queue size can be changed before adding any targets via:
```go
lgr := logr.Logr{MaxQueueSize: 10000}
```
Returning true will drop the log record. False will block until the log record can be added, which creates a natural throttle at the expense of latency for the calling goroutine. The default is to block.
### ```Logr.OnTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool```
Called on an attempt to add a log record to a full target queue. This generally means your target's max queue size is too small, or the target is very slow to output.
As with the Logr queue, returning true will drop the log record. False will block until the log record can be added, which creates a natural throttle at the expense of latency for the calling goroutine. The default is to block.
### ```Logr.OnExit func(code int) and Logr.OnPanic func(err interface{})```
OnExit and OnPanic are called when the Logger.FatalXXX and Logger.PanicXXX functions are called respectively.
In both cases the default behavior is to shut down gracefully, draining all targets, and calling `os.Exit` or `panic` respectively.
When adding your own handlers, be sure to call `Logr.Shutdown` before exiting the application to avoid losing log records.

11
vendor/github.com/wiggin77/logr/config.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,11 @@
package logr
import (
"fmt"
"github.com/wiggin77/cfg"
)
func ConfigLogger(config *cfg.Config) error {
return fmt.Errorf("Not implemented yet")
}

30
vendor/github.com/wiggin77/logr/const.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,30 @@
package logr
import "time"
// Defaults.
const (
// DefaultMaxQueueSize is the default maximum queue size for Logr instances.
DefaultMaxQueueSize = 1000
// DefaultMaxStackFrames is the default maximum max number of stack frames collected
// when generating stack traces for logging.
DefaultMaxStackFrames = 30
// DefaultEnqueueTimeout is the default amount of time a log record can take to be queued.
// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
// and returns false.
DefaultEnqueueTimeout = time.Second * 30
// DefaultShutdownTimeout is the default amount of time `logr.Shutdown` can execute before
// timing out.
DefaultShutdownTimeout = time.Second * 30
// DefaultFlushTimeout is the default amount of time `logr.Flush` can execute before
// timing out.
DefaultFlushTimeout = time.Second * 30
// DefaultMaxPooledBuffer is the maximum size a pooled buffer can be.
// Buffers that grow beyond this size are garbage collected.
DefaultMaxPooledBuffer = 1024 * 1024
)

26
vendor/github.com/wiggin77/logr/filter.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,26 @@
package logr
// LevelID is the unique id of each level.
type LevelID uint8
// Level provides a mechanism to enable/disable specific log lines.
type Level struct {
ID LevelID
Name string
Stacktrace bool
}
// String returns the name of this level.
func (level Level) String() string {
return level.Name
}
// Filter allows targets to determine which Level(s) are active
// for logging and which Level(s) require a stack trace to be output.
// A default implementation using "panic, fatal..." is provided, and
// a more flexible alternative implementation is also provided that
// allows any number of custom levels.
type Filter interface {
IsEnabled(Level) bool
IsStacktraceEnabled(Level) bool
}

241
vendor/github.com/wiggin77/logr/format/json.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,241 @@
package format
import (
"bytes"
"fmt"
"runtime"
"sync"
"time"
"github.com/francoispqt/gojay"
"github.com/wiggin77/logr"
)
// JSON formats log records as JSON.
type JSON struct {
// DisableTimestamp disables output of timestamp field.
DisableTimestamp bool
// DisableLevel disables output of level field.
DisableLevel bool
// DisableMsg disables output of msg field.
DisableMsg bool
// DisableContext disables output of all context fields.
DisableContext bool
// DisableStacktrace disables output of stack trace.
DisableStacktrace bool
// TimestampFormat is an optional format for timestamps. If empty
// then DefTimestampFormat is used.
TimestampFormat string
// Indent sets the character used to indent or pretty print the JSON.
// Empty string means no pretty print.
Indent string
// EscapeHTML determines if certain characters (e.g. `<`, `>`, `&`)
// are escaped.
EscapeHTML bool
// KeyTimestamp overrides the timestamp field key name.
KeyTimestamp string
// KeyLevel overrides the level field key name.
KeyLevel string
// KeyMsg overrides the msg field key name.
KeyMsg string
// KeyContextFields when not empty will group all context fields
// under this key.
KeyContextFields string
// KeyStacktrace overrides the stacktrace field key name.
KeyStacktrace string
once sync.Once
}
// Format converts a log record to bytes in JSON format.
func (j *JSON) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
j.once.Do(j.applyDefaultKeyNames)
if buf == nil {
buf = &bytes.Buffer{}
}
enc := gojay.BorrowEncoder(buf)
defer func() {
enc.Release()
}()
jlr := JSONLogRec{
LogRec: rec,
JSON: j,
stacktrace: stacktrace,
}
err := enc.EncodeObject(jlr)
if err != nil {
return nil, err
}
return buf, nil
}
func (j *JSON) applyDefaultKeyNames() {
if j.KeyTimestamp == "" {
j.KeyTimestamp = "timestamp"
}
if j.KeyLevel == "" {
j.KeyLevel = "level"
}
if j.KeyMsg == "" {
j.KeyMsg = "msg"
}
if j.KeyStacktrace == "" {
j.KeyStacktrace = "stacktrace"
}
}
// JSONLogRec decorates a LogRec adding JSON encoding.
type JSONLogRec struct {
*logr.LogRec
*JSON
stacktrace bool
}
// MarshalJSONObject encodes the LogRec as JSON.
func (rec JSONLogRec) MarshalJSONObject(enc *gojay.Encoder) {
if !rec.DisableTimestamp {
timestampFmt := rec.TimestampFormat
if timestampFmt == "" {
timestampFmt = logr.DefTimestampFormat
}
time := rec.Time()
enc.AddTimeKey(rec.KeyTimestamp, &time, timestampFmt)
}
if !rec.DisableLevel {
enc.AddStringKey(rec.KeyLevel, rec.Level().Name)
}
if !rec.DisableMsg {
enc.AddStringKey(rec.KeyMsg, rec.Msg())
}
if !rec.DisableContext {
if rec.KeyContextFields != "" {
enc.AddObjectKey(rec.KeyContextFields, jsonFields(rec.Fields()))
} else {
m := rec.Fields()
if len(m) > 0 {
for k, v := range m {
key := rec.prefixCollision(k)
encodeField(enc, key, v)
}
}
}
}
if rec.stacktrace && !rec.DisableStacktrace {
frames := rec.StackFrames()
if len(frames) > 0 {
enc.AddArrayKey(rec.KeyStacktrace, stackFrames(frames))
}
}
}
// IsNil returns true if the LogRec pointer is nil.
func (rec JSONLogRec) IsNil() bool {
return rec.LogRec == nil
}
func (rec JSONLogRec) prefixCollision(key string) string {
switch key {
case rec.KeyTimestamp, rec.KeyLevel, rec.KeyMsg, rec.KeyStacktrace:
return rec.prefixCollision("_" + key)
}
return key
}
type stackFrames []runtime.Frame
// MarshalJSONArray encodes stackFrames slice as JSON.
func (s stackFrames) MarshalJSONArray(enc *gojay.Encoder) {
for _, frame := range s {
enc.AddObject(stackFrame(frame))
}
}
// IsNil returns true if stackFrames is empty slice.
func (s stackFrames) IsNil() bool {
return len(s) == 0
}
type stackFrame runtime.Frame
// MarshalJSONArray encodes stackFrame as JSON.
func (f stackFrame) MarshalJSONObject(enc *gojay.Encoder) {
enc.AddStringKey("Function", f.Function)
enc.AddStringKey("File", f.File)
enc.AddIntKey("Line", f.Line)
}
func (f stackFrame) IsNil() bool {
return false
}
type jsonFields logr.Fields
// MarshalJSONObject encodes Fields map to JSON.
func (f jsonFields) MarshalJSONObject(enc *gojay.Encoder) {
for k, v := range f {
encodeField(enc, k, v)
}
}
// IsNil returns true if map is nil.
func (f jsonFields) IsNil() bool {
return f == nil
}
func encodeField(enc *gojay.Encoder, key string, val interface{}) {
switch vt := val.(type) {
case gojay.MarshalerJSONObject:
enc.AddObjectKey(key, vt)
case gojay.MarshalerJSONArray:
enc.AddArrayKey(key, vt)
case string:
enc.AddStringKey(key, vt)
case error:
enc.AddStringKey(key, vt.Error())
case bool:
enc.AddBoolKey(key, vt)
case int:
enc.AddIntKey(key, vt)
case int64:
enc.AddInt64Key(key, vt)
case int32:
enc.AddIntKey(key, int(vt))
case int16:
enc.AddIntKey(key, int(vt))
case int8:
enc.AddIntKey(key, int(vt))
case uint64:
enc.AddIntKey(key, int(vt))
case uint32:
enc.AddIntKey(key, int(vt))
case uint16:
enc.AddIntKey(key, int(vt))
case uint8:
enc.AddIntKey(key, int(vt))
case float64:
enc.AddFloatKey(key, vt)
case float32:
enc.AddFloat32Key(key, vt)
case *gojay.EmbeddedJSON:
enc.AddEmbeddedJSONKey(key, vt)
case time.Time:
enc.AddTimeKey(key, &vt, logr.DefTimestampFormat)
case *time.Time:
enc.AddTimeKey(key, vt, logr.DefTimestampFormat)
default:
s := fmt.Sprintf("%v", vt)
enc.AddStringKey(key, s)
}
}

75
vendor/github.com/wiggin77/logr/format/plain.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,75 @@
package format
import (
"bytes"
"fmt"
"github.com/wiggin77/logr"
)
// Plain is the simplest formatter, outputting only text with
// no colors.
type Plain struct {
// DisableTimestamp disables output of timestamp field.
DisableTimestamp bool
// DisableLevel disables output of level field.
DisableLevel bool
// DisableMsg disables output of msg field.
DisableMsg bool
// DisableContext disables output of all context fields.
DisableContext bool
// DisableStacktrace disables output of stack trace.
DisableStacktrace bool
// Delim is an optional delimiter output between each log field.
// Defaults to a single space.
Delim string
// TimestampFormat is an optional format for timestamps. If empty
// then DefTimestampFormat is used.
TimestampFormat string
}
// Format converts a log record to bytes.
func (p *Plain) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
delim := p.Delim
if delim == "" {
delim = " "
}
if buf == nil {
buf = &bytes.Buffer{}
}
timestampFmt := p.TimestampFormat
if timestampFmt == "" {
timestampFmt = logr.DefTimestampFormat
}
if !p.DisableTimestamp {
var arr [128]byte
tbuf := rec.Time().AppendFormat(arr[:0], timestampFmt)
buf.Write(tbuf)
buf.WriteString(delim)
}
if !p.DisableLevel {
fmt.Fprintf(buf, "%v%s", rec.Level().Name, delim)
}
if !p.DisableMsg {
fmt.Fprint(buf, rec.Msg(), delim)
}
if !p.DisableContext {
ctx := rec.Fields()
if len(ctx) > 0 {
logr.WriteFields(buf, ctx, " ")
}
}
if stacktrace && !p.DisableStacktrace {
frames := rec.StackFrames()
if len(frames) > 0 {
buf.WriteString("\n")
logr.WriteStacktrace(buf, rec.StackFrames())
}
}
buf.WriteString("\n")
return buf, nil
}

119
vendor/github.com/wiggin77/logr/formatter.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,119 @@
package logr
import (
"bytes"
"fmt"
"io"
"runtime"
"sort"
)
// Formatter turns a LogRec into a formatted string.
type Formatter interface {
// Format converts a log record to bytes. If buf is not nil then it will be
// be filled with the formatted results, otherwise a new buffer will be allocated.
Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error)
}
const (
// DefTimestampFormat is the default time stamp format used by
// Plain formatter and others.
DefTimestampFormat = "2006-01-02 15:04:05.000 Z07:00"
)
// DefaultFormatter is the default formatter, outputting only text with
// no colors and a space delimiter. Use `format.Plain` instead.
type DefaultFormatter struct {
}
// Format converts a log record to bytes.
func (p *DefaultFormatter) Format(rec *LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
if buf == nil {
buf = &bytes.Buffer{}
}
delim := " "
timestampFmt := DefTimestampFormat
fmt.Fprintf(buf, "%s%s", rec.Time().Format(timestampFmt), delim)
fmt.Fprintf(buf, "%v%s", rec.Level(), delim)
fmt.Fprint(buf, rec.Msg(), delim)
ctx := rec.Fields()
if len(ctx) > 0 {
WriteFields(buf, ctx, " ")
}
if stacktrace {
frames := rec.StackFrames()
if len(frames) > 0 {
buf.WriteString("\n")
WriteStacktrace(buf, rec.StackFrames())
}
}
buf.WriteString("\n")
return buf, nil
}
// WriteFields writes zero or more name value pairs to the io.Writer.
// The pairs are sorted by key name and output in key=value format
// with optional separator between fields.
func WriteFields(w io.Writer, flds Fields, separator string) {
keys := make([]string, 0, len(flds))
for k := range flds {
keys = append(keys, k)
}
sort.Strings(keys)
sep := ""
for _, key := range keys {
writeField(w, key, flds[key], sep)
sep = separator
}
}
func writeField(w io.Writer, key string, val interface{}, sep string) {
var template string
switch v := val.(type) {
case error:
val := v.Error()
if shouldQuote(val) {
template = "%s%s=%q"
} else {
template = "%s%s=%s"
}
case string:
if shouldQuote(v) {
template = "%s%s=%q"
} else {
template = "%s%s=%s"
}
default:
template = "%s%s=%v"
}
fmt.Fprintf(w, template, sep, key, val)
}
// shouldQuote returns true if val contains any characters that might be unsafe
// when injecting log output into an aggregator, viewer or report.
func shouldQuote(val string) bool {
for _, c := range val {
if !((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z')) {
return true
}
}
return false
}
// WriteStacktrace formats and outputs a stack trace to an io.Writer.
func WriteStacktrace(w io.Writer, frames []runtime.Frame) {
for _, frame := range frames {
if frame.Function != "" {
fmt.Fprintf(w, " %s\n", frame.Function)
}
if frame.File != "" {
fmt.Fprintf(w, " %s:%d\n", frame.File, frame.Line)
}
}
}

11
vendor/github.com/wiggin77/logr/go.mod сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,11 @@
module github.com/wiggin77/logr
go 1.12
require (
github.com/francoispqt/gojay v1.2.13
github.com/nsf/jsondiff v0.0.0-20190712045011-8443391ee9b6
github.com/wiggin77/cfg v1.0.2
github.com/wiggin77/merror v1.0.2
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)

172
vendor/github.com/wiggin77/logr/go.sum сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,172 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nsf/jsondiff v0.0.0-20190712045011-8443391ee9b6 h1:qsqscDgSJy+HqgMTR+3NwjYJBbp1+honwDsszLoS+pA=
github.com/nsf/jsondiff v0.0.0-20190712045011-8443391ee9b6/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wiggin77/cfg v1.0.2 h1:NBUX+iJRr+RTncTqTNvajHwzduqbhCQjEqxLHr6Fk7A=
github.com/wiggin77/cfg v1.0.2/go.mod h1:b3gotba2e5bXTqTW48DwIFoLc+4lWKP7WPi/CdvZ4aE=
github.com/wiggin77/merror v1.0.2 h1:V0nH9eFp64ASyaXC+pB5WpvBoCg7NUwvaCSKdzlcHqw=
github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

83
vendor/github.com/wiggin77/logr/levelcache.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,83 @@
package logr
import (
"sync"
)
// LevelStatus represents whether a level is enabled and
// requires a stack trace.
type LevelStatus struct {
Enabled bool
Stacktrace bool
empty bool
}
type levelCache interface {
setup()
get(id LevelID) (LevelStatus, bool)
put(id LevelID, status LevelStatus)
clear()
}
// syncMapLevelCache uses sync.Map which may better handle large concurrency
// scenarios.
type syncMapLevelCache struct {
m sync.Map
}
func (c *syncMapLevelCache) setup() {
c.clear()
}
func (c *syncMapLevelCache) get(id LevelID) (LevelStatus, bool) {
s, _ := c.m.Load(id)
status := s.(LevelStatus)
return status, !status.empty
}
func (c *syncMapLevelCache) put(id LevelID, status LevelStatus) {
c.m.Store(id, status)
}
func (c *syncMapLevelCache) clear() {
var i LevelID
for i = 0; i < 255; i++ {
c.m.Store(i, LevelStatus{empty: true})
}
}
// arrayLevelCache using array and a mutex.
type arrayLevelCache struct {
arr [256]LevelStatus
mux sync.RWMutex
}
func (c *arrayLevelCache) setup() {
c.clear()
}
//var dummy = LevelStatus{}
func (c *arrayLevelCache) get(id LevelID) (LevelStatus, bool) {
c.mux.RLock()
status := c.arr[id]
ok := !status.empty
c.mux.RUnlock()
return status, ok
}
func (c *arrayLevelCache) put(id LevelID, status LevelStatus) {
c.mux.Lock()
defer c.mux.Unlock()
c.arr[id] = status
}
func (c *arrayLevelCache) clear() {
c.mux.Lock()
defer c.mux.Unlock()
for i := range c.arr {
c.arr[i] = LevelStatus{empty: true}
}
}

45
vendor/github.com/wiggin77/logr/levelcustom.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,45 @@
package logr
import (
"sync"
)
// CustomFilter allows targets to enable logging via a list of levels.
type CustomFilter struct {
mux sync.RWMutex
levels map[LevelID]Level
}
// IsEnabled returns true if the specified Level exists in this list.
func (st *CustomFilter) IsEnabled(level Level) bool {
st.mux.RLock()
defer st.mux.RUnlock()
_, ok := st.levels[level.ID]
return ok
}
// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
func (st *CustomFilter) IsStacktraceEnabled(level Level) bool {
st.mux.RLock()
defer st.mux.RUnlock()
lvl, ok := st.levels[level.ID]
if ok {
return lvl.Stacktrace
}
return false
}
// Add adds one or more levels to the list. Adding a level enables logging for
// that level on any targets using this CustomFilter.
func (st *CustomFilter) Add(levels ...Level) {
st.mux.Lock()
defer st.mux.Unlock()
if st.levels == nil {
st.levels = make(map[LevelID]Level)
}
for _, s := range levels {
st.levels[s.ID] = s
}
}

37
vendor/github.com/wiggin77/logr/levelstd.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,37 @@
package logr
// StdFilter allows targets to filter via classic log levels where any level
// beyond a certain verbosity/severity is enabled.
type StdFilter struct {
Lvl Level
Stacktrace Level
}
// IsEnabled returns true if the specified Level is at or above this verbosity. Also
// determines if a stack trace is required.
func (lt StdFilter) IsEnabled(level Level) bool {
return level.ID <= lt.Lvl.ID
}
// IsStacktraceEnabled returns true if the specified Level requires a stack trace.
func (lt StdFilter) IsStacktraceEnabled(level Level) bool {
return level.ID <= lt.Stacktrace.ID
}
var (
// Panic is the highest level of severity. Logs the message and then panics.
Panic = Level{ID: 0, Name: "panic"}
// Fatal designates a catastrophic error. Logs the message and then calls
// `logr.Exit(1)`.
Fatal = Level{ID: 1, Name: "fatal"}
// Error designates a serious but possibly recoverable error.
Error = Level{ID: 2, Name: "error"}
// Warn designates non-critical error.
Warn = Level{ID: 3, Name: "warn"}
// Info designates information regarding application events.
Info = Level{ID: 4, Name: "info"}
// Debug designates verbose information typically used for debugging.
Debug = Level{ID: 5, Name: "debug"}
// Trace designates the highest verbosity of log output.
Trace = Level{ID: 6, Name: "trace"}
)

218
vendor/github.com/wiggin77/logr/logger.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,218 @@
package logr
import (
"fmt"
)
// Fields type, used to pass to `WithFields`.
type Fields map[string]interface{}
// Logger provides context for logging via fields.
type Logger struct {
logr *Logr
fields Fields
}
// Logr returns the `Logr` instance that created this `Logger`.
func (logger Logger) Logr() *Logr {
return logger.logr
}
// WithField creates a new `Logger` with any existing fields
// plus the new one.
func (logger Logger) WithField(key string, value interface{}) Logger {
return logger.WithFields(Fields{key: value})
}
// WithFields creates a new `Logger` with any existing fields
// plus the new ones.
func (logger Logger) WithFields(fields Fields) Logger {
l := Logger{logr: logger.logr}
// if parent has no fields then avoid creating a new map.
oldLen := len(logger.fields)
if oldLen == 0 {
l.fields = fields
return l
}
l.fields = make(Fields, len(fields)+oldLen)
for k, v := range logger.fields {
l.fields[k] = v
}
for k, v := range fields {
l.fields[k] = v
}
return l
}
// Log checks that the level matches one or more targets, and
// if so, generates a log record that is added to the Logr queue.
// Arguments are handled in the manner of fmt.Print.
func (logger Logger) Log(lvl Level, args ...interface{}) {
status := logger.logr.IsLevelEnabled(lvl)
if status.Enabled {
rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
logger.logr.enqueue(rec)
}
}
// Trace is a convenience method equivalent to `Log(TraceLevel, args...)`.
func (logger Logger) Trace(args ...interface{}) {
logger.Log(Trace, args...)
}
// Debug is a convenience method equivalent to `Log(DebugLevel, args...)`.
func (logger Logger) Debug(args ...interface{}) {
logger.Log(Debug, args...)
}
// Print ensures compatibility with std lib logger.
func (logger Logger) Print(args ...interface{}) {
logger.Info(args...)
}
// Info is a convenience method equivalent to `Log(InfoLevel, args...)`.
func (logger Logger) Info(args ...interface{}) {
logger.Log(Info, args...)
}
// Warn is a convenience method equivalent to `Log(WarnLevel, args...)`.
func (logger Logger) Warn(args ...interface{}) {
logger.Log(Warn, args...)
}
// Error is a convenience method equivalent to `Log(ErrorLevel, args...)`.
func (logger Logger) Error(args ...interface{}) {
logger.Log(Error, args...)
}
// Fatal is a convenience method equivalent to `Log(FatalLevel, args...)`
// followed by a call to os.Exit(1).
func (logger Logger) Fatal(args ...interface{}) {
logger.Log(Fatal, args...)
logger.logr.exit(1)
}
// Panic is a convenience method equivalent to `Log(PanicLevel, args...)`
// followed by a call to panic().
func (logger Logger) Panic(args ...interface{}) {
logger.Log(Panic, args...)
panic(fmt.Sprint(args...))
}
//
// Printf style
//
// Logf checks that the level matches one or more targets, and
// if so, generates a log record that is added to the main
// queue (channel). Arguments are handled in the manner of fmt.Printf.
func (logger Logger) Logf(lvl Level, format string, args ...interface{}) {
status := logger.logr.IsLevelEnabled(lvl)
if status.Enabled {
rec := NewLogRec(lvl, logger, format, args, status.Stacktrace)
logger.logr.enqueue(rec)
}
}
// Tracef is a convenience method equivalent to `Logf(TraceLevel, args...)`.
func (logger Logger) Tracef(format string, args ...interface{}) {
logger.Logf(Trace, format, args...)
}
// Debugf is a convenience method equivalent to `Logf(DebugLevel, args...)`.
func (logger Logger) Debugf(format string, args ...interface{}) {
logger.Logf(Debug, format, args...)
}
// Infof is a convenience method equivalent to `Logf(InfoLevel, args...)`.
func (logger Logger) Infof(format string, args ...interface{}) {
logger.Logf(Info, format, args...)
}
// Printf ensures compatibility with std lib logger.
func (logger Logger) Printf(format string, args ...interface{}) {
logger.Infof(format, args...)
}
// Warnf is a convenience method equivalent to `Logf(WarnLevel, args...)`.
func (logger Logger) Warnf(format string, args ...interface{}) {
logger.Logf(Warn, format, args...)
}
// Errorf is a convenience method equivalent to `Logf(ErrorLevel, args...)`.
func (logger Logger) Errorf(format string, args ...interface{}) {
logger.Logf(Error, format, args...)
}
// Fatalf is a convenience method equivalent to `Logf(FatalLevel, args...)`
// followed by a call to os.Exit(1).
func (logger Logger) Fatalf(format string, args ...interface{}) {
logger.Logf(Fatal, format, args...)
logger.logr.exit(1)
}
// Panicf is a convenience method equivalent to `Logf(PanicLevel, args...)`
// followed by a call to panic().
func (logger Logger) Panicf(format string, args ...interface{}) {
logger.Logf(Panic, format, args...)
}
//
// Println style
//
// Logln checks that the level matches one or more targets, and
// if so, generates a log record that is added to the main
// queue (channel). Arguments are handled in the manner of fmt.Println.
func (logger Logger) Logln(lvl Level, args ...interface{}) {
status := logger.logr.IsLevelEnabled(lvl)
if status.Enabled {
rec := NewLogRec(lvl, logger, "", args, status.Stacktrace)
rec.newline = true
logger.logr.enqueue(rec)
}
}
// Traceln is a convenience method equivalent to `Logln(TraceLevel, args...)`.
func (logger Logger) Traceln(args ...interface{}) {
logger.Logln(Trace, args...)
}
// Debugln is a convenience method equivalent to `Logln(DebugLevel, args...)`.
func (logger Logger) Debugln(args ...interface{}) {
logger.Logln(Debug, args...)
}
// Infoln is a convenience method equivalent to `Logln(InfoLevel, args...)`.
func (logger Logger) Infoln(args ...interface{}) {
logger.Logln(Info, args...)
}
// Println ensures compatibility with std lib logger.
func (logger Logger) Println(args ...interface{}) {
logger.Infoln(args...)
}
// Warnln is a convenience method equivalent to `Logln(WarnLevel, args...)`.
func (logger Logger) Warnln(args ...interface{}) {
logger.Logln(Warn, args...)
}
// Errorln is a convenience method equivalent to `Logln(ErrorLevel, args...)`.
func (logger Logger) Errorln(args ...interface{}) {
logger.Logln(Error, args...)
}
// Fatalln is a convenience method equivalent to `Logln(FatalLevel, args...)`
// followed by a call to os.Exit(1).
func (logger Logger) Fatalln(args ...interface{}) {
logger.Logln(Fatal, args...)
logger.logr.exit(1)
}
// Panicln is a convenience method equivalent to `Logln(PanicLevel, args...)`
// followed by a call to panic().
func (logger Logger) Panicln(args ...interface{}) {
logger.Logln(Panic, args...)
}

461
vendor/github.com/wiggin77/logr/logr.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,461 @@
package logr
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"sync"
"time"
"github.com/wiggin77/cfg"
"github.com/wiggin77/merror"
)
// Logr maintains a list of log targets and accepts incoming
// log records.
type Logr struct {
tmux sync.RWMutex // target mutex
targets []Target
mux sync.RWMutex
maxQueueSizeActual int
in chan *LogRec
done chan struct{}
once sync.Once
shutdown bool
lvlCache levelCache
bufferPool sync.Pool
// MaxQueueSize is the maximum number of log records that can be queued.
// If exceeded, `OnQueueFull` is called which determines if the log
// record will be dropped or block until add is successful.
// If this is modified, it must be done before `Configure` or
// `AddTarget`. Defaults to DefaultMaxQueueSize.
MaxQueueSize int
// OnLoggerError, when not nil, is called any time an internal
// logging error occurs. For example, this can happen when a
// target cannot connect to its data sink.
OnLoggerError func(error)
// OnQueueFull, when not nil, is called on an attempt to add
// a log record to a full Logr queue.
// `MaxQueueSize` can be used to modify the maximum queue size.
// This function should return quickly, with a bool indicating whether
// the log record should be dropped (true) or block until the log record
// is successfully added (false). If nil then blocking (false) is assumed.
OnQueueFull func(rec *LogRec, maxQueueSize int) bool
// OnTargetQueueFull, when not nil, is called on an attempt to add
// a log record to a full target queue provided the target supports reporting
// this condition.
// This function should return quickly, with a bool indicating whether
// the log record should be dropped (true) or block until the log record
// is successfully added (false). If nil then blocking (false) is assumed.
OnTargetQueueFull func(target Target, rec *LogRec, maxQueueSize int) bool
// OnExit, when not nil, is called when a FatalXXX style log API is called.
// When nil, then the default behavior is to cleanly shut down this Logr and
// call `os.Exit(code)`.
OnExit func(code int)
// OnPanic, when not nil, is called when a PanicXXX style log API is called.
// When nil, then the default behavior is to cleanly shut down this Logr and
// call `panic(err)`.
OnPanic func(err interface{})
// EnqueueTimeout is the amount of time a log record can take to be queued.
// This only applies to blocking enqueue which happen after `logr.OnQueueFull`
// is called and returns false.
EnqueueTimeout time.Duration
// ShutdownTimeout is the amount of time `logr.Shutdown` can execute before
// timing out.
ShutdownTimeout time.Duration
// FlushTimeout is the amount of time `logr.Flush` can execute before
// timing out.
FlushTimeout time.Duration
// UseSyncMapLevelCache can be set to true before the first target is added
// when high concurrency (e.g. >32 cores) is expected. This may improve
// performance with large numbers of cores - benchmark for your use case.
UseSyncMapLevelCache bool
// MaxPooledFormatBuffer determines the maximum size of a buffer that can be
// pooled. To reduce allocations, the buffers needed during formatting (etc)
// are pooled. A very large log item will grow a buffer that could stay in
// memory indefinitely. This settings lets you control how big a pooled buffer
// can be - anything larger will be garbage collected after use.
// Defaults to 1MB.
MaxPooledBuffer int
// DisableBufferPool when true disables the buffer pool. See MaxPooledBuffer.
DisableBufferPool bool
}
// Configure adds/removes targets via the supplied `Config`.
func (logr *Logr) Configure(config *cfg.Config) error {
// TODO
return fmt.Errorf("not implemented yet")
}
// AddTarget adds a target to the logger which will receive
// log records for outputting.
func (logr *Logr) AddTarget(target Target) error {
logr.mux.Lock()
defer logr.mux.Unlock()
if logr.shutdown {
return fmt.Errorf("logr shut down")
}
logr.tmux.Lock()
defer logr.tmux.Unlock()
logr.targets = append(logr.targets, target)
logr.once.Do(func() {
logr.maxQueueSizeActual = logr.MaxQueueSize
if logr.maxQueueSizeActual == 0 {
logr.maxQueueSizeActual = DefaultMaxQueueSize
}
if logr.maxQueueSizeActual < 0 {
logr.maxQueueSizeActual = 0
}
logr.in = make(chan *LogRec, logr.maxQueueSizeActual)
logr.done = make(chan struct{})
if logr.UseSyncMapLevelCache {
logr.lvlCache = &syncMapLevelCache{}
} else {
logr.lvlCache = &arrayLevelCache{}
}
if logr.MaxPooledBuffer == 0 {
logr.MaxPooledBuffer = DefaultMaxPooledBuffer
}
logr.bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
logr.lvlCache.setup()
go logr.start()
})
logr.resetLevelCache()
return nil
}
// NewLogger creates a Logger using defaults. A `Logger` is light-weight
// enough to create on-demand, but typically one or more Loggers are
// created and re-used.
func (logr *Logr) NewLogger() Logger {
logger := Logger{logr: logr}
return logger
}
var levelStatusDisabled = LevelStatus{}
// IsLevelEnabled returns true if at least one target has the specified
// level enabled. The result is cached so that subsequent checks are fast.
func (logr *Logr) IsLevelEnabled(lvl Level) LevelStatus {
// Check cache. lvlCache may still be nil if no targets added.
if logr.lvlCache == nil {
return levelStatusDisabled
}
status, ok := logr.lvlCache.get(lvl.ID)
if ok {
return status
}
logr.mux.RLock()
defer logr.mux.RUnlock()
// Don't accept new log records after shutdown.
if logr.shutdown {
return levelStatusDisabled
}
status = LevelStatus{}
// Check each target.
logr.tmux.RLock()
defer logr.tmux.RUnlock()
for _, t := range logr.targets {
e, s := t.IsLevelEnabled(lvl)
if e {
status.Enabled = true
if s {
status.Stacktrace = true
break // if both enabled then no sense checking more targets
}
}
}
// Cache and return the result.
logr.lvlCache.put(lvl.ID, status)
return status
}
// ResetLevelCache resets the cached results of `IsLevelEnabled`. This is
// called any time a Target is added or a target's level is changed.
func (logr *Logr) ResetLevelCache() {
// Write lock so that new cache entries cannot be stored while we
// clear the cache.
logr.mux.Lock()
defer logr.mux.Unlock()
logr.resetLevelCache()
}
// resetLevelCache empties the level cache without locking.
// mux.Lock must be held before calling this function.
func (logr *Logr) resetLevelCache() {
// lvlCache may still be nil if no targets added.
if logr.lvlCache != nil {
logr.lvlCache.clear()
}
}
// enqueue adds a log record to the logr queue. If the queue is full then
// this function either blocks or the log record is dropped, depending on
// the result of calling `OnQueueFull`.
func (logr *Logr) enqueue(rec *LogRec) {
if logr.in == nil {
logr.ReportError(fmt.Errorf("AddTarget or Configure must be called before enqueue"))
}
select {
case logr.in <- rec:
default:
if logr.OnQueueFull != nil && logr.OnQueueFull(rec, logr.maxQueueSizeActual) {
return // drop the record
}
select {
case <-time.After(logr.enqueueTimeout()):
logr.ReportError(fmt.Errorf("enqueue timed out for log rec [%v]", rec))
case logr.in <- rec: // block until success or timeout
}
}
}
// exit is called by one of the FatalXXX style APIS. If `logr.OnExit` is not nil
// then that method is called, otherwise the default behavior is to shut down this
// Logr cleanly then call `os.Exit(code)`.
func (logr *Logr) exit(code int) {
if logr.OnExit != nil {
logr.OnExit(code)
return
}
if err := logr.Shutdown(); err != nil {
logr.ReportError(err)
}
os.Exit(code)
}
// panic is called by one of the PanicXXX style APIS. If `logr.OnPanic` is not nil
// then that method is called, otherwise the default behavior is to shut down this
// Logr cleanly then call `panic(err)`.
func (logr *Logr) panic(err interface{}) {
if logr.OnPanic != nil {
logr.OnPanic(err)
return
}
if err := logr.Shutdown(); err != nil {
logr.ReportError(err)
}
panic(err)
}
// Flush blocks while flushing the logr queue and all target queues, by
// writing existing log records to valid targets.
// Any attempts to add new log records will block until flush is complete.
// `logr.FlushTimeout` determines how long flush can execute before
// timing out. Use `IsTimeoutError` to determine if the returned error is
// due to a timeout.
func (logr *Logr) Flush() error {
logr.mux.Lock()
defer logr.mux.Unlock()
ctx, cancel := context.WithTimeout(context.Background(), logr.flushTimeout())
defer cancel()
rec := newFlushLogRec(logr.NewLogger())
logr.enqueue(rec)
select {
case <-ctx.Done():
return newTimeoutError("logr queue shutdown timeout")
case <-rec.flush:
}
return nil
}
// Shutdown cleanly stops the logging engine after making best efforts
// to flush all targets. Call this function right before application
// exit - logr cannot be restarted once shut down.
// `logr.ShutdownTimeout` determines how long shutdown can execute before
// timing out. Use `IsTimeoutError` to determine if the returned error is
// due to a timeout.
func (logr *Logr) Shutdown() error {
logr.mux.Lock()
if logr.shutdown {
logr.mux.Unlock()
return errors.New("Shutdown called again after shut down")
}
logr.shutdown = true
logr.resetLevelCache()
logr.mux.Unlock()
errs := merror.New()
ctx, cancel := context.WithTimeout(context.Background(), logr.shutdownTimeout())
defer cancel()
// close the incoming channel and wait for read loop to exit.
if logr.in != nil {
close(logr.in)
select {
case <-ctx.Done():
errs.Append(newTimeoutError("logr queue shutdown timeout"))
case <-logr.done:
}
}
// logr.in channel should now be drained to targets and no more log records
// can be added.
logr.tmux.RLock()
defer logr.tmux.RUnlock()
for _, t := range logr.targets {
err := t.Shutdown(ctx)
if err != nil {
errs.Append(err)
}
}
return errs.ErrorOrNil()
}
// ReportError is used to notify the host application of any internal logging errors.
// If `OnLoggerError` is not nil, it is called with the error, otherwise the error is
// output to `os.Stderr`.
func (logr *Logr) ReportError(err interface{}) {
if logr.OnLoggerError == nil {
fmt.Fprintln(os.Stderr, err)
return
}
logr.OnLoggerError(fmt.Errorf("%v", err))
}
// BorrowBuffer borrows a buffer from the pool. Release the buffer to reduce garbage collection.
func (logr *Logr) BorrowBuffer() *bytes.Buffer {
if logr.DisableBufferPool {
return &bytes.Buffer{}
}
return logr.bufferPool.Get().(*bytes.Buffer)
}
// ReleaseBuffer returns a buffer to the pool to reduce garbage collection. The buffer is only
// retained if less than MaxPooledBuffer.
func (logr *Logr) ReleaseBuffer(buf *bytes.Buffer) {
if !logr.DisableBufferPool && buf.Cap() < logr.MaxPooledBuffer {
buf.Reset()
logr.bufferPool.Put(buf)
}
}
// enqueueTimeout returns amount of time a log record can take to be queued.
// This only applies to blocking enqueue which happen after `logr.OnQueueFull` is called
// and returns false.
func (logr *Logr) enqueueTimeout() time.Duration {
if logr.EnqueueTimeout == 0 {
return DefaultEnqueueTimeout
}
return logr.EnqueueTimeout
}
// shutdownTimeout returns the timeout duration for `logr.Shutdown`.
func (logr *Logr) shutdownTimeout() time.Duration {
if logr.ShutdownTimeout == 0 {
return DefaultShutdownTimeout
}
return logr.ShutdownTimeout
}
// flushTimeout returns the timeout duration for `logr.Flush`.
func (logr *Logr) flushTimeout() time.Duration {
if logr.FlushTimeout == 0 {
return DefaultFlushTimeout
}
return logr.FlushTimeout
}
// start selects on incoming log records until done channel signals.
// Incoming log records are fanned out to all log targets.
func (logr *Logr) start() {
defer func() {
if r := recover(); r != nil {
logr.ReportError(r)
go logr.start()
}
}()
for rec := range logr.in {
if rec.flush != nil {
logr.flush(rec.flush)
} else {
rec.prep()
logr.fanout(rec)
}
}
close(logr.done)
}
// fanout pushes a LogRec to all targets.
func (logr *Logr) fanout(rec *LogRec) {
var target Target
defer func() {
if r := recover(); r != nil {
logr.ReportError(fmt.Errorf("fanout failed for target %s, %v", target, r))
}
}()
logr.tmux.RLock()
defer logr.tmux.RUnlock()
for _, target = range logr.targets {
if enabled, _ := target.IsLevelEnabled(rec.Level()); enabled {
target.Log(rec)
}
}
}
// flush drains the queue and notifies when done.
func (logr *Logr) flush(done chan<- struct{}) {
// first drain the logr queue.
loop:
for {
var rec *LogRec
select {
case rec = <-logr.in:
if rec.flush == nil {
rec.prep()
logr.fanout(rec)
}
default:
break loop
}
}
logger := logr.NewLogger()
// drain all the targets; block until finished.
logr.tmux.RLock()
defer logr.tmux.RUnlock()
for _, target := range logr.targets {
rec := newFlushLogRec(logger)
target.Log(rec)
<-rec.flush
}
done <- struct{}{}
}

189
vendor/github.com/wiggin77/logr/logrec.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,189 @@
package logr
import (
"fmt"
"runtime"
"strings"
"sync"
"time"
)
var (
logrPkg string
)
func init() {
// Calc current package name
pcs := make([]uintptr, 2)
_ = runtime.Callers(0, pcs)
tmp := runtime.FuncForPC(pcs[1]).Name()
logrPkg = getPackageName(tmp)
}
// LogRec collects raw, unformatted data to be logged.
// TODO: pool these? how to reliably know when targets are done with them? Copy for each target?
type LogRec struct {
mux sync.RWMutex
time time.Time
level Level
logger Logger
template string
newline bool
args []interface{}
stackPC []uintptr
stackCount int
// flushes Logr and target queues when not nil.
flush chan struct{}
// remaining fields calculated by `prep`
msg string
frames []runtime.Frame
}
// NewLogRec creates a new LogRec with the current time and optional stack trace.
func NewLogRec(lvl Level, logger Logger, template string, args []interface{}, incStacktrace bool) *LogRec {
rec := &LogRec{time: time.Now(), logger: logger, level: lvl, template: template, args: args}
if incStacktrace {
rec.stackPC = make([]uintptr, DefaultMaxStackFrames)
rec.stackCount = runtime.Callers(2, rec.stackPC)
}
return rec
}
// newFlushLogRec creates a LogRec that flushes the Logr queue and
// any target queues that support flushing.
func newFlushLogRec(logger Logger) *LogRec {
return &LogRec{logger: logger, flush: make(chan struct{})}
}
// prep resolves all args and field values to strings, and
// resolves stack trace to frames.
func (rec *LogRec) prep() {
rec.mux.Lock()
defer rec.mux.Unlock()
// resolve args
if rec.template == "" {
if rec.newline {
rec.msg = fmt.Sprintln(rec.args...)
} else {
rec.msg = fmt.Sprint(rec.args...)
}
} else {
rec.msg = fmt.Sprintf(rec.template, rec.args...)
}
// resolve stack trace
if rec.stackCount > 0 {
frames := runtime.CallersFrames(rec.stackPC[:rec.stackCount])
for {
f, more := frames.Next()
rec.frames = append(rec.frames, f)
if !more {
break
}
}
// remove leading logr package entries.
var start int
for i, frame := range rec.frames {
pkg := getPackageName(frame.Function)
if pkg != "" && pkg != logrPkg {
start = i
break
}
}
rec.frames = rec.frames[start:]
}
}
// WithTime returns a shallow copy of the log record while replacing
// the time. This can be used by targets and formatters to adjust
// the time, or take ownership of the log record.
func (rec *LogRec) WithTime(time time.Time) *LogRec {
rec.mux.RLock()
defer rec.mux.RUnlock()
return &LogRec{
time: time,
level: rec.level,
logger: rec.logger,
template: rec.template,
newline: rec.newline,
args: rec.args,
msg: rec.msg,
stackPC: rec.stackPC,
stackCount: rec.stackCount,
frames: rec.frames,
}
}
// Logger returns the `Logger` that created this `LogRec`.
func (rec *LogRec) Logger() Logger {
return rec.logger
}
// Time returns this log record's time stamp.
func (rec *LogRec) Time() time.Time {
// no locking needed as this field is not mutated.
return rec.time
}
// Level returns this log record's Level.
func (rec *LogRec) Level() Level {
// no locking needed as this field is not mutated.
return rec.level
}
// Fields returns this log record's Fields.
func (rec *LogRec) Fields() Fields {
// no locking needed as this field is not mutated.
return rec.logger.fields
}
// Msg returns this log record's message text.
func (rec *LogRec) Msg() string {
rec.mux.RLock()
defer rec.mux.RUnlock()
return rec.msg
}
// StackFrames returns this log record's stack frames or
// nil if no stack trace was required.
func (rec *LogRec) StackFrames() []runtime.Frame {
rec.mux.RLock()
defer rec.mux.RUnlock()
return rec.frames
}
// String returns a string representation of this log record.
func (rec *LogRec) String() string {
if rec.flush != nil {
return "[flusher]"
}
f := &DefaultFormatter{}
buf := rec.logger.logr.BorrowBuffer()
defer rec.logger.logr.ReleaseBuffer(buf)
buf, _ = f.Format(rec, true, buf)
return strings.TrimSpace(buf.String())
}
// getPackageName reduces a fully qualified function name to the package name
// By sirupsen: https://github.com/sirupsen/logrus/blob/master/entry.go
func getPackageName(f string) string {
for {
lastPeriod := strings.LastIndex(f, ".")
lastSlash := strings.LastIndex(f, "/")
if lastPeriod > lastSlash {
f = f[:lastPeriod]
} else {
break
}
}
return f
}

152
vendor/github.com/wiggin77/logr/target.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,152 @@
package logr
import (
"context"
"fmt"
"os"
"time"
)
// Target represents a destination for log records such as file,
// database, TCP socket, etc.
type Target interface {
// IsLevelEnabled returns true if this target should emit
// logs for the specified level. Also determines if
// a stack trace is required.
IsLevelEnabled(Level) (enabled bool, stacktrace bool)
// Formatter returns the Formatter associated with this Target.
Formatter() Formatter
// Log outputs the log record to this target's destination.
Log(rec *LogRec)
// Shutdown makes best effort to flush target queue and
// frees/closes all resources.
Shutdown(ctx context.Context) error
}
// RecordWriter can convert a LogRecord to bytes and output to some data sink.
type RecordWriter interface {
Write(rec *LogRec) error
}
// Basic provides the basic functionality of a Target that can be used
// to more easily compose your own Targets. To use, just embed Basic
// in your target type, implement `RecordWriter`, and call `Start`.
type Basic struct {
target Target
filter Filter
formatter Formatter
in chan *LogRec
done chan struct{}
w RecordWriter
}
// Start initializes this target helper and starts accepting log records for processing.
func (b *Basic) Start(target Target, rw RecordWriter, filter Filter, formatter Formatter, maxQueued int) {
if filter == nil {
filter = &StdFilter{Lvl: Fatal}
}
if formatter == nil {
formatter = &DefaultFormatter{}
}
b.target = target
b.filter = filter
b.formatter = formatter
b.in = make(chan *LogRec, maxQueued)
b.done = make(chan struct{}, 1)
b.w = rw
go b.start()
}
// IsLevelEnabled returns true if this target should emit
// logs for the specified level. Also determines if
// a stack trace is required.
func (b *Basic) IsLevelEnabled(lvl Level) (enabled bool, stacktrace bool) {
return b.filter.IsEnabled(lvl), b.filter.IsStacktraceEnabled(lvl)
}
// Formatter returns the Formatter associated with this Target.
func (b *Basic) Formatter() Formatter {
return b.formatter
}
// Shutdown stops processing log records after making best
// effort to flush queue.
func (b *Basic) Shutdown(ctx context.Context) error {
// close the incoming channel and wait for read loop to exit.
close(b.in)
select {
case <-ctx.Done():
case <-b.done:
}
// b.in channel should now be drained.
return nil
}
// Log outputs the log record to this targets destination.
func (b *Basic) Log(rec *LogRec) {
lgr := rec.Logger().Logr()
select {
case b.in <- rec:
default:
handler := lgr.OnTargetQueueFull
if handler != nil && handler(b.target, rec, cap(b.in)) {
return // drop the record
}
select {
case <-time.After(lgr.enqueueTimeout()):
lgr.ReportError(fmt.Errorf("target enqueue timeout for log rec [%v]", rec))
case b.in <- rec: // block until success or timeout
}
}
}
// Start accepts log records via In channel and writes to the
// supplied writer, until Done channel signaled.
func (b *Basic) start() {
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(os.Stderr, "Basic.start -- ", r)
go b.start()
}
}()
for rec := range b.in {
if rec.flush != nil {
b.flush(rec.flush)
} else {
err := b.w.Write(rec)
if err != nil {
rec.Logger().Logr().ReportError(err)
}
}
}
close(b.done)
}
// flush drains the queue and notifies when done.
func (b *Basic) flush(done chan<- struct{}) {
for {
var rec *LogRec
var err error
select {
case rec = <-b.in:
// ignore any redundant flush records.
if rec.flush == nil {
err = b.w.Write(rec)
if err != nil {
rec.Logger().Logr().ReportError(err)
}
}
default:
done <- struct{}{}
return
}
}
}

34
vendor/github.com/wiggin77/logr/timeout.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
package logr
import "github.com/wiggin77/merror"
// timeoutError is returned from functions that can timeout.
type timeoutError struct {
text string
}
// newTimeoutError returns a TimeoutError.
func newTimeoutError(text string) timeoutError {
return timeoutError{text: text}
}
// IsTimeoutError returns true if err is a TimeoutError.
func IsTimeoutError(err error) bool {
if _, ok := err.(timeoutError); ok {
return true
}
// if a multi-error, return true if any of the errors
// are TimeoutError
if merr, ok := err.(*merror.MError); ok {
for _, e := range merr.Errors() {
if IsTimeoutError(e) {
return true
}
}
}
return false
}
func (err timeoutError) Error() string {
return err.text
}

22
vendor/github.com/wiggin77/logrus4logr/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,22 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Log files
*.log
# test apps
test/cmd/textformatter/textformatter
test/cmd/nestedformatter/nestedformatter
test/cmd/fluentdformatter/fluentdformatter
test/cmd/lfshook/lfshook
test/cmd/lfshook-simple/lfshook-simple

21
vendor/github.com/wiggin77/logrus4logr/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 wiggin77
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

91
vendor/github.com/wiggin77/logrus4logr/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,91 @@
# logrus4logr
[![GoDoc](https://godoc.org/github.com/wiggin77/logrus4logr?status.svg)](https://godoc.org/github.com/wiggin77/logrus4logr)
Provides adapters for using [Logrus](https://github.com/sirupsen/logrus) hooks and formatters with [Logr](https://github.com/wiggin77/logr).
While Logrus hooks and formatters can easily be modified to work directly with Logr, these adapters are provided for convenience.
## Hooks
A Logrus hook can be adapted to a Logr target. The example below uses [LFSHook](https://github.com/rifflock/lfshook).
More examples can be found [here](./test/cmd).
```go
package main
import (
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"github.com/wiggin77/logr"
"github.com/wiggin77/logrus4logr"
)
func main() {
var lgr = &logr.Logr{}
// create a Local File System Hook (LFSHook)
pathMap := lfshook.PathMap{
logrus.InfoLevel: "./info.log",
logrus.WarnLevel: "./warn.log",
logrus.ErrorLevel: "./error.log",
}
lfsHook := lfshook.NewHook(pathMap, &logrus.JSONFormatter{})
// log severity Info or higher.
filter := &logr.StdFilter{Lvl: logr.Info}
// create adapter wrapping lfshook.
target := logrus4logr.NewAdapterTarget(filter, nil, lfsHook, 1000)
lgr.AddTarget(target)
// log stuff!
logger := lgr.NewLogger().WithField("status", "woot!")
logger.Info("I'm hooked on Logr")
logger.WithField("code", 501).Error("Request failed")
lgr.Shutdown()
}
```
## Formatters
A Logrus formatter can be used by Logr via an adapter. The example below uses Logrus' built-in TextFormatter.
More examples can be found [here](./test/cmd).
```go
package main
import (
"github.com/sirupsen/logrus"
"github.com/wiggin77/logr"
"github.com/wiggin77/logrus4logr"
)
func main() {
var lgr = &logr.Logr{}
// create a Logrus TextFormatter with whatever settings you prefer.
logrusFormatter := &logrus.TextFormatter{
// settings...
}
// log severity Info or higher.
filter := &logr.StdFilter{Lvl: logr.Info}
// wrap TextFormatter in Logr adapter.
formatter := &logrus4logr.FAdapter{Fmtr: logrusFormatter}
// create writer target to stdout using adapter.
var t logr.Target
t = target.NewWriterTarget(filter, formatter, os.Stdout, 1000)
lgr.AddTarget(t)
// log stuff!
logger := lgr.NewLogger().WithField("status", "woot!")
logger.Info("I'm hooked on Logr")
logger.WithField("code", 501).Error("Request failed")
lgr.Shutdown()
}
```

51
vendor/github.com/wiggin77/logrus4logr/convert.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,51 @@
package logrus4logr
import (
"github.com/wiggin77/logr"
"github.com/sirupsen/logrus"
)
func convertLogRec(rec *logr.LogRec, rus *logrus.Logger) *logrus.Entry {
entry := &logrus.Entry{
Logger: rus,
Data: convertFields(rec.Fields()),
Time: rec.Time(),
Level: convertLevel(rec.Level()),
//Caller: *runtime.Frame
Message: rec.Msg(),
//Buffer *bytes.Buffer
//Context context.Context
//err string
}
return entry
}
func convertLevel(lvl logr.Level) logrus.Level {
switch lvl {
case logr.Panic:
return logrus.PanicLevel
case logr.Fatal:
return logrus.FatalLevel
case logr.Error:
return logrus.ErrorLevel
case logr.Warn:
return logrus.WarnLevel
case logr.Info:
return logrus.InfoLevel
case logr.Debug:
return logrus.DebugLevel
case logr.Trace:
return logrus.TraceLevel
default:
return logrus.InfoLevel
}
}
func convertFields(flds logr.Fields) logrus.Fields {
f := make(logrus.Fields, len(flds))
for k, v := range flds {
f[k] = v
}
return f
}

36
vendor/github.com/wiggin77/logrus4logr/formatter.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,36 @@
package logrus4logr
import (
"bytes"
"sync"
"github.com/sirupsen/logrus"
"github.com/wiggin77/logr"
)
// FAdapter wraps a Logrus formatter so it can be used as a Logr formatter.
type FAdapter struct {
// Fmtr is the Logrus formatter to wrap.
Fmtr logrus.Formatter
// Logger is an optional logrus.Logger instance to use instead of the default.
Logger *logrus.Logger
once sync.Once
}
// Format converts a log record to bytes using a Logrus formatter.
func (a *FAdapter) Format(rec *logr.LogRec, stacktrace bool, buf *bytes.Buffer) (*bytes.Buffer, error) {
a.once.Do(func() {
if a.Logger == nil {
a.Logger = logrus.StandardLogger()
}
})
entry := convertLogRec(rec, a.Logger)
data, err := a.Fmtr.Format(entry)
if err == nil {
buf.Write(data)
}
return buf, err
}

15
vendor/github.com/wiggin77/logrus4logr/go.mod сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
module github.com/wiggin77/logrus4logr
go 1.13
require (
github.com/Freman/eventloghook v0.0.0-20191003051739-e4d803b6b48b
github.com/antonfisher/nested-logrus-formatter v1.0.2
github.com/joonix/log v0.0.0-20190524090622-13fe31bbdd7a
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.4.2
github.com/wiggin77/logr v1.0.3
golang.org/x/sys v0.0.0-20191008105621-543471e840be
google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd // indirect
)

218
vendor/github.com/wiggin77/logrus4logr/go.sum сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,218 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Freman/eventloghook v0.0.0-20191003051739-e4d803b6b48b h1:IltY1fRcdIshI/c8KOdmaO8P4lBwDXHJYPymMisvvDs=
github.com/Freman/eventloghook v0.0.0-20191003051739-e4d803b6b48b/go.mod h1:VGwG8f2pQ8SAFjTSH3PEDmLdlvi0XTd7a4C4AZn+pVw=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antonfisher/nested-logrus-formatter v1.0.2 h1:t65eOqj0fWbOkZR2+OgmxPa0KYIwbPhKdYmseaCMIyI=
github.com/antonfisher/nested-logrus-formatter v1.0.2/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
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/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
github.com/joonix/log v0.0.0-20190524090622-13fe31bbdd7a h1:LL1gwNo4Z1LG68SaaNb8bxB+YnMSilYzytRfkF3AigE=
github.com/joonix/log v0.0.0-20190524090622-13fe31bbdd7a/go.mod h1:fS54ONkjDV71zS9CDx3V9K21gJg7byKSvI4ajuWFNJw=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
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/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nsf/jsondiff v0.0.0-20190712045011-8443391ee9b6/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs=
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pkg/errors v0.8.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/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/wiggin77/cfg v1.0.2 h1:NBUX+iJRr+RTncTqTNvajHwzduqbhCQjEqxLHr6Fk7A=
github.com/wiggin77/cfg v1.0.2/go.mod h1:b3gotba2e5bXTqTW48DwIFoLc+4lWKP7WPi/CdvZ4aE=
github.com/wiggin77/logr v0.0.0-20191008153504-baac1b801e73 h1:lRao0Wc0zDcje991m1OQzCDXDhJ2dAU2J+214tEoUdQ=
github.com/wiggin77/logr v0.0.0-20191008153504-baac1b801e73/go.mod h1:VZeJzSbyHqC3zInXnFBJZURn9rGbqlTzlO2m5wdijZ8=
github.com/wiggin77/logr v0.0.0-20191009035425-189ce7304c34 h1:XhYLDM920VmlED8oElS+0/odwPeH3qkkmlvS0VVwCPE=
github.com/wiggin77/logr v0.0.0-20191009035425-189ce7304c34/go.mod h1:VZeJzSbyHqC3zInXnFBJZURn9rGbqlTzlO2m5wdijZ8=
github.com/wiggin77/logr v0.0.0-20191011233000-e3bc20703517 h1:vdjEWflo0H1hEt2Iw9A3aqtCWx8dnUmIYstZtLsF2Hg=
github.com/wiggin77/logr v0.0.0-20191011233000-e3bc20703517/go.mod h1:9sOJ1T4F2YdtgMrMaq9I1PiTV8R6wKModG5qZH+ba/s=
github.com/wiggin77/logr v0.0.0-20191014204114-2df550845cfc h1:ZTtN7Tg+n2OAhQTy++YLQBl52pdUyOWPXTB6wjFdb5g=
github.com/wiggin77/logr v0.0.0-20191014204114-2df550845cfc/go.mod h1:9sOJ1T4F2YdtgMrMaq9I1PiTV8R6wKModG5qZH+ba/s=
github.com/wiggin77/logr v0.0.0-20200207002347-890d83b925be h1:lGz7zKuDckJCH48b4YCEV8nNOmETu6bW3CCws7/Euvc=
github.com/wiggin77/logr v0.0.0-20200207002347-890d83b925be/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/logr v0.0.0-20200207172336-0c93e6357eb5 h1:PahhDMzc5XrJg/mgT87Aav4npUCkA5cBGyN9WQw3GVY=
github.com/wiggin77/logr v0.0.0-20200207172336-0c93e6357eb5/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/logr v0.0.0-20200207192333-388c3fe88257 h1:SusN+cM1cWx20H9vv4N3dQUIlhfncUxLi8lokmo8ZUs=
github.com/wiggin77/logr v0.0.0-20200207192333-388c3fe88257/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/logr v1.0.0 h1:i0hCQjlUpwBYdcu7iqf3hQCNIH9uf9Y2jbwcReNPscc=
github.com/wiggin77/logr v1.0.0/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/logr v1.0.2 h1:zNuYJ+UABevEFhvlEi/MXGYiZgVrMmUJPPt60xmByBs=
github.com/wiggin77/logr v1.0.2/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/logr v1.0.3 h1:4Cj899GZJInB9vudlxsmLRDsBlsw9pE/nyJo9XZ/yzo=
github.com/wiggin77/logr v1.0.3/go.mod h1:oIvnsSkyTQojUsr7QO0d4rE2afZbsTj/5WbiikGJu3E=
github.com/wiggin77/merror v1.0.2 h1:V0nH9eFp64ASyaXC+pB5WpvBoCg7NUwvaCSKdzlcHqw=
github.com/wiggin77/merror v1.0.2/go.mod h1:uQTcIU0Z6jRK4OwqganPYerzQxSFJ4GSHM3aurxxQpg=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 h1:4rNOqY4ULrKzS6twXa619uQgI7h9PaVd4ZhjFQ7C5zs=
google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd h1:84VQPzup3IpKLxuIAZjHMhVjJ8fZ4/i3yUnj3k6fUdw=
google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

44
vendor/github.com/wiggin77/logrus4logr/target.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,44 @@
package logrus4logr
import (
"fmt"
"github.com/wiggin77/logr"
"github.com/sirupsen/logrus"
)
// TAdapter wraps a Logrus hook allowing the hook be used as a Logr target.
// Create instances with `NewAdapterTarget`.
type TAdapter struct {
logr.Basic
hook logrus.Hook
// Logger is an optional logrus.Logger instance to use instead of the default.
Logger *logrus.Logger
}
// NewAdapterTarget creates a target wrapper for a Logrus hook.
// If filter and/or formatter are nil then defaults will be used (Panic level; Plain formatter).
func NewAdapterTarget(filter logr.Filter, formatter logr.Formatter, hook logrus.Hook, maxQueue int) *TAdapter {
a := &TAdapter{hook: hook}
a.Basic.Start(a, a, filter, formatter, maxQueue)
return a
}
// Write converts a log record to a Logrus entry and
// passes it to the Logrus hook.
func (a *TAdapter) Write(rec *logr.LogRec) error {
rus := a.Logger
if rus == nil {
rus = logrus.StandardLogger()
}
entry := convertLogRec(rec, rus)
return a.hook.Fire(entry)
}
// String returns the type name of the Logrus hook.
func (a *TAdapter) String() string {
return fmt.Sprintf("%T", a.hook)
}

12
vendor/github.com/wiggin77/merror/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,12 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

21
vendor/github.com/wiggin77/merror/LICENSE сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 wiggin77
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
vendor/github.com/wiggin77/merror/README.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,2 @@
# merror
Multiple Error aggregator for Golang.

43
vendor/github.com/wiggin77/merror/format.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
package merror
import (
"fmt"
"strings"
)
// FormatterFunc is a function that converts a merror
// to a string.
type FormatterFunc func(merr *MError) string
// GlobalFormatter is the global merror formatter.
// Set this to a custom formatter if desired.
var GlobalFormatter = defaultFormatter
// defaultFormatter
func defaultFormatter(merr *MError) string {
count := 0
overflow := 0
var format func(sb *strings.Builder, merr *MError, indent string)
format = func(sb *strings.Builder, merr *MError, indent string) {
count += merr.Len()
overflow += merr.Overflow()
fmt.Fprintf(sb, "%sMError:\n", indent)
for _, err := range merr.Errors() {
if e, ok := err.(*MError); ok {
format(sb, e, indent+" ")
} else {
fmt.Fprintf(sb, "%s%s\n", indent, err.Error())
}
}
}
sb := &strings.Builder{}
format(sb, merr, "")
fmt.Fprintf(sb, "%d errors total.\n", count)
if merr.overflow > 0 {
fmt.Fprintf(sb, "%d errors truncated.\n", overflow)
}
return sb.String()
}

1
vendor/github.com/wiggin77/merror/go.mod сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
module github.com/wiggin77/merror

87
vendor/github.com/wiggin77/merror/merror.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,87 @@
package merror
// MError represents zero or more errors that can be
// accumulated via the `Append` method.
type MError struct {
cap int
errors []error
overflow int
formatter FormatterFunc
}
// New returns a new instance of `MError` with no limit on the
// number of errors that can be appended.
func New() *MError {
me := &MError{}
me.errors = make([]error, 0, 10)
return me
}
// NewWithCap returns a new instance of `MError` with a maximum
// capacity of `cap` errors. If exceeded only the overflow counter
// will be incremented.
//
// A `cap` of zero of less means no cap and max size of a slice
// on the current platform is the upper bound.
func NewWithCap(cap int) *MError {
me := New()
me.cap = cap
return me
}
// Append adds an error to the aggregated error list.
func (me *MError) Append(err error) {
if err == nil {
return
}
if me.cap > 0 && len(me.errors) >= me.cap {
me.overflow++
} else {
me.errors = append(me.errors, err)
}
}
// Errors returns an array of the `error` instances that have been
// appended to this `MError`.
func (me *MError) Errors() []error {
return me.errors
}
// Len returns the number of errors that have been appended.
func (me *MError) Len() int {
return len(me.errors)
}
// Overflow returns the number of errors that have been truncated
// because maximum capacity was exceeded.
func (me *MError) Overflow() int {
return me.overflow
}
// SetFormatter sets the `FormatterFunc` to be used when `Error` is
// called. The previous `FormatterFunc` is returned.
func (me *MError) SetFormatter(f FormatterFunc) (old FormatterFunc) {
old = me.formatter
me.formatter = f
return
}
// ErrorOrNil returns nil if this `MError` contains no errors,
// otherwise this `MError` is returned.
func (me *MError) ErrorOrNil() error {
if me == nil || len(me.errors) == 0 {
return nil
}
return me
}
// Error returns a string representation of this MError.
// The output format depends on the `Formatter` set for this
// merror instance, or the global formatter if none set.
func (me *MError) Error() string {
f := me.formatter
if f == nil {
f = GlobalFormatter
}
return f(me)
}