Source File
entry.go
Belonging Package
go.uber.org/zap/zapcore
// Copyright (c) 2016 Uber Technologies, Inc.//// 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.package zapcoreimport ()var _cePool = pool.New(func() *CheckedEntry {// Pre-allocate some space for cores.return &CheckedEntry{cores: make([]Core, 4),}})func () *CheckedEntry {:= _cePool.Get().reset()return}func ( *CheckedEntry) {if == nil {return}_cePool.Put()}// NewEntryCaller makes an EntryCaller from the return signature of// runtime.Caller.func ( uintptr, string, int, bool) EntryCaller {if ! {return EntryCaller{}}return EntryCaller{PC: ,File: ,Line: ,Defined: true,}}// EntryCaller represents the caller of a logging function.type EntryCaller struct {Defined boolPC uintptrFile stringLine intFunction string}// String returns the full path and line number of the caller.func ( EntryCaller) () string {return .FullPath()}// FullPath returns a /full/path/to/package/file:line description of the// caller.func ( EntryCaller) () string {if !.Defined {return "undefined"}:= bufferpool.Get().AppendString(.File).AppendByte(':').AppendInt(int64(.Line)):= .String().Free()return}// TrimmedPath returns a package/file:line description of the caller,// preserving only the leaf directory name and file name.func ( EntryCaller) () string {if !.Defined {return "undefined"}// nb. To make sure we trim the path correctly on Windows too, we// counter-intuitively need to use '/' and *not* os.PathSeparator here,// because the path given originates from Go stdlib, specifically// runtime.Caller() which (as of Mar/17) returns forward slashes even on// Windows.//// See https://github.com/golang/go/issues/3335// and https://github.com/golang/go/issues/18151//// for discussion on the issue on Go side.//// Find the last separator.//:= strings.LastIndexByte(.File, '/')if == -1 {return .FullPath()}// Find the penultimate separator.= strings.LastIndexByte(.File[:], '/')if == -1 {return .FullPath()}:= bufferpool.Get()// Keep everything after the penultimate separator..AppendString(.File[+1:]).AppendByte(':').AppendInt(int64(.Line)):= .String().Free()return}// An Entry represents a complete log message. The entry's structured context// is already serialized, but the log level, time, message, and call site// information are available for inspection and modification. Any fields left// empty will be omitted when encoding.//// Entries are pooled, so any functions that accept them MUST be careful not to// retain references to them.type Entry struct {Level LevelTime time.TimeLoggerName stringMessage stringCaller EntryCallerStack string}// CheckWriteHook is a custom action that may be executed after an entry is// written.//// Register one on a CheckedEntry with the After method.//// if ce := logger.Check(...); ce != nil {// ce = ce.After(hook)// ce.Write(...)// }//// You can configure the hook for Fatal log statements at the logger level with// the zap.WithFatalHook option.type CheckWriteHook interface {// OnWrite is invoked with the CheckedEntry that was written and a list// of fields added with that entry.//// The list of fields DOES NOT include fields that were already added// to the logger with the With method.OnWrite(*CheckedEntry, []Field)}// CheckWriteAction indicates what action to take after a log entry is// processed. Actions are ordered in increasing severity.type CheckWriteAction uint8const (// WriteThenNoop indicates that nothing special needs to be done. It's the// default behavior.WriteThenNoop CheckWriteAction = iota// WriteThenGoexit runs runtime.Goexit after Write.WriteThenGoexit// WriteThenPanic causes a panic after Write.WriteThenPanic// WriteThenFatal causes an os.Exit(1) after Write.WriteThenFatal)// OnWrite implements the OnWrite method to keep CheckWriteAction compatible// with the new CheckWriteHook interface which deprecates CheckWriteAction.func ( CheckWriteAction) ( *CheckedEntry, []Field) {switch {case WriteThenGoexit:runtime.Goexit()case WriteThenPanic:panic(.Message)case WriteThenFatal:exit.With(1)}}var _ CheckWriteHook = CheckWriteAction(0)// CheckedEntry is an Entry together with a collection of Cores that have// already agreed to log it.//// CheckedEntry references should be created by calling AddCore or After on a// nil *CheckedEntry. References are returned to a pool after Write, and MUST// NOT be retained after calling their Write method.type CheckedEntry struct {EntryErrorOutput WriteSyncerdirty bool // best-effort detection of pool misuseafter CheckWriteHookcores []Core}func ( *CheckedEntry) () {.Entry = Entry{}.ErrorOutput = nil.dirty = false.after = nilfor := range .cores {// don't keep references to cores.cores[] = nil}.cores = .cores[:0]}// Write writes the entry to the stored Cores, returns any errors, and returns// the CheckedEntry reference to a pool for immediate re-use. Finally, it// executes any required CheckWriteAction.func ( *CheckedEntry) ( ...Field) {if == nil {return}if .dirty {if .ErrorOutput != nil {// Make a best effort to detect unsafe re-use of this CheckedEntry.// If the entry is dirty, log an internal error; because the// CheckedEntry is being used after it was returned to the pool,// the message may be an amalgamation from multiple call sites.fmt.Fprintf(.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", .Time, .Entry)_ = .ErrorOutput.Sync() // ignore error}return}.dirty = truevar errorfor := range .cores {= multierr.Append(, .cores[].Write(.Entry, ))}if != nil && .ErrorOutput != nil {fmt.Fprintf(.ErrorOutput, "%v write error: %v\n", .Time, )_ = .ErrorOutput.Sync() // ignore error}:= .afterif != nil {.OnWrite(, )}putCheckedEntry()}// AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be// used by Core.Check implementations, and is safe to call on nil CheckedEntry// references.func ( *CheckedEntry) ( Entry, Core) *CheckedEntry {if == nil {= getCheckedEntry().Entry =}.cores = append(.cores, )return}// Should sets this CheckedEntry's CheckWriteAction, which controls whether a// Core will panic or fatal after writing this log entry. Like AddCore, it's// safe to call on nil CheckedEntry references.//// Deprecated: Use [CheckedEntry.After] instead.func ( *CheckedEntry) ( Entry, CheckWriteAction) *CheckedEntry {return .After(, )}// After sets this CheckEntry's CheckWriteHook, which will be called after this// log entry has been written. It's safe to call this on nil CheckedEntry// references.func ( *CheckedEntry) ( Entry, CheckWriteHook) *CheckedEntry {if == nil {= getCheckedEntry().Entry =}.after =return}
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |