core.go raw

   1  // Copyright (c) 2016 Uber Technologies, Inc.
   2  //
   3  // Permission is hereby granted, free of charge, to any person obtaining a copy
   4  // of this software and associated documentation files (the "Software"), to deal
   5  // in the Software without restriction, including without limitation the rights
   6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   7  // copies of the Software, and to permit persons to whom the Software is
   8  // furnished to do so, subject to the following conditions:
   9  //
  10  // The above copyright notice and this permission notice shall be included in
  11  // all copies or substantial portions of the Software.
  12  //
  13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19  // THE SOFTWARE.
  20  
  21  package zapcore
  22  
  23  // Core is a minimal, fast logger interface. It's designed for library authors
  24  // to wrap in a more user-friendly API.
  25  type Core interface {
  26  	LevelEnabler
  27  
  28  	// With adds structured context to the Core.
  29  	With([]Field) Core
  30  	// Check determines whether the supplied Entry should be logged (using the
  31  	// embedded LevelEnabler and possibly some extra logic). If the entry
  32  	// should be logged, the Core adds itself to the CheckedEntry and returns
  33  	// the result.
  34  	//
  35  	// Callers must use Check before calling Write.
  36  	Check(Entry, *CheckedEntry) *CheckedEntry
  37  	// Write serializes the Entry and any Fields supplied at the log site and
  38  	// writes them to their destination.
  39  	//
  40  	// If called, Write should always log the Entry and Fields; it should not
  41  	// replicate the logic of Check.
  42  	Write(Entry, []Field) error
  43  	// Sync flushes buffered logs (if any).
  44  	Sync() error
  45  }
  46  
  47  type nopCore struct{}
  48  
  49  // NewNopCore returns a no-op Core.
  50  func NewNopCore() Core                                        { return nopCore{} }
  51  func (nopCore) Enabled(Level) bool                            { return false }
  52  func (n nopCore) With([]Field) Core                           { return n }
  53  func (nopCore) Check(_ Entry, ce *CheckedEntry) *CheckedEntry { return ce }
  54  func (nopCore) Write(Entry, []Field) error                    { return nil }
  55  func (nopCore) Sync() error                                   { return nil }
  56  
  57  // NewCore creates a Core that writes logs to a WriteSyncer.
  58  func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core {
  59  	return &ioCore{
  60  		LevelEnabler: enab,
  61  		enc:          enc,
  62  		out:          ws,
  63  	}
  64  }
  65  
  66  type ioCore struct {
  67  	LevelEnabler
  68  	enc Encoder
  69  	out WriteSyncer
  70  }
  71  
  72  var (
  73  	_ Core           = (*ioCore)(nil)
  74  	_ leveledEnabler = (*ioCore)(nil)
  75  )
  76  
  77  func (c *ioCore) Level() Level {
  78  	return LevelOf(c.LevelEnabler)
  79  }
  80  
  81  func (c *ioCore) With(fields []Field) Core {
  82  	clone := c.clone()
  83  	addFields(clone.enc, fields)
  84  	return clone
  85  }
  86  
  87  func (c *ioCore) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
  88  	if c.Enabled(ent.Level) {
  89  		return ce.AddCore(ent, c)
  90  	}
  91  	return ce
  92  }
  93  
  94  func (c *ioCore) Write(ent Entry, fields []Field) error {
  95  	buf, err := c.enc.EncodeEntry(ent, fields)
  96  	if err != nil {
  97  		return err
  98  	}
  99  	_, err = c.out.Write(buf.Bytes())
 100  	buf.Free()
 101  	if err != nil {
 102  		return err
 103  	}
 104  	if ent.Level > ErrorLevel {
 105  		// Since we may be crashing the program, sync the output.
 106  		// Ignore Sync errors, pending a clean solution to issue #370.
 107  		_ = c.Sync()
 108  	}
 109  	return nil
 110  }
 111  
 112  func (c *ioCore) Sync() error {
 113  	return c.out.Sync()
 114  }
 115  
 116  func (c *ioCore) clone() *ioCore {
 117  	return &ioCore{
 118  		LevelEnabler: c.LevelEnabler,
 119  		enc:          c.enc.Clone(),
 120  		out:          c.out,
 121  	}
 122  }
 123