summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/logr/logrec.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/mattermost/logr/logrec.go')
-rw-r--r--vendor/github.com/mattermost/logr/logrec.go189
1 files changed, 189 insertions, 0 deletions
diff --git a/vendor/github.com/mattermost/logr/logrec.go b/vendor/github.com/mattermost/logr/logrec.go
new file mode 100644
index 00000000..9428aaec
--- /dev/null
+++ b/vendor/github.com/mattermost/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
+}