clog

package
v0.0.0-...-d7ad1eb Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2025 License: MIT Imports: 19 Imported by: 0

README

The Clues Logger

Regular logging

Infow/Debugw/Errorw are also supported.
So are the *f variations. Because I'm trying to be nice.
Warn is not included. Because I'm not that nice.

clog.Ctx(ctx).Info("information")
clog.Ctx(ctx).Label(clog.ExampleDebugLabel).Debug("debugging")
clog.Ctx(ctx).Err(err).Error("badness")

Labeling your logs

Labeling is intended to make categorical lookup of logs much easier.

Many times we build unintentional colloquialisms into our log vocabulary and try to filter on those when looking for info. Ex: logs that say "recoverable error" are "the important error logs". No, none of that.

If you have a set of logging that you always want to include or exclude, put a label on it. "How was this run configured?" -> filter clabel like /clabel_configuration/ "What caused the process to fail?" -> filter clabel like /clabel_error_origin/

clog.CtxErr(ctx, err).
  Label(clog.LStartOfRun, clog.LFailureSource).
  Info("couldn't start up process")

Commenting your logs

clog.Ctx(ctx).
  Comment(`I could just add this in code... but now we can pull double duty!
  whatever I say here is readable to anyone who is looking at the logs (which is good
  if I'm trying to tell them what they need to know about due to this log occurring);
  it's also a regular comment, as if in code, so the code is now also commented!`).
  Info("information")

Automatically adds structured data from clues

ctx := clues.Add(ctx, "foo", "bar")
err := clues.New("a bad happened").With("fnords", "smarf")

clog.CtxErr(ctx, err).
  With("beaux", "regarde").
  Debug("all the info!")

// this produces a log containing:
// {
//  "msg": "all the info!",
//  "foo": "bar",
//  "fnords": "smarf",
//  "beaux": "regarde",
// }

Setting up logs

set := clog.Settings{
  Format: clog.FormatForHumans,
  Level: clog.LevelInfo,
}

ctx := clog.Init(ctx, set)

Filtering Debug Logs (aka, improved debug levels)

You're using labels to categorize your logs, right? Right? Well then you've already built out your debug logging levels! Want to only include a certain set of your very noisy debug logs? Just specify which label you want included in the debug level.

set := clog.Settings{
  Format: clog.FormatForHumans,
  Level: clog.LevelDebug,
  OnlyLogDebugIfContainsLabel: []string{clog.APICall},
}

ctx := clog.Init(ctx, set)

Documentation

Index

Constants

View Source
const (
	// good for categorizing debugging-level api call info.
	APICall = "clabel_api_call"
	// when you want your log to cause a lot of noise.
	AlarmOnThis = "clabel_alarm_on_this"
	// for info about end-of-run resource cleanup.
	Cleanup = "clabel_cleanup"
	// for showcasing the runtime configuration of your app
	Configuration = "clabel_configuration"
	// everything that you want to know about the process
	// at the time of its conclusion.
	EndOfRunResults = "clabel_end_of_run_results"
	// good for marking the the error logs that you need to review
	// when debugging "what exactly failed in this run?"
	FailureOrigin = "clabel_failure_origin"
	// when you want debug logging to include info about every item
	// that gets handled through the process.
	IndividualItemDetails = "clabel_individual_item_details"
	// when debugging the progress of a process and you want to
	// include logs that track the completion of long running
	// processes.
	ProgressTicker = "clabel_progress_ticker"
	// everything that you want to know about the state of the
	// application when you kick off a new process.
	StartOfRun = "clabel_start_of_run"
	// who needs a logging level when you can use a label instead?
	Warning = "clabel_warning"
)

Default / Example labels

View Source
const (
	LevelDebug    logLevel = "debug"
	LevelInfo     logLevel = "info"
	LevelError    logLevel = "error"
	LevelDisabled logLevel = "disabled"
)
View Source
const (
	// use for cli/terminal
	FormatForHumans logFormat = "human"
	// use for cloud logging
	FormatToJSON logFormat = "json"
)
View Source
const (
	HashSensitiveInfo            sensitiveInfoHandlingAlgo = "hash"
	MaskSensitiveInfo            sensitiveInfoHandlingAlgo = "mask"
	ShowSensitiveInfoInPlainText sensitiveInfoHandlingAlgo = "plaintext"
)
View Source
const (
	Stderr = "stderr"
	Stdout = "stdout"
)

Variables

This section is empty.

Functions

func Ctx

func Ctx(ctx context.Context) *builder

Ctx retrieves the logger embedded in the context. It also extracts any clues from the ctx and adds all k:v pairs to that log instance.

func CtxErr

func CtxErr(ctx context.Context, err error) *builder

CtxErr is a shorthand for clog.Ctx(ctx).Err(err)

func Flush

func Flush(ctx context.Context)

Flush writes out all buffered logs. Probably good to do before shutting down whatever instance had initialized the singleton.

func Inherit

func Inherit(
	from, to context.Context,
	clobber bool,
) context.Context

Inherit propagates the clog client from one context to another. This is particularly useful for taking an initialized context from a main() func and ensuring the logger is available for request-bound conetxts, such as in a http server pattern.

If the 'to' context already contains an initialized logger, no change is made. Callers can force a 'from' logger to override a 'to' logger by setting clobber=true.

func Init

func Init(ctx context.Context, set Settings) context.Context

Init embeds a logger within the context for later retrieval. It is a preferred, but not necessary, initialization step. If you don't call this and you start logging, or you call Singleton(), then the package will initialize a logger instance with the default values. If you need to configure your logs, make sure to embed this first.

func PlantLogger

func PlantLogger(ctx context.Context, seed *zap.SugaredLogger) context.Context

PlantLogger allows users to embed their own zap.SugaredLogger within the context. It's good for inheriting a logger instance that was generated elsewhere, in case you have a downstream package that wants to clog the code with a different zsl.

func Singleton

func Singleton() *builder

Singleton is a shorthand for .Ctx(context.Background()). IE: it'll use the singleton logger directly; building one if necessary. You should avoid this and use .Ctx or .CtxErr if possible. Likelihood is that you're somewhere deep in a func chain that doesn't accept a ctx, and you still want to add a quick log; maybe for debugging purposes.

That's fine! Everything should work great.

Unless you call this before initialization. Then it'll panic. We do want you to init the logger first, else you'll potentially lose these logs due different buffers.

Types

type Settings

type Settings struct {

	// Format defines the output structure, standard design is
	// as text (human-at-a-console) or json (automation).
	Format logFormat
	// Level determines the minimum logging level.  Anything
	// below this level (following standard semantics) will
	// not get logged.
	Level logLevel

	// more fiddly bits
	SensitiveInfoHandling sensitiveInfoHandlingAlgo // how to obscure pii
	// when non-empty, only debuglogs with a label that matches
	// the provided labels will get delivered.  All other debug
	// logs get dropped.  Good way to expose a little bit of debug
	// logs without flooding your system.
	OnlyLogDebugIfContainsLabel []string
	// contains filtered or unexported fields
}

Settings records the user's preferred logging settings.

func (Settings) EnsureDefaults

func (s Settings) EnsureDefaults() Settings

EnsureDefaults sets any non-populated settings to their default value. exported for testing without circular dependencies.

func (Settings) LogToFile

func (s Settings) LogToFile(pathToFile string) (Settings, error)

LogToFile defines a system file to write all logs onto.

func (Settings) LogToStdOut

func (s Settings) LogToStdOut() Settings

LogToStdOut swaps the log output from Stderr to Stdout.

type Writer

type Writer struct {
	Ctx context.Context
}

Writer is a wrapper that turns the logger embedded in the given ctx into an io.Writer. All logs are currently info-level.

func (Writer) Write

func (w Writer) Write(p []byte) (int, error)

Write writes to the the Writer's clogger.

Jump to

Keyboard shortcuts

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