log

package
v0.0.0-...-5ec3a36 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2018 License: Apache-2.0, UPL-1.0 Imports: 7 Imported by: 4

README

wercker/pkg/log

The package contains several

Usage

...

Guidelines

The following are the guidelines that Wercker uses when it comes to logging. This should be read by Wercker employees, and can be used during code reviews.

Only use github.com/wercker/pkg/log

Always use github.com/wercker/pkg/log when writing logs. Do not use github.com/sirupsen/logrus, log or fmt.Print* for logs.

Use log.FromContext

When a context.Context is available always use log.FromContext to get a log instance. The logger retrieved from this func will include all the fields defined on the global logger, and any fields defined in the context.

Best practice: always instantiate a logger as the first line of a context aware function, then use this logger throughout this function. Example:

func (s *SomeService) GetByID(ctx context.Context, id string) (*SomeStruct, error) {
  logger := log.FromContext(ctx)
  
  logger.Info("SomeService.GetByID was called")

  // ...
}
Log messages should be a human-readable sentence

The message that is logged as part of the log event (ie. log.Info("<message>")) should be a normal sentence meant for humans. It should start with a capitalized letter, but should not end with a .. Any dynamic properties should be favoured to use fields, as these allow for easier filtering.

Avoid:

logger := log.FromContext(ctx)
logger.Infof("SomeService.GetByID was called; runID: %s, applicationID: %s, userID: %s.", rundID, applicationID, userID)

Instead:

logger := log.FromContext(ctx)
logger.WithFields(log.Fields{"runID": rundID, "applicationID": applicationID, "userID": userID}).Infof("SomeService.GetByID  was called")
When returning errors, do not capitalize the first letter

The error message should not capitalize its first letter as it might be wrapped in another error. In the situtation the error message will be delimited by a colon, so it will look weird when it contains a capitalized first letter.

Never:

return errors.New("Something failed")

Instead:

return errors.New("something failed")
Use errors.Wrap when returning errors

When checking for a error, try to wrap the error with errors.Wrap to add more context to the error before returning it. See https://godoc.org/github.com/pkg/errors

import "github.com/pkg/errors"

func (s *SomeService) SomeFunc(ctx context.Context, args string) error {
  logger := log.FromContext(ctx)

  result1, err := s.service1.get(id)
  if err != nil {
    return errors.Wrap(err, "something bad happened in service1")
  }

  result2, err := s.service2.Something(args)
  if err != nil {
    return errors.Wrap(err, "something bad happened in service2")
  }

  // ...
}
Always use log.WithError

When logging an error, always add the error object as a field using log.WithError.

Never:

func main() {
  err := someFunc()
  if err != nil {
    log.Errorf("Unable to execute someFunc: %s", err)
    os.Exit(1)
  }

  // ...
}

Instead:

func main() {
  err := someFunc()
  if err != nil {
    log.WithError(err).Error("Unable to execute someFunc")
    os.Exit(1)
  }

  // ...
}

Fields

Field keys should follow camel casing rules

The keys of the fields should always follow the lower camel casing rules, and they should only contain letters and numbers. Words in names that are initialisms or acronyms (e.g. "URL" or "NATO") should have a consistent case though.

Never:

log.WithField("some_field", "")

log.WithField("UserId", "")

Instead:

log.WithField("someField", "")

log.WithField("userID", "")
Field keys can be namespaced

Field keys can optionally be namespaced by dots. The segements should still follow the previous rule. Try to apply namespaced fields when there are multiple fields that have the same prefix, unless it diverges from consistent fields names in other services.

log.WithField("keen.projectID")
Add request specific data to the context

When a context.Context is available and there are some request specific fields, add them using log.AddFieldToCtx. This allows fields to be logged in unrelated services. Use this for fields that are relevant for a request.

Example (where TraceMiddleware will be called before MongoStore)

func (s *TraceMiddleware) Middleware(ctx context.Context) {
  ctx, logger := AddFieldToCtx("traceID", generateTraceID())
  // ...
}

func (s *MongoStore) Func(ctx context.Context) {
  logger := log.FromContext(ctx)
  // logger now contains the traceID field
}
Use consistent names for field keys

Use consistent field keys for the same data that other services are using.

NOTE(bvdberg): how do we keep track and decide which field keys to use?

Avoid:

log.WithField("runIdentifier", "")

log.WithField("run.id", "")

Better:

log.WithField("runID", "")

Levels

Error

Use Error when something failed and the operation was not able to continue.

Warn

Use Warn when something happened that was not expected, but the operation was able to finish.

Info

Use Info for normal messages.

Debug

Use Debug for verbose message, it is possible that these will not be displayed.

Dates

Note, logging a time.Time struct directly as a field will not comply with the Wercker guidelines.

Always use the UTC timezone

Convert a time.Time to the UTC timezone before adding it to a field.

Never:

log.WithField("createdAt", time.Now().Format(time.RFC3339))

Instead:

log.WithField("createdAt", time.Now().UTC().Format(time.RFC3339))
Always use the time.RFC3339 format

When logging a time.Time as a field, always format it to the RFC3339 format.

Never:

log.WithField("createdAt", time.Now().UTC())

Instead:

log.WithField("createdAt", time.Now().UTC().Format(time.RFC3339))

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddFields

func AddFields(fields Fields)

AddFields adds some fields globally to the standard entry

func AddHook

func AddHook(hook Hook)

AddHook adds a hook to the standard logger hooks.

func ContextWithFields

func ContextWithFields(ctx context.Context, fields Fields) context.Context

ContextWithFields set fields in a new context based on ctx, and returns this context. Any Fields defined in ctx will be overriden.

func Debug

func Debug(args ...interface{})

Debug logs a message at level Debug on the standard entry.

func Debugf

func Debugf(format string, args ...interface{})

Debugf logs a message at level Debug on the standard entry.

func Debugln

func Debugln(args ...interface{})

Debugln logs a message at level Debug on the standard entry.

func Error

func Error(args ...interface{})

Error logs a message at level Error on the standard entry.

func Errorf

func Errorf(format string, args ...interface{})

Errorf logs a message at level Error on the standard entry.

func Errorln

func Errorln(args ...interface{})

Errorln logs a message at level Error on the standard entry.

func Fatal

func Fatal(args ...interface{})

Fatal logs a message at level Fatal on the standard entry.

func Fatalf

func Fatalf(format string, args ...interface{})

Fatalf logs a message at level Fatal on the standard entry.

func Fatalln

func Fatalln(args ...interface{})

Fatalln logs a message at level Fatal on the standard entry.

func Info

func Info(args ...interface{})

Info logs a message at level Info on the standard entry.

func Infof

func Infof(format string, args ...interface{})

Infof logs a message at level Info on the standard entry.

func Infoln

func Infoln(args ...interface{})

Infoln logs a message at level Info on the standard entry.

func Panic

func Panic(args ...interface{})

Panic logs a message at level Panic on the standard entry.

func Panicf

func Panicf(format string, args ...interface{})

Panicf logs a message at level Panic on the standard entry.

func Panicln

func Panicln(args ...interface{})

Panicln logs a message at level Panic on the standard entry.

func Print

func Print(args ...interface{})

Print logs a message at level Info on the standard entry.

func Printf

func Printf(format string, args ...interface{})

Printf logs a message at level Info on the standard entry.

func Println

func Println(args ...interface{})

Println logs a message at level Info on the standard entry.

func SetFormatter

func SetFormatter(formatter Formatter)

SetFormatter sets the standard logger formatter.

func SetLevel

func SetLevel(level Level)

SetLevel sets the standard logger level.

func SetOutput

func SetOutput(out io.Writer)

SetOutput sets the standard logger output.

func SetupLogging

func SetupLogging(c *cli.Context) error

func Warn

func Warn(args ...interface{})

Warn logs a message at level Warn on the standard entry.

func Warnf

func Warnf(format string, args ...interface{})

Warnf logs a message at level Warn on the standard entry.

func Warning

func Warning(args ...interface{})

Warning logs a message at level Warn on the standard entry.

func Warningf

func Warningf(format string, args ...interface{})

Warningf logs a message at level Warn on the standard entry.

func Warningln

func Warningln(args ...interface{})

Warningln logs a message at level Warn on the standard entry.

func Warnln

func Warnln(args ...interface{})

Warnln logs a message at level Warn on the standard entry.

Types

type Entry

type Entry struct {
	*logrus.Entry
}

Entry is the final or intermediate Logrus logging entry.

func AddFieldToCtx

func AddFieldToCtx(ctx context.Context, key string, value interface{}) (context.Context, *Entry)

AddFieldToCtx adds a new field to fields in the ctx (creates a new one if there is none). It returns the new context and a entry will the current Fields objects.

func AddFieldsToCtx

func AddFieldsToCtx(ctx context.Context, newFields Fields) (context.Context, *Entry)

AddFieldsToCtx adds newFields to fields in the ctx (creates a new one if there is none). It returns the new context and a entry will the current Fields objects.

func FromContext

func FromContext(ctx context.Context) *Entry

FromContext will create a new Entry based on the Global entry with any custom fields defined in ctx.

func WithError

func WithError(err error) *Entry

WithError creates an entry from the standard entry and adds an error to it, using the value defined in ErrorKey as key.

func WithField

func WithField(key string, value interface{}) *Entry

WithField creates an entry from the standard entry and adds a field to it. If you want multiple fields, use `WithFields`.

Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal or Panic on the Entry it returns.

func WithFields

func WithFields(fields Fields) *Entry

WithFields creates an entry from the standard entry and adds multiple fields to it. This is simply a helper for `WithField`, invoking it once for each field.

Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal or Panic on the Entry it returns.

func (*Entry) WithField

func (e *Entry) WithField(key string, value interface{}) *Entry

WithField wraps logrus

func (*Entry) WithFields

func (e *Entry) WithFields(fields Fields) *Entry

WithFields wraps logrus

type Fields

type Fields logrus.Fields

Fields type, used to pass to `WithFields`

func FieldsFromContext

func FieldsFromContext(ctx context.Context) (Fields, bool)

FieldsFromContext retrieves the Fields from ctx.

type Formatter

type Formatter logrus.Formatter

Formatter interface is used to implement a custom Formatter

type Hook

type Hook logrus.Hook

Hook to be fired when logging on the logging levels returned from `Levels()` on your implementation of the interface.

type Level

type Level logrus.Level

Level type

const (
	// PanicLevel level, highest level of severity. Logs and then calls panic with the
	// message passed to Debug, Info, ...
	PanicLevel Level = iota
	// FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the
	// logging level is set to Panic.
	FatalLevel
	// ErrorLevel level. Logs. Used for errors that should definitely be noted.
	// Commonly used for hooks to send errors to an error tracking service.
	ErrorLevel
	// WarnLevel level. Non-critical entries that deserve eyes.
	WarnLevel
	// InfoLevel level. General operational entries about what's going on inside the
	// application.
	InfoLevel
	// DebugLevel level. Usually only enabled when debugging. Very verbose logging.
	DebugLevel
)

These are the different logging levels. You can set the logging level to log on your instance of logger, obtained with `logrus.New()`.

func GetLevel

func GetLevel() Level

GetLevel returns the standard logger level.

Jump to

Keyboard shortcuts

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