cue

package module
v0.0.0-...-852726b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2016 License: MIT Imports: 10 Imported by: 5

README

Build Status Coverage Report Card GoDoc

Cue

Overview

Cue implements contextual logging with "batteries included". It has thorough test coverage and supports logging to stdout/stderr, file, syslog, and network sockets, as well as hosted third-party logging and error/reporting services such as Honeybadger, Loggly, Opbeat, Rollbar, and Sentry.

API Promise

Minor breaking changes may occur prior to the 1.0 release. After the 1.0 release, the API is guaranteed to remain backwards compatible.

Cue makes use of sync/atomic.Value and thus requires Go 1.4.x or later.

Key Features

  • Simple API. You only need to know cue.NewLogger and the cue.Logger interface to get started. The rest of the API is centered around log output configuration.
  • Supports both fully synchronous and fully asynchronous (guaranteed non-blocking) log collection.
  • Supports a variety of log outputs:
  • Very flexible formatting
  • Designed to stay out of your way. Log collection is explicitly opt-in, meaning cue is safe to use within libraries. If the end user doesn't configure log collection, logging calls are silently dropped.
  • Designed with performance in mind. Cue uses atomic operations to avoid lock contention and reuses formatting buffers to avoid excessive memory allocation and garbage collection. Logging calls that don't match a registered Collector threshold (e.g. DEBUG in production) are quickly pruned via atomic operations. On a 2015 MacBook pro, these calls take ~16ns/call, meaning tens of millions of no-op calls may be serviced per second.
  • Gracefully handles and recovers from failures.
  • Has thorough test coverage:

Basic Use

Please see the godocs for additional information.

This example logs to both the terminal (stdout) and to file. If the program receives SIGHUP, the file will be reopened. This is useful for log rotation. Additional context is added via the .WithValue and .WithFields Logger methods.

The formatting may be changed by passing a different formatter to either collector. See the cue/format godocs for details. The context data may also be formatted as JSON for machine parsing if desired. See cue/format.JSONMessage and cue/format.JSONContext.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/collector"
	"os"
	"syscall"
)

var log = cue.NewLogger("main")

func main() {
	cue.Collect(cue.INFO, collector.Terminal{}.New())
	cue.Collect(cue.INFO, collector.File{
		Path:         "app.log",
		ReopenSignal: syscall.SIGHUP,
	}.New())

	log := cue.NewLogger("example")
	log.Debug("Debug message -- a quick no-op since our collector is registered at INFO level")
	log.Info("Info message")
	log.Warn("Warn message")

	// Add additional context
	log.WithValue("items", 2).Infof("This is an %s", "example")
	log.WithFields(cue.Fields{
		"user":          "bob",
		"authenticated": true,
	}).Warn("Doing something important")

	host, err := os.Hostname()
	if err != nil {
		log.Error(err, "Failed to retrieve hostname")
	} else {
		log.Infof("My hostname is %s", host)
	}

	// The output looks something like:
	// Mar 13 12:40:10 INFO example_basic_test.go:25 Info message
	// Mar 13 12:40:10 WARN example_basic_test.go:26 Warn message
	// Mar 13 12:40:10 INFO example_basic_test.go:29 This is an example items=2
	// Mar 13 12:40:10 WARN example_basic_test.go:33 Doing something important user=bob authenticated=true
	// Mar 13 12:40:10 INFO example_basic_test.go:39 My hostname is pegasus.bobbyz.org
}

Error Reporting

Please see the godocs for additional information.

This example uses cue/hosted.Honeybadger to report error events to Honeybadger.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/hosted"
	"os"
	"time"
)

var log = cue.NewLogger("main")

func main() {
	// Here we're assuming the Honeybadger API key is stored via environment
	// variable, as well as an APP_ENV variable specifying "test", "production", etc.
	cue.CollectAsync(cue.ERROR, 10000, hosted.Honeybadger{
		Key:         os.Getenv("HONEYBADGER_KEY"),
		Environment: os.Getenv("APP_ENV"),
	}.New())

	// We want to collect more stack frames for error and panic events so that
	// our Honeybadger incidents show us enough stack trace to troubleshoot.
	cue.SetFrames(1, 32)

	// We use Close to flush the asynchronous buffer.  This way we won't
	// lose error reports if one is in the process of sending when the program
	// is terminating.
	defer cue.Close(5 * time.Second)

	// If something panics, it will automatically open a Honeybadger event
	// when recovered by this line
	defer log.Recover("Recovered panic")

	// Force a panic
	PanickingFunc()
}

func PanickingFunc() {
	panic("This will be reported to Honeybadger")
}

Features

Please see the godocs for additional information.

This example shows quite a few of the cue features: logging to a file that reopens on SIGHUP (for log rotation), logging colored output to stdout, logging to syslog with JSON context formatting, and reporting errors to Honeybadger.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/collector"
	"github.com/bobziuchkovski/cue/format"
	"github.com/bobziuchkovski/cue/hosted"
	"os"
	"syscall"
	"time"
)

var log = cue.NewLogger("main")

func main() {
	// defer cue.Close before log.Recover so that Close flushes any events
	// triggers by panic recovery
	defer cue.Close(5 * time.Second)
	defer log.Recover("Recovered panic in main")
	ConfigureLogging()
	RunTheProgram()
}

func ConfigureLogging() {
	// Collect logs to stdout in color!  :)
	cue.Collect(cue.DEBUG, collector.Terminal{
		Formatter: format.HumanReadableColors,
	}.New())

	// Collect to app.log and reopen the handle if we receive SIGHUP
	cue.Collect(cue.INFO, collector.File{
		Path:         "app.log",
		ReopenSignal: syscall.SIGHUP,
	}.New())

	// Collect to syslog, formatting the context data as JSON for indexing.
	cue.Collect(cue.WARN, collector.Syslog{
		App:       "app",
		Facility:  collector.LOCAL7,
		Formatter: format.JSONMessage,
	}.New())

	// Report errors asynchronously to Honeybadger.  If HONEYBADGER_KEY is
	// unset, Honeybadger.New will return nil and cue.CollectAsync will
	// ignore it.  This works great for development.
	cue.CollectAsync(cue.ERROR, 10000, hosted.Honeybadger{
		Key:         os.Getenv("HONEYBADGER_KEY"),
		Environment: os.Getenv("APP_ENV"),
	}.New())
	cue.SetFrames(1, 32)
}

func RunTheProgram() {
	log.Info("Running the program!")
	log.WithFields(cue.Fields{
		"sad":    true,
		"length": 0,
	}).Panic("No program", "Whoops, there's no program to run!")
}

Motivation

There are quite a few Go logging libraries that already exist. Why create a new one?

I didn't start with the intention of creating a new library, but I struggled to find an existing logging library that met my primary objectives:

  1. Built-in support for error reporting services. Error reporting services are incredibly valuable for production applications. They provide immediate notification and visibility into bugs that your end users are encountering. However, there's nothing particularly special about how error reporting services work. They are merely a form of error logging. I feel it's important to be able to log/collect application errors without needing to explicitly specify where to send them. Calling log.Error/log.Recover should be enough to trigger the error report. Where that error is sent should be a configuration detail and shouldn't require additional service-specific API calls.
  2. Contextual logging support. It's often valuable to know under what conditions application events trigger: the account that accessed a page, flags associated with the account, country of origin, etc. Cue simplifies collection of these details via the Logger.WithFields and Logger.WithValues methods, and provides flexible formatting options for rendering these values, including machine-parseable formats for search and indexing. Furthermore, I have every intention of providing a bridge API to integrate contextual logging with the upstream "context" package depending on what happens with this proposal.
  3. Asynchronous logging with guaranteed non-blocking behavior. When logging to third-party services, you don't want a service disruption to halt your entire application. Unfortunately, many existing logging libraries obtain a global lock for logging calls and log synchronously. This is low risk when logging to stdout, but high risk when logging to external services. If those external services go down, your entire application may halt trying to acquire a logging mutex that's blocked trying to write to the downed service.
  4. Low overhead. Developers should feel comfortable peppering their code with logging calls wherever there's value in collecting the data. They shouldn't need to worry about the overhead of those logging calls or bottlenecking on logging. To that point, cue is carefully designed to avoid lock contention and to avoid excessive object allocation. Cue uses atomic operations to quickly prune logging calls that don't match registered collector thresholds (e.g. DEBUG logs in production). Cue also reuses formatting buffers via a sync.Pool to reduce object allocations and garbage collection overhead. Logging calls aren't free, but cue makes them as cheap as possible.
  5. Has thorough test coverage. If you're peppering your code with calls to a logging API, you should feel comfortable that the API is well-tested and stable. Many existing logging libraries have weak test coverage and lack API promises.
  6. Friendly to library authors. Many of the existing logging libraries write log output to stdout/stderr or to file by default. This makes life difficult on library authors because you're left either interfering with your end user's logging configuration (explicitly changing logging library defaults), or omitting logging altogether. Cue addresses this by requiring explicit opt-in by the end user in order to collect logging output. Uncollected logging calls are no-ops.

Documentation

Please see the godocs for additional details.

Authors

Bob Ziuchkovski (@bobziuchkovski)

License (MIT)

Copyright (c) 2016 Bob Ziuchkovski

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.

Documentation

Overview

Package cue implements contextual logging with "batteries included". It has thorough test coverage and supports logging to stdout/stderr, file, syslog, and network sockets, as well as hosted third-party logging and error/reporting services such as Honeybadger, Loggly, Opbeat, Rollbar, and Sentry.

Cue uses atomic operations to compare logging calls to registered collector thresholds. This ensures no-op calls are performed quickly and without lock contention. On a 2015 MacBook Pro, no-op calls take about 16ns/call, meaning tens of millions of calls may be dispatched per second. Uncollected log calls are very cheap.

Furthermore, collector thresholds may be altered dynamically at run-time, on a per-collector basis. If debugging logs are needed to troubleshoot a live issue, collector thresholds may be set to the DEBUG level for a short period of time and then restored to their original levels shortly thereafter. See the SetLevel function for details.

Basics

Logging instances are created via the NewLogger function. A simple convention is to initialize an unexported package logger:

var log = cue.NewLogger("some/package/name")

Additional context information may be added to the package logger via the log.WithValue and log.WithFields methods:

func DoSomething(user string) {
	log.WithValue("user", user).Info("Doing something")
}

func DoSomethingElse(user string, authorized bool) {
	log.WithFields(cue.Fields{
		"user": user,
		"authorized": authorized,
	}).Info("Something else requested")
}

Depending on the collector and log format, output would look something like:

<DATE> INFO Something else requested user=<user> authorized=<authorized>

Error Logging and Recovery

Cue simplifies error reporting by logging the given error and message, and then returning the same error value. Hence you can return the log.Error/log.Errorf values in-line:

filename := "somefile"
f, err := os.Create(filename)
if err != nil {
	return log.Errorf(err, "Failed to create %q", filename)
}

Cue provides Collector implementations for popular error reporting services such as Honeybadger, Rollbar, Sentry, and Opbeat. If one of these collector implementations were registered, the above code would automatically open a new error report, complete with stack trace and context information from the logger instance. See the cue/hosted package for details.

Finally, cue provides convenience methods for panic and recovery. Calling Panic or Panicf will log the provided message at the FATAL level and then panic. Calling Recover recovers from panics and logs the recovered value and message at the FATAL level.

func doSomething() {
	defer log.Recover("Recovered panic in doSomething")
	doSomethingThatPanics()
}

If a panic is triggered via a cue logger instance's Panic or Panicf methods, Recover recovers from the panic but only emits the single event from the Panic/Panicf method.

Event Collection

Cue decouples event generation from event collection. Library and framework authors may generate log events without concern for the details of collection. Event collection is opt-in -- no collectors are registered by default.

Event collection, if enabled, should be configured close to a program's main package/function, not by libraries. This gives the event subscriber complete control over the behavior of event collection.

Collectors are registered via the Collect and CollectAsync functions. Each collector is registered for a given level threshold. The threshold for a collector may be updated at any time using the SetLevel function.

Collect registers fully synchronous event collectors. Logging calls that match a synchronous collector's threshold block until the collector's Collect method returns successfully. This is dangerous if the Collector performs any operations that block or return errors. However, it's simple to use and understand:

func main() {
	// Follow a 12-factor approach and log unbuffered to stdout.
	// See http://12factor.net for details.
	cue.Collect(cue.INFO, collector.Terminal{}.New())
	defer log.Recover("Recovered from panic in main")

	RunTheProgram()
}

CollectAsync registers asynchronous collectors. It creates a buffered channel for the collector and starts a worker goroutine to service events. Logging calls return after queuing events to the collector channel. If the channel's buffer is full, the event is dropped and a drop counter is incremented atomically. This ensures asynchronous logging calls never block. The worker goroutine detects changes in the atomic drop counter and surfaces drop events as collector errors. See the cue/collector docs for details on collector error handling.

When asynchronous logging is enabled, Close must be called to flush queued events on program termination. Close is safe to call even if asynchronous logging isn't enabled -- it returns immediately if no events are queued. Note that ctrl+c and kill <pid> terminate Go programs without triggering cleanup code. When using asynchronous logging, it's a good idea to register signal handlers to capture SIGINT (ctrl+c) and SIGTERM (kill <pid>). See the os/signals package docs for details.

func main() {
	// Use async logging to local syslog
	cue.CollectAsync(cue.INFO, 10000, collector.Syslog{
		App: "theapp",
		Facility: collector.LOCAL0,
	}.New())

	// Close/flush buffered events on program termination.
	// Note that this won't fire if ctrl+c is used or kill <pid>.  You need
	// to install signal handlers for SIGINT/SIGTERM to handle those cases.
	defer cue.Close(5 * time.Second)

	defer log.Recover("Recovered from panic in main")
	RunTheProgram()
}

Stack Frame Collection

By default, cue collects a single stack frame for any event that matches a registered collector. This ensures collectors may log the file name, package, and line number for any collected event. SetFrames may be used to alter this frame count, or disable frame collection entirely. See the SetFrames function for details.

When using error reporting services, SetFrames should be used to increase the errorFrames parameter from the default value of 1 to a value that provides enough stack context to successfully diagnose reported errors.

Example (Basic)

This example logs to both the terminal (stdout) and to file. If the program receives SIGHUP, the file will be reopened (for log rotation). Additional context is added via the .WithValue and .WithFields Logger methods.

The formatting may be changed by passing a different formatter to either collector. See the cue/format godocs for details. The context data may also be formatted as JSON for machine parsing if desired. See cue/format.JSONMessage and cue/format.JSONContext.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/collector"
	"os"
	"syscall"
)

func main() {
	cue.Collect(cue.INFO, collector.Terminal{}.New())
	cue.Collect(cue.INFO, collector.File{
		Path:         "app.log",
		ReopenSignal: syscall.SIGHUP,
	}.New())

	log := cue.NewLogger("example")
	log.Debug("Debug message -- a quick no-op since our collector is registered at INFO level")
	log.Info("Info message")
	log.Warn("Warn message")

	// Add additional context
	log.WithValue("items", 2).Infof("This is an %s", "example")
	log.WithFields(cue.Fields{
		"user":          "bob",
		"authenticated": true,
	}).Warn("Doing something important")

	host, err := os.Hostname()
	if err != nil {
		log.Error(err, "Failed to retrieve hostname")
	} else {
		log.Infof("My hostname is %s", host)
	}

	// The output looks something like:
	// Mar 13 12:40:10 INFO example_basic_test.go:25 Info message
	// Mar 13 12:40:10 WARN example_basic_test.go:26 Warn message
	// Mar 13 12:40:10 INFO example_basic_test.go:29 This is an example items=2
	// Mar 13 12:40:10 WARN example_basic_test.go:33 Doing something important user=bob authenticated=true
	// Mar 13 12:40:10 INFO example_basic_test.go:39 My hostname is pegasus.bobbyz.org

	// The formatting could be changed by passing a different formatter to collector.Terminal.
	// see the cue/format docs for details
}
Output:

Example (ErrorReporting)

This example shows how to use error reporting services.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/hosted"
	"os"
	"time"
)

// This example shows how to use error reporting services.
func main() {
	// Here we're assuming the Honeybadger API key is stored via environment
	// variable, as well as an APP_ENV variable specifying "test", "production", etc.
	cue.CollectAsync(cue.ERROR, 10000, hosted.Honeybadger{
		Key:         os.Getenv("HONEYBADGER_KEY"),
		Environment: os.Getenv("APP_ENV"),
	}.New())

	// We want to collect more stack frames for error and panic events so that
	// our Honeybadger incidents show us enough stack trace to troubleshoot.
	cue.SetFrames(1, 32)

	// We use Close to flush the asynchronous buffer.  This way we won't
	// lose error reports if one is in the process of sending when the program
	// is terminating.
	defer cue.Close(5 * time.Second)

	// If something panics, it will automatically open a Honeybadger event
	// when recovered by this line
	log := cue.NewLogger("example")
	defer log.Recover("Recovered panic")

	// Force a panic
	PanickingFunc()
}

func PanickingFunc() {
	panic("This will be reported to Honeybadger")
}
Output:

Example (Features)

This example shows quite a few of the cue features: logging to a file that reopens on SIGHUP (for log rotation), logging colored output to stdout, logging to syslog, and reporting errors to Honeybadger.

package main

import (
	"github.com/bobziuchkovski/cue"
	"github.com/bobziuchkovski/cue/collector"
	"github.com/bobziuchkovski/cue/format"
	"github.com/bobziuchkovski/cue/hosted"
	"os"
	"syscall"
	"time"
)

var log = cue.NewLogger("example")

// This example shows quite a few of the cue features: logging to a file that
// reopens on SIGHUP (for log rotation), logging colored output to stdout,
// logging to syslog, and reporting errors to Honeybadger.
func main() {
	// defer cue.Close before log.Recover so that Close flushes any events
	// triggers by panic recovery
	defer cue.Close(5 * time.Second)
	defer log.Recover("Recovered panic in main")
	ConfigureLogging()
	RunTheProgram()
}

func ConfigureLogging() {
	// Collect logs to stdout in color!  :)
	cue.Collect(cue.DEBUG, collector.Terminal{
		Formatter: format.HumanReadableColors,
	}.New())

	// Collect to app.log and reopen the handle if we receive SIGHUP
	cue.Collect(cue.INFO, collector.File{
		Path:         "app.log",
		ReopenSignal: syscall.SIGHUP,
	}.New())

	// Collect to syslog, formatting the context data as JSON for indexing.
	cue.Collect(cue.WARN, collector.Syslog{
		App:       "app",
		Facility:  collector.LOCAL7,
		Formatter: format.JSONMessage,
	}.New())

	// Report errors asynchronously to Honeybadger.  If HONEYBADGER_KEY is
	// unset, Honeybadger.New will return nil and cue.CollectAsync will
	// ignore it.  This works great for development.
	cue.CollectAsync(cue.ERROR, 10000, hosted.Honeybadger{
		Key:         os.Getenv("HONEYBADGER_KEY"),
		Environment: os.Getenv("APP_ENV"),
	}.New())
	cue.SetFrames(1, 32)
}

func RunTheProgram() {
	log.Info("Running the program!")
	log.WithFields(cue.Fields{
		"sad":    true,
		"length": 0,
	}).Panic("No program", "Whoops, there's no program to run!")
}
Output:

Index

Examples

Constants

View Source
const (
	UnknownPackage  = "<unknown package>"
	UnknownFunction = "<unknown function>"
	UnknownFile     = "<unknown file>"
)

Frame fields use UnknownPackage, UnknownFunction, and UnknownFile when the package, function, or file cannot be determined for a stack frame.

Variables

View Source
var Version = struct {
	Major int
	Minor int
	Patch int
}{0, 8, 0}

Version records the cue package version.

Functions

func Close

func Close(timeout time.Duration) error

Close is used to terminate and flush asynchronous logging buffers. Close signals each worker to silently drop new events, flush existing buffered events, and then terminate worker goroutines. If all events flush within the given timeout, Close returns nil. Otherwise it returns an error. Close may be called regardless of asynchronous logging state. It returns immediately if no events are buffered and no workers need to be terminated.

Close may be called multiple times throughout program execution. If Close returns nil, cue is guaranteed to be reset to it's initial state. This is useful for testing.

func Collect

func Collect(threshold Level, c Collector)

Collect registers a Collector for the given threshold using synchronous event collection. Any event logged within the specified threshold will be sent to the provided collector. Thus a collector registered for the WARN level will receive WARN, ERROR, and FATAL events.

All events sent to the collector are fully synchronous and block until the collector's Collect method returns successfully. This is dangerous if the collector performs blocking operations or returns errors.

func CollectAsync

func CollectAsync(threshold Level, bufsize int, c Collector)

CollectAsync registers a Collector for the given threshold using asynchronous event collection. Any event logged within the specified threshold will be sent to the provided collector. Thus a collector registered for the WARN level will receive WARN, ERROR, and FATAL events.

CollectAsync registers asynchronous collectors. It creates a buffered channel for the collector and starts a worker goroutine to service events. Logging calls return after queuing events to the collector channel. If the channel's buffer is full, the event is dropped and a drop counter is incremented atomically. This ensures asynchronous logging calls never block. The worker goroutine detects changes in the atomic drop counter and surfaces drop events as collector errors. See the cue/collector docs for details on collector error handling.

When asynchronous logging is enabled, Close must be called to flush queued events on program termination. Close is safe to call even if asynchronous logging isn't enabled -- it returns immediately if no events are queued. Note that ctrl+c and kill <pid> terminate Go programs without triggering cleanup code. When using asynchronous logging, it's a good idea to register signal handlers to capture SIGINT (ctrl+c) and SIGTERM (kill <pid>). See the Signals example and os/signals package docs for details.

func SetFrames

func SetFrames(frames int, errorFrames int)

SetFrames specifies the number of stack frames to collect for log events. The frames parameter specifies the frame count to collect for DEBUG, INFO, and WARN events. The errorFrames parameter specifies the frame count to collect for ERROR and FATAL events. By default, a single frame is collected for events of any level that matches a subscribed collector's threshold. This ensures collectors may log the file name, package, function, and line number of the logging call site for any collected event. SetFrames may be used to alter this frame count, or disable frame collection entirely by specifying a 0 value for either parameter. SetFrames may be called any number of times during program execution to dynamically alter frame collection.

When using error reporting services, SetFrames should be called to increase the errorFrames parameter from the default value of 1 to a value that provides enough stack context to successfully diagnose reported errors.

func SetLevel

func SetLevel(threshold Level, c Collector)

SetLevel changes a registered collector's threshold level. The OFF value may be used to disable event collection entirely. SetLevel may be called any number of times during program execution to dynamically alter collector thresholds.

Types

type Collector

type Collector interface {
	Collect(event *Event) error
}

Collector is the interface representing event subscribers. Log events are only generated and dispatched if collectors are registered with corresponding threshold levels.

If a Collector implements the io.Closer interface, it's Close() method is called as part of termination.

type Context

type Context interface {
	// Name returns the name of the context.
	Name() string

	// NumValues returns the number of key/value pairs in the Context.
	// The counting behavior for duplicate keys is currently undefined.
	NumValues() int

	// Each executes function fn on each of the Context's key/value pairs.
	// Iteration order is currently undefined.
	Each(fn func(key string, value interface{}))

	// Fields returns a map representation of the Context's key/value pairs.
	// Duplicate key handling is currently undefined.
	Fields() Fields

	// WithFields returns a new Context that adds the key/value pairs from
	// fields to the existing key/value pairs.
	WithFields(fields Fields) Context

	// WithValue returns a new Context that adds key and value to the existing
	// key/value pairs.
	WithValue(key string, value interface{}) Context
}

Context is an interface representing contextual key/value pairs. Any key/value pair may be added to a context with one exception: an empty string is not a valid key. Pointer values are dereferenced and their target is added. Values of basic types -- string, bool, integer, float, and complex -- are stored directly. Other types, including all slices and arrays, are coerced to a string representation via fmt.Sprint. This ensures stored context values are immutable. This is important for safe asynchronous operation.

Storing duplicate keys is allowed, but the resulting behavior is currently undefined.

func JoinContext

func JoinContext(name string, contexts ...Context) Context

JoinContext returns a new Context with the given name, containing all the key/value pairs joined from the provided contexts.

func NewContext

func NewContext(name string) Context

NewContext returns a new Context with the given name.

type Event

type Event struct {
	Time    time.Time // Local time when the event was generated
	Level   Level     // Event severity level
	Context Context   // Context of the logger that generated the event
	Frames  []*Frame  // Stack frames for the call site, or nil if disabled
	Error   error     // The error associated with the message (ERROR and FATAL levels only)
	Message string    // The log message
}

Event represents a log event. A single Event pointer is passed to all matching collectors across multiple goroutines. For this reason, Event fields -must not- be altered in place.

type Fields

type Fields map[string]interface{}

Fields is a map representation of contextual key/value pairs.

type Frame

type Frame struct {
	Package  string // Package name or cue.UnknownPackage ("<unknown package>") if unknown
	Function string // Function name or cue.UnknownFunction ("<unknown function>") if unknown
	File     string // Full file path or cue.UnknownFile ("<unknown file>") if unknown
	Line     int    // Line Number or 0 if unknown
}

Frame represents a single stack frame.

type Level

type Level uint

Level represents the severity level for a logged event. Events are only generated and collected if their severity level is within the threshold level for one or more registered Collectors. Calling Logger.Info, for example, will only generate an event if a Collector is registered at the INFO or DEBUG threshold levels.

const (
	OFF Level = iota
	FATAL
	ERROR
	WARN
	INFO
	DEBUG
)

OFF, FATAL, ERROR, WARN, INFO, and DEBUG are logging Level constants.

func (Level) String

func (l Level) String() string

String returns the level's name.

type Logger

type Logger interface {
	// WithFields returns a new logger instance with fields added to the current
	// logger's context.
	WithFields(fields Fields) Logger

	// WithValue returns a new logger instance with key and value added to the
	// current logger's context.
	WithValue(key string, value interface{}) Logger

	// Debug logs a message at the DEBUG level.
	Debug(message string)

	// Debugf logs a message at the DEBUG level using formatting rules from
	// the fmt package.
	Debugf(format string, values ...interface{})

	// Info logs a message at the INFO level.
	Info(message string)

	// Infof logs a message at the INFO level using formatting rules from
	// the fmt package.
	Infof(format string, values ...interface{})

	// Warn logs a message at the WARN level.
	Warn(message string)

	// Warnf logs a message at the WARN level using formatting rules from
	// the fmt package.
	Warnf(format string, values ...interface{})

	// Error logs the given error and message at the ERROR level and returns
	// the same error value. If err is nil, Error returns without emitting
	// a log event.
	Error(err error, message string) error

	// Errorf logs the given error at the ERROR level using formatting rules
	// from the fmt package and returns the same error value.  If err is nil,
	// Errorf returns without emitting a log event.
	Errorf(err error, format string, values ...interface{}) error

	// Panic logs the given cause and message at the FATAL level and then
	// calls panic(cause).  Panic does nothing is cause is nil.
	Panic(cause interface{}, message string)

	// Panicf logs the given cause at the FATAL level using formatting rules
	// from the fmt package and then calls panic(cause). Panicf does nothing if
	// cause is nil.
	Panicf(cause interface{}, format string, values ...interface{})

	// Recover recovers from panics and logs the recovered value and message
	// at the FATAL level.  Recover must be called via defer. If a logger's
	// Panic or Panicf method is used to trigger the panic, Recover returns
	// without emitting a new log event.  Recover does nothing if there's no
	// panic to recover.
	Recover(message string)

	// ReportRecovery logs the given cause and message at the FATAL level.
	// If used, it should be called from a deferred function after that
	// function has recovered from a panic.  In most cases, using the Recover
	// method directly is simpler.  However, sometimes it's necessary to test
	// whether a panic occurred or not.  In those cases, it's easier to use
	// the built-in recover() function and simply report the recovery via
	// ReportRecovery.  ReportRecovery does nothing if cause is nil.
	ReportRecovery(cause interface{}, message string)

	// Wrap returns a logging instance that skips one additional frame when
	// capturing frames for a call site.  Wrap should only be used when logging
	// calls are wrapped by an additional library function or method.
	Wrap() Logger
}

Logger is the interface for logging instances.

func NewLogger

func NewLogger(name string) Logger

NewLogger returns a new logger instance using name for the context.

Directories

Path Synopsis
Package collector implements event collection.
Package collector implements event collection.
Package format implements event formatting.
Package format implements event formatting.
Package hosted implements event collection for hosted third-party services.
Package hosted implements event collection for hosted third-party services.
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL