ulog

package
v1.0.0-beta1 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2017 License: MIT Imports: 18 Imported by: 0

README

Logging package

package ulog provides an API wrapper around the logging library zap. package ulog uses the builder pattern to instantiate the logger. With LogBuilder you can perform pre-initialization setup by injecting configuration, custom logger, and log level prior to building the usable ulog.Log object.

ulog.Log interface provides a few benefits:

  • Decouple services from the logger used underneath the framework
  • Easy to use API for logging
  • Easily swappable backend logger without changing the service

Sample usage

package main

import "go.uber.org/fx/ulog"

func main() {
  // Configure logger with configuration preferred by your service
  logConfig := ulog.Configuration{}
  logBuilder := ulog.Builder().WithConfiguration(&logConfig)

  // Build ulog.Log from logBuilder
  log := lobBuilder.Build()

  // Use logger in your service
  log.Info("Message describing logging reason", "key", "value")
}

Context

It is very common that in addition to logging a string message, it is desirable to provide additional information: customer uuid, tracing id, etc.

For that very reason, the logging methods (Info,Warn, Debug, etc) take additional parameters as key value pairs.

Retaining Context

Sometimes the same context is used over and over in a logger. For example service name, shard id, module name, etc. For this very reason With() functionality exists which will return a new instance of the logger with that information baked in so it doesn't have to be provided for each logging call.

For example, the following piece of code:

package main

import "go.uber.org/fx/ulog"

func main() {
  log := ulog.Logger()
  log.Info("My info message")
  log.Info("Info with context", "customer_id", 1234)

  richLog := log.With("shard_id", 3, "levitation", true)
  richLog.Info("Rich info message")
  richLog.Info("Even richer", "more_info", []int{1, 2, 3})
}

Produces this output:

{"level":"info","ts":1479946972.102394,"msg":"My info message"}
{"level":"info","ts":1479946972.1024208,"msg":"Info with context","customer_id":1234}
{"level":"info","ts":1479946972.1024246,"msg":"Rich info message","shard_id":3,"levitation":true}
{"level":"info","ts":1479946972.1024623,"msg":"Even richer","shard_id":3,"levitation":true,"more_info":[1,2,3]}

Configuration

ulog configuration can be defined in multiple ways:

Writing the struct yourself
loggingConfig := ulog.Configuration{
  Stdout: true,
}
Configuration defined in YAML
logging:
  stdout: true
  level: debug
Benchmarks

Current performance benchmark data with ulog interface, ulog baseLogger struct, and zap.Logger

BenchmarkUlogWithoutFields-8                    10000000               223 ns/op               0 B/op          0 allocs/op
BenchmarkUlogWithFieldsLogIFace-8                1000000              1237 ns/op            1005 B/op         18 allocs/op
BenchmarkUlogWithFieldsBaseLoggerStruct-8        1000000              1096 ns/op             748 B/op         17 allocs/op
BenchmarkUlogWithFieldsZapLogger-8               2000000               664 ns/op             514 B/op          1 allocs/op
BenchmarkUlogLiteWithFields-8                    3000000               489 ns/op             249 B/op          6 allocs/op
BenchmarkUlogSentry-8                            3000000               407 ns/op             128 B/op          4 allocs/op
BenchmarkUlogSentryWith-8                        1000000              1535 ns/op            1460 B/op         12 allocs/op

Sentry

ulog has a seamless integration with Sentry. For out-of-the-box usage just include this in your configuration yaml:

logging:
  sentry:
    dsn: http://user:secret@your.sentry.dsn/project

If you'd like to take more control over the Sentry integration, see sentry.Configuration

For example, to turn off Stacktrace generation:

logging:
  sentry:
    dsn: http://user:secret@your.sentry.dsn/project
    trace:
      disabled: true

To set up Sentry in code use sentry.Hook. For example:

import (
  "github.com/uber-go/zap"
  "go.uber.org/fx/ulog/ulog"
  "go.uber.org/fx/ulog/sentry"
  "go.uber.org/fx/service"
)

func main() {
  h := sentry.New(MY_DSN, MinLevel(zap.InfoLevel), DisableTraces())
  l := ulog.Builder().WithSentryHook(h).Build()
  svc, err := service.WithLogger(l).Build()
}

Documentation

Overview

Package ulog is the Logging package.

package ulog provides an API wrapper around the logging library zap (https://github.com/uber-go/zap). package ulog uses the builder pattern to instantiate the logger. With LogBuilder you can perform pre-initialization setup by injecting configuration, custom logger, and log level prior to building the usable ulog.Log object.

ulog.Log interface provides a few benefits:

• Decouple services from the logger used underneath the framework

• Easy to use API for logging

• Easily swappable backend logger without changing the service

Sample usage

package main

import "go.uber.org/fx/ulog"

func main() {
  // Configure logger with configuration preferred by your service
  logConfig := ulog.Configuration{}
  logBuilder := ulog.Builder().WithConfiguration(&logConfig)

  // Build ulog.Log from logBuilder
  log := lobBuilder.Build()

  // Use logger in your service
  log.Info("Message describing logging reason", "key", "value")
}

Context

It is very common that in addition to logging a string message, it is desirable to provide additional information: customer uuid, tracing id, etc.

For that very reason, the logging methods (Info,Warn, Debug, etc) take additional parameters as key value pairs.

Retaining Context

Sometimes the same context is used over and over in a logger. For example service name, shard id, module name, etc. For this very reason With()functionality exists which will return a new instance of the logger with that information baked in so it doesn't have to be provided for each logging call.

For example, the following piece of code:

package main

import "go.uber.org/fx/ulog"

func main() {
  log := ulog.Logger()
  log.Info("My info message")
  log.Info("Info with context", "customer_id", 1234)

  richLog := log.With("shard_id", 3, "levitation", true)
  richLog.Info("Rich info message")
  richLog.Info("Even richer", "more_info", []int{1, 2, 3})
}

Produces this output:

{"level":"info","ts":1479946972.102394,"msg":"My info message"}
{"level":"info","ts":1479946972.1024208,"msg":"Info with context","customer_id":1234}
{"level":"info","ts":1479946972.1024246,"msg":"Rich info message","shard_id":3,"levitation":true}
{"level":"info","ts":1479946972.1024623,"msg":"Even richer","shard_id":3,"levitation":true,"more_info":[1,2,3]}

Configuration

ulog configuration can be defined in multiple ways:

Writing the struct yourself

loggingConfig := ulog.Configuration{
  Stdout: true,
}

Configuration defined in YAML

logging:
  stdout: true
  level: debug

Benchmarks

Current performance benchmark data with ulog interface, ulog baseLogger struct, and zap.Logger

BenchmarkUlogWithoutFields-8                    10000000               223 ns/op               0 B/op          0 allocs/op
BenchmarkUlogWithFieldsLogIFace-8                1000000              1237 ns/op            1005 B/op         18 allocs/op
BenchmarkUlogWithFieldsBaseLoggerStruct-8        1000000              1096 ns/op             748 B/op         17 allocs/op
BenchmarkUlogWithFieldsZapLogger-8               2000000               664 ns/op             514 B/op          1 allocs/op
BenchmarkUlogLiteWithFields-8                    3000000               489 ns/op             249 B/op          6 allocs/op
BenchmarkUlogSentry-8                            3000000               407 ns/op             128 B/op          4 allocs/op
BenchmarkUlogSentryWith-8                        1000000              1535 ns/op            1460 B/op         12 allocs/op

Sentry

ulog has a seamless integration with Sentry. For out-of-the-box usage just include this in your configuration yaml:

logging:
  sentry:
    dsn: http://user:secret@your.sentry.dsn/project

If you'd like to take more control over the Sentry integration, see sentry.Configuration

For example, to turn off Stacktrace generation:

logging:
  sentry:
    dsn: http://user:secret@your.sentry.dsn/project
    trace:
      disabled: true

To set up Sentry in code use sentry.Hook. For example:

import (
  "github.com/uber-go/zap"
  "go.uber.org/fx/ulog/ulog"
  "go.uber.org/fx/ulog/sentry"
  "go.uber.org/fx/service"
)

func main() {
  h := sentry.New(MY_DSN, MinLevel(zap.InfoLevel), DisableTraces())
  l := ulog.Builder().WithSentryHook(h).Build()
  svc, err := service.WithLogger(l).Build()
}

Index

Constants

This section is empty.

Variables

View Source
var NopLogger = nopLogger()

NopLogger should be used in tests if you wish to discard the output

Functions

func ContextWithLogger

func ContextWithLogger(ctx context.Context, log Log) context.Context

ContextWithLogger sets the context with the context aware logger

func ContextWithTraceLogger

func ContextWithTraceLogger(ctx context.Context, span opentracing.Span) context.Context

ContextWithTraceLogger returns a new context with a context-aware logger

func SetLogger

func SetLogger(log Log)

SetLogger sets configured logger at the start of the service

Types

type Configuration

type Configuration struct {
	Level   string
	File    *FileConfiguration
	Stdout  bool
	Verbose bool

	// Do not automatically emit metrics for logging counts
	DisableMetrics bool

	Sentry *sentry.Configuration

	TextFormatter *bool // use TextFormatter (default json)
	// contains filtered or unexported fields
}

Configuration for logging with UberFx

type FileConfiguration

type FileConfiguration struct {
	Enabled   bool
	Directory string
	FileName  string
}

FileConfiguration describes the properties needed to log to a file

type Log

type Log interface {
	// With creates a child logger with the provided parameters as key value pairs
	// ulog uses uber-go/zap library as its child logger which needs pairs of key value objects
	// in the form of zap.Fields(key, value). ulog performs field conversion from
	// supplied keyVals pair to zap.Fields format.
	//
	// **IMPORTANT**: With should never be used if the resulting logger
	// object is not being retained. If you need to add some context to
	// a logging message, use the Error, Info, etc. functions
	// and pass in additional interface{} pairs for logging.
	With(keyVals ...interface{}) Log

	// Check returns a zap.CheckedMessage if logging a message at the specified level is enabled.
	Check(level zap.Level, message string) *zap.CheckedMessage

	// Typed returns underlying logger implementation (zap.Logger) to get around the ulog.Log interface
	Typed() zap.Logger

	// Log at the provided zap.Level with message, and a sequence of parameters as key value pairs
	Log(level zap.Level, message string, keyVals ...interface{})

	// Debug logs at Debug level with message, and parameters as key value pairs
	Debug(message string, keyVals ...interface{})

	// Info logs at Info level with message, and parameters as key value pairs
	Info(message string, keyVals ...interface{})

	// Warn ogs at Warn level with message, and parameters as key value pairs
	Warn(message string, keyVals ...interface{})

	// Error logs at Error level with message, and parameters as key value pairs
	Error(message string, keyVals ...interface{})

	// Panic logs at Panic level with message, and parameters as key value pairs
	Panic(message string, keyVals ...interface{})

	// Fatal logs at Fatal level with message, and parameters as key value pairs
	Fatal(message string, keyVals ...interface{})

	// DPanic logs at Debug level (Fatal for development) with message, and parameters as key value pairs
	DPanic(message string, keyVals ...interface{})
}

Log is the UberFx wrapper for underlying logging service

func Logger

func Logger(ctx context.Context) Log

Logger is the context based logger

func New

func New() Log

New instance of ulog.Log is returned with the default setup

func TestingLogger

func TestingLogger() (Log, *spy.Sink)

TestingLogger returns basic logger and underlying sink for testing the messages WithInMemoryLogger testing helper can also be used to test actual outputted JSON bytes

type LogBuilder

type LogBuilder struct {
	// contains filtered or unexported fields
}

LogBuilder is the struct containing logger

func Builder

func Builder() *LogBuilder

Builder creates an empty builder for building ulog.Log object

func (*LogBuilder) Build

func (lb *LogBuilder) Build() Log

Build the ulog logger for use TODO: build should return `(Log, error)` in case we can't properly instantiate

func (*LogBuilder) Configure

func (lb *LogBuilder) Configure() zap.Logger

Configure Log object with the provided log.Configuration

func (*LogBuilder) SetLogger

func (lb *LogBuilder) SetLogger(zap zap.Logger) *LogBuilder

SetLogger allows users to set their own initialized logger to work with ulog APIs

func (*LogBuilder) WithConfiguration

func (lb *LogBuilder) WithConfiguration(logConfig Configuration) *LogBuilder

WithConfiguration sets up configuration for the log builder

func (*LogBuilder) WithScope

func (lb *LogBuilder) WithScope(s tally.Scope) *LogBuilder

WithScope sets up configuration for the log builder

func (*LogBuilder) WithSentryHook

func (lb *LogBuilder) WithSentryHook(hook *sentry.Hook) *LogBuilder

WithSentryHook allows users to manually configure the sentry hook

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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