This file is indexed.

/usr/share/gocode/src/github.com/tendermint/log15/ext/handler.go is in golang-github-tendermint-log15-dev 2.3-67-g9545b24-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package ext

import (
	"os"
	"sync"
	"sync/atomic"
	"unsafe"

	log "github.com/tendermint/log15"
)

// EscalateErrHandler wraps another handler and passes all records through
// unchanged except if the logged context contains a non-nil error
// value in its context. In that case, the record's level is raised
// to LvlError unless it was already more serious (LvlCrit).
//
// This allows you to log the result of all functions for debugging
// and still capture error conditions when in production with a single
// log line. As an example, the following the log record will be written
// out only if there was an error writing a value to redis:
//
//     logger := logext.EscalateErrHandler(
//         log.LvlFilterHandler(log.LvlInfo, log.StdoutHandler))
//
//     reply, err := redisConn.Do("SET", "foo", "bar")
//     logger.Debug("Wrote value to redis", "reply", reply, "err", err)
//     if err != nil {
//         return err
//     }
//
func EscalateErrHandler(h log.Handler) log.Handler {
	return log.FuncHandler(func(r *log.Record) error {
		if r.Lvl > log.LvlError {
			for i := 1; i < len(r.Ctx); i++ {
				if v, ok := r.Ctx[i].(error); ok && v != nil {
					r.Lvl = log.LvlError
					break
				}
			}
		}
		return h.Log(r)
	})
}

// SpeculativeHandler is a handler for speculative logging. It
// keeps a ring buffer of the given size full of the last events
// logged into it. When Flush is called, all buffered log records
// are written to the wrapped handler. This is extremely for
// continuosly capturing debug level output, but only flushing those
// log records if an exceptional condition is encountered.
func SpeculativeHandler(size int, h log.Handler) *Speculative {
	return &Speculative{
		handler: h,
		recs:    make([]*log.Record, size),
	}
}

type Speculative struct {
	mu      sync.Mutex
	idx     int
	recs    []*log.Record
	handler log.Handler
	full    bool
}

func (h *Speculative) Log(r *log.Record) error {
	h.mu.Lock()
	defer h.mu.Unlock()
	h.recs[h.idx] = r
	h.idx = (h.idx + 1) % len(h.recs)
	h.full = h.full || h.idx == 0
	return nil
}

func (h *Speculative) Flush() {
	recs := make([]*log.Record, 0)
	func() {
		h.mu.Lock()
		defer h.mu.Unlock()
		if h.full {
			recs = append(recs, h.recs[h.idx:]...)
		}
		recs = append(recs, h.recs[:h.idx]...)

		// reset state
		h.full = false
		h.idx = 0
	}()

	// don't hold the lock while we flush to the wrapped handler
	for _, r := range recs {
		h.handler.Log(r)
	}
}

// HotSwapHandler wraps another handler that may swapped out
// dynamically at runtime in a thread-safe fashion.
// HotSwapHandler is the same functionality
// used to implement the SetHandler method for the default
// implementation of Logger.
func HotSwapHandler(h log.Handler) *HotSwap {
	hs := new(HotSwap)
	hs.Swap(h)
	return hs
}

type HotSwap struct {
	handler unsafe.Pointer
}

func (h *HotSwap) Log(r *log.Record) error {
	return (*(*log.Handler)(atomic.LoadPointer(&h.handler))).Log(r)
}

func (h *HotSwap) Swap(newHandler log.Handler) {
	atomic.StorePointer(&h.handler, unsafe.Pointer(&newHandler))
}

// FatalHandler makes critical errors exit the program
// immediately, much like the log.Fatal* methods from the
// standard log package
func FatalHandler(h log.Handler) log.Handler {
	return log.FuncHandler(func(r *log.Record) error {
		err := h.Log(r)
		if r.Lvl == log.LvlCrit {
			os.Exit(1)
		}
		return err
	})
}