github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/thirdparty/eventlog/log.go (about)

     1  package eventlog
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
     8  	"github.com/ipfs/go-ipfs/util" // TODO remove IPFS dependency
     9  )
    10  
    11  // StandardLogger provides API compatibility with standard printf loggers
    12  // eg. go-logging
    13  type StandardLogger interface {
    14  	Debug(args ...interface{})
    15  	Debugf(format string, args ...interface{})
    16  	Error(args ...interface{})
    17  	Errorf(format string, args ...interface{})
    18  	Fatal(args ...interface{})
    19  	Fatalf(format string, args ...interface{})
    20  	Info(args ...interface{})
    21  	Infof(format string, args ...interface{})
    22  	Panic(args ...interface{})
    23  	Panicf(format string, args ...interface{})
    24  	Warning(args ...interface{})
    25  	Warningf(format string, args ...interface{})
    26  }
    27  
    28  // EventLogger extends the StandardLogger interface to allow for log items
    29  // containing structured metadata
    30  type EventLogger interface {
    31  	StandardLogger
    32  
    33  	// Event merges structured data from the provided inputs into a single
    34  	// machine-readable log event.
    35  	//
    36  	// If the context contains metadata, a copy of this is used as the base
    37  	// metadata accumulator.
    38  	//
    39  	// If one or more loggable objects are provided, these are deep-merged into base blob.
    40  	//
    41  	// Next, the event name is added to the blob under the key "event". If
    42  	// the key "event" already exists, it will be over-written.
    43  	//
    44  	// Finally the timestamp and package name are added to the accumulator and
    45  	// the metadata is logged.
    46  	Event(ctx context.Context, event string, m ...Loggable)
    47  
    48  	EventBegin(ctx context.Context, event string, m ...Loggable) *EventInProgress
    49  }
    50  
    51  // Logger retrieves an event logger by name
    52  func Logger(system string) EventLogger {
    53  
    54  	// TODO if we would like to adjust log levels at run-time. Store this event
    55  	// logger in a map (just like the util.Logger impl)
    56  	return &eventLogger{system: system, StandardLogger: util.Logger(system)}
    57  }
    58  
    59  // eventLogger implements the EventLogger and wraps a go-logging Logger
    60  type eventLogger struct {
    61  	StandardLogger
    62  
    63  	system string
    64  	// TODO add log-level
    65  }
    66  
    67  func (el *eventLogger) EventBegin(ctx context.Context, event string, metadata ...Loggable) *EventInProgress {
    68  	start := time.Now()
    69  	el.Event(ctx, fmt.Sprintf("%sBegin", event), metadata...)
    70  
    71  	eip := &EventInProgress{}
    72  	eip.doneFunc = func(additional []Loggable) {
    73  
    74  		metadata = append(metadata, additional...)                      // anything added during the operation
    75  		metadata = append(metadata, LoggableMap(map[string]interface{}{ // finally, duration of event
    76  			"duration": time.Now().Sub(start),
    77  		}))
    78  
    79  		el.Event(ctx, event, metadata...)
    80  	}
    81  	return eip
    82  }
    83  
    84  func (el *eventLogger) Event(ctx context.Context, event string, metadata ...Loggable) {
    85  
    86  	// short circuit if theres nothing to write to
    87  	if !WriterGroup.Active() {
    88  		return
    89  	}
    90  
    91  	// Collect loggables for later logging
    92  	var loggables []Loggable
    93  
    94  	// get any existing metadata from the context
    95  	existing, err := MetadataFromContext(ctx)
    96  	if err != nil {
    97  		existing = Metadata{}
    98  	}
    99  	loggables = append(loggables, existing)
   100  
   101  	for _, datum := range metadata {
   102  		loggables = append(loggables, datum)
   103  	}
   104  
   105  	e := entry{
   106  		loggables: loggables,
   107  		system:    el.system,
   108  		event:     event,
   109  	}
   110  
   111  	e.Log() // TODO replace this when leveled-logs have been implemented
   112  }
   113  
   114  type EventInProgress struct {
   115  	loggables []Loggable
   116  	doneFunc  func([]Loggable)
   117  }
   118  
   119  // Append adds loggables to be included in the call to Done
   120  func (eip *EventInProgress) Append(l Loggable) {
   121  	eip.loggables = append(eip.loggables, l)
   122  }
   123  
   124  // SetError includes the provided error
   125  func (eip *EventInProgress) SetError(err error) {
   126  	eip.loggables = append(eip.loggables, LoggableMap{
   127  		"error": err.Error(),
   128  	})
   129  }
   130  
   131  // Done creates a new Event entry that includes the duration and appended
   132  // loggables.
   133  func (eip *EventInProgress) Done() {
   134  	eip.doneFunc(eip.loggables) // create final event with extra data
   135  }
   136  
   137  // Close is an alias for done
   138  func (eip *EventInProgress) Close() error {
   139  	eip.Done()
   140  	return nil
   141  }