xop

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jan 23, 2024 License: MIT Imports: 18 Imported by: 2

README

xop - Golang structured log generation combined with tracing (Cross Obserability Platform)

GoDoc unit tests report card codecov

Vision

Logging that is chap, rich, in-context, searchable, and long-lived creates a situation where bugs can be fixed quickly, especially when combined with with supportive programming practices.

Logs that are in-context allow a story to be told. A story of what happened and why. This story can be supported by logging data models, tables, and other references that would allow bugs to be reproduced.

In-context means that you know what triggered something to happen. You also know what trigggered that prior thing. And what triggered the thing before that. This requires logging a lot. It also requires being able to see only the part of the logs that matter. All logs are within spans. All spans are within requests. All requests are within traces.

Searchable doesn't mean full-text search, though that could be present. When a software engineer learns that there is a problem with someting, that usually comes with identifiers attached to it. Customer numbers. Invoices. Some kinda of identity that lives within the system. These identifiers can be attributes that are attached to requests. Searchable logs means that given an identifier or two and some hint of what went wrong, an engineer can quickly find the exact point, in a log, where the problem first manifested, and by working backwards, following links in the logs, find likely cause.

The main supportive coding practice that helps at this point is building complex things with pure functions. The inputs to pure functions, or at least ways to regenerate the inputs, can be included in the logs. Once you have one regression test built from replaying inputs from logs, any further problems with the same pure function can usually be reporoduced in minutes.

Combine all these elements and the time to diagnose and reproduce a new code issue can drop down to a handful of minutes.

The goal of XOP is to provide that richness in a way that is easy to use, efficient, and easy to integrate into existing code.

Development status

Ready to use, not yet stable. Any incompatible changes will be clearly marked in the release descriptions. At this point, adoptors should make themselves known and discuss anything that comes up.

Please open issues to start discussions around a subject. Please feel free to open pull requests, especially to added base loggers or propagators.

Expect the following changes as development continues:

  • API changes as additional features are added

    Currently xop has no metrics support. That will change and adding metrics will probably be the biggest API change

  • Additional gateway base loggers will be written

    To make xop the best logging library for library writers, a full compliment of xop -> logger gateways will be written.

    • zap
    • logrus
    • zerolog
    • onelog
  • The full set of OpenTelemetry semconv (Semantic Conventions) to be imported into xopconst (or perhaps somewhere else).

  • Performance has been neglected for a while to focus on other things. Performance will be a focus again.

Historical context

Observability code and technique is rapidly evolving. The Open Telemetry project is the focus of most of the energy now. Until Open Telemetry releases a Go logger, there still isn't a well integrated logs and traces package.

That is beginning to change. There is now a Zap/OTEL integration.

Xop is currently the only Go structured logs and tracing system. Performance-wise, it's better that Zap, and was on-par with Zerolog, but recently fell behind.

Where Xop shines is in it's API design. Xop manages to be very flexible, has lots of features, is easy to use and has high performance. Meeting all of those goals simultaneously made Xop somewhat difficult to build. Making logging type-safe is difficult because most ways to accomplish it make logging more diffuclt and more complex. Xop tries to strike a blance between safety and usability. Metadata on spans are fully type-safe and keywords must be pre-registered. Data elements on log lines are mostly type-safe but do not need to be pre-registered.

Base loggers

Xop is a two-level logger. The top-level logger provides the API for logging lines and spans, etc. The bottom-level loggers translate the logs to different formats.

Some of the bottom-level loggers are "full fidelity" which means that they are bundled with a function that can consume their own output and re-log it to a different bottom-level logger thus translating from one format to another. Xop bottom-level loggers must implement the xopbase Logger interface.

name full fidelity description
xopjson yes JSON output
xopotel yes Output though OpenTelemetry spans (Go logger not available)
xopcon no Console/text logger emphasizing human readability
xopconsole yes Console/text logger with no information loss
xoppb yes Protobuf output
xoprecorder yes Output into a structured in-memory buffer
xoptest no Output to testing.T logger

Using xop

To log, you must have a *Log object. To create one you must start with a Seed. Seeds are created with NewSeed(mods ...SeedModifier). The SeedModifiers are where you specify where the logs actually go by supplying a bottom level, log exporter: a xopbase.Logger. There are various bottom level loggers: xoptest for logging to a *testing.T, xopjson for generating JSON logs, and xopotel for exporting traces (and logs) via OpenTelemtry.

seed := xop.NewSeed(xop.WithBase(xopjson.New(xopbytes.WriteToIOWriter(io.Stdout))))

When you've got a contrete task, for example responding to an HTTP request or running a cronjob, you convert the Seed into a *Log with the Request() method. This can be hooked into your HTTP router so that a *Log is injected into the request's Context.

log := seed.Request("GET /users")
r = r.WithContext(log.IntoContext(r.Context()))

Once you have a *Log, you can log individual "lines", text with optional attached data elements.

The creation of a log line is done with chained methods. It starts with selecting the log level.

log.Info().String("username", "john").Msg("created new user")

Logs are more useful when they have context. Xop supports adding context by making it easy to create sub-spans. There are two flavors of sub-spans: one for when doing things in parallel and one for when doing a sequence of actions.

forkA := log.Sub().Fork("do something in a go-routine")
step1 := log.Sub().Step("do the first step of a sequence")

Later, when looking at the various span and requests, it is helpful to have metadata attached. The metadata keys must be pre-registered.

var BillingAccountKey = xopat.Make{
	Key: "billing.account",
	Namespace: "myApp",
	Indexed: true,
	Prominence: 10,
	Description: "A billing account number",
}.Int64Attribute()

step1.Span().Int64(BillingAccountKey, 299232)

There are many other features including:

  • creating sub-loggers (span, etc) that prefill line attributes
  • fetch logger out of Context
  • adjust the logging level based on environment variables so that different Go packages can log at different levels
  • change the set of base loggers on the fly
  • mark with spans are done
  • adjust Seed values as *Log is created
  • redact sensitive values as they're being logged
  • create a seed from a *Log or *Span

Although xop supports a global logger, it's use is discouraged because it doesn't provide enough context for the resulting logs to be useful.

Performance

The performance of Xop is good enough. See the benchmark results at logbench.

In general: faster than zap; about the same as zerolog; but not as quick as onelog or phuslog.

Xop has a much richer feature set than onelog or phuslog and a nicer API than zap.

Propagation

Tracing is inter-process. Xop supports both B3 and WC3 trace headers in the propagators that have been written.

Incoming

Incoming propagation is when we learn our parent trace id from a request made to our server. Xop currently only supports HTTP. It is done with the xopmiddle package.

xopmiddle generates middleware in various flavors so that you can incorporate into various http router frameworks.

Outgoing

Outgoing propagation is sharing the current trace id as the parent request to another server when making a request. Xop currently only supports HTTP and that only with resty in the xopresty package. Adding additional outgoing propagators is an outstanding priority.

Version compatibility

xop is currently tested with go1.18 through go1.20. It is probably compatible with go1.17 and perhaps earlier.

Terminology

A "trace" is the the entire set of spans relating to one starting request or action. It can span multiple servers.

A "request" is a single request or action being handled by one program. It does not span multiple servers. There can be multiple requests in a trace.

A "span" is a linear portion of the processing required to handle a request. A single span should not include multiple threads of execution. Span should represent a logical component to of the work being done. Breaking the work into spans is an exercise for the programmer.

A "logger" is something that is used throughout code to generate log lines and spans.

A "base logger" is the layer below that the "logger" uses to send output to different systems.

A "bytes logger" is an optional layer below "base logger" that works with logs that have already become []bytes.

Naming

Name registry

Arbitrary names are supported for tagging log lines. For attributes to be displayed specially in front-ends, they need to follow standards. Standard attribute groups are pre-registered as structs. These can be shared between organizations by contributing them to the Xop repository.

The following names are reserved. What happens if they're used is undefined and up to the individual base loggers.

  • xop. Used to indicate the kind of item begin emitted in a stream of objects. Empty for lines, span for spans. enum to establish enum -> string mappings. chunk for things broken up because they're too big. template for lines that need template expansion.
  • msg. Used for the text of a log line.
  • ts. Used for the timestamp of the log event, if included.
  • stack. Used for stacktraces when errors or alerts are logged.
  • span. Used for the span-id of log lines for some base loggers.
  • caller. Used to indicate the immediate caller (file & line) when that's desired.
  • level. The log level (debug, trace, info, warn, error, alert)

The data associated with spans, traces, and requests must come from pre-registered keys.

Attribute/Key naming
Open Telementry

OpenTelemetry has invested heavily in naming. They call it semconv (Semantic Conventions). Although not yet complete, an open TODO for xop is to import the entirty of the OpenTelemetry semantic conventions into attributes. We'll do this for two resons:

  1. Compatibility
  2. The effenciency of not re-inventing the wheel.

They say to use dots (.) to separate namespaces in attribute names and underscores (_) to separate words within a name. Do not use a namespace as an attribute.

They have lots of examples for:

Open Tracing

The Open Tracing project has been "archived" in favor of Open Telementry. That said, they have a much shorter set of semantic conventions.

Zipkin

While lacking a full set of semantic conventions, Zipkin has some sage advice around how to instrument spans

OpenCensus

OpenCensus lacks a full set of semantic conventions, but it does having suggestions for how to name spans. In OpenCensus, tags names need to be registered.

Philosophy

Xop is opinionated. It gently nudges in certain directions. Perhaps the biggest nudge is that there is no support for generating logs outside of a span.

Log less

Do not log details that don't materialy add to the value of the log

Log more

Use logs as a narritive of what's going on in the program so that when you look at the logs, you can follow along with what's going on.

Always log in context

Logs are best viewed in context: without without needing to search and correlate, you should know how you go to the point of the log line you're looking at. This means the line itself needs less detail and it contributes to the context of the lines around it.

No log.Fatal

Panic should be caught and logged. If panic is caught, log.Fatal() is not needed and is even redundant as it would problaby panic itself causing multiple log.Alert() for the same event.

Defer work

Most logs won't be looked at. Ever. When possilbe defer the work of assembling the log to when it viewed.

Other systems

This logger is primarily inspired by a proprietary logger at BlueOwl. Other structured loggers also provided inspiration: onelog; phuslog; zap; zerolog; Open Telementry; and Jaeger.

Special thanks to phuslog as some of its code was used.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Default = NewSeed().Request("discard")

Default serves as a fallback logger if FromContextOrDefault does not find a logger. Unless modified, it discards all logs.

View Source
var DefaultConfig = Config{
	FlushDelay: time.Minute * 5,
	ErrorReporter: func(err error) {
		golog.Print("Error from zop", err)
	},
}
View Source
var DefaultSettings = func() LogSettings {
	var settings LogSettings
	settings.stackFramesWanted[xopnum.AlertLevel] = 20
	settings.stackFramesWanted[xopnum.ErrorLevel] = 10
	settings.minimumLogLevel = xopnum.DebugLevel
	settings.synchronousFlushWhenDone = true
	settings.stackFilenameRewrite = func(s string) string { return s }
	return settings
}()

DefaultSettings are the settings that are used if no setting changes are made. Trace logs are excluded. Alert and Error level log lines get stack traces.

View Source
var LogLinkPrefix string

LogLinkPrefix can be set during init(). It should not be modified afterwards. It can be used by base loggers (like xoptest) to prefix a traceheader to turn it into a link.

Functions

func CombineBaseLoggers added in v0.3.0

func CombineBaseLoggers(first xopbase.Logger, more ...xopbase.Logger) xopbase.Logger

CombineBaseLoggers is probably only useful for testing xop because Seed already provides a better way to manage multiple base loggers.

func ContextLevelAdjuster

func ContextLevelAdjuster(getLogFromContext func(context.Context) *Logger, opts ...AdjusterOption) func(context.Context) *Logger

ContextLevelAdjuster returns a function that gets a logger from context. The logger it returns will have a minimum logging level that is specific for the calling package. If starting from a logger instead of a context, use LevelAdjuster

The level used will be the level set in this order: (1) From the environment variable "XOPLEVEL_foo" (for package foo). The level can either a string or the numeric level. See xopnum/level.go. (2) From the level provided in the call to AdjustedLevelLoger assuming that the passed level is not zero. (3) The level that the logger already has.

package foo
var getLogger = xop.AdjustedLevelLoger(xop.FromContextOrPanic)

func CustomFromContext

func CustomFromContext(getLogFromContext func(context.Context) *Logger, adjustSettings func(*Sub) *Sub) func(context.Context) *Logger

CustomFromContext returns a convenience function: it calls either FromContextOrPanic() or FromContextOrDefault() and then calls a function to adjust setting.

Pass FromContextOrPanic or FromContextOrDefault as the first argument and a function to adjust settings as the second argument.

func LevelAdjuster

func LevelAdjuster(opts ...AdjusterOption) func(*Logger) *Logger

LevelAdjuster returns a function that adjusts the level of a logger for local package-scoped defaults. It is a sibling to AdjustedLevelLogger.

The default behavior is to determine the name of the local package and then using that look at the environment variable "XOPLEVEL_<package_name>" (where <package_name> is the name of the current package) and set the minimum log level according to the value of that environment variable.

package foo
var adjustLogger = xop.LevelAdjuster()

Types

type AdjusterOption

type AdjusterOption func(*adjustOptions)

func WithDefault

func WithDefault(level xopnum.Level) AdjusterOption

WithDefault sets a default logger level for LevelAdjuster and ContextLevelAdjuster. If the environment variable is found then that will override this default. This default will override the existing minimum logging level.

The default minimum level comes from DefaultSettings

func WithEnvironment

func WithEnvironment(environmentVariableName string) AdjusterOption

WithEnvironment overrides the name of the environment variable used to override log levels in LevelAdjuster and ContextLevelAdjuster. WithEnvironment makes the package name irrelevant and thus should not bue used in combination with WithPackage.

func WithPackage

func WithPackage(pkg string) AdjusterOption

WithPackage overrides how the package name is found. The package name is combined with "XOPLEVEL_" to create the name of the environment variable to check for adjusting log levels with LevelAdjuster and ContextLevelAdjuster

func WithSkippedFrames

func WithSkippedFrames(additionalFramesToSkip int) AdjusterOption

WithSkippedFrames is needed only if LevelAdjuster or ContextLevelAdjuster are called from within another function that should not be used to derrive the package name.

type Config

type Config struct {
	UseB3      bool // Zipkin
	FlushDelay time.Duration

	// ErrorReporter provides a way to choose the behavior
	// for when underlying log functions throw an error.
	// Generally speaking, needing to check errors when
	// generating logs is a non-starter because the cost is
	// too high.  It would discourage logging.  That said,
	// there is a an error, we don't want to completely
	// ignore it.
	ErrorReporter func(error)
}

type ConfigModifier

type ConfigModifier func(*Config)

type Detaching

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

Detaching is a ephemeral type used in the chain

child := logger.Sub().Detach().Fork()
child := logger.Sub().Detach().Step()

to indicate that the new logger/span has an independent lifetime from it's parent so a call to Done() on the parent does not imply the child is done.

func (*Detaching) Fork

func (d *Detaching) Fork(msg string, mods ...SeedModifier) *Logger

func (*Detaching) Step

func (d *Detaching) Step(msg string, mods ...SeedModifier) *Logger

type Key added in v0.3.0

type Key = xopat.K

type Line

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

Line represents a single log event that is in progress. All methods on Line either return Line or don't. The methods that do not return line, like Msg() mark the end of life for that Line. It should not be used in any way after that point.

Nothing checks that Line isn't used after Msg(). Using line after Msg() probably won't panic, but will definitely open the door to confusing inconsistent logs and race conditions.

func (*Line) Any

func (line *Line) Any(k xopat.K, v interface{}) *Line

Any can be used to log something that might be modified after this call. If any base logger does not immediately serialize, then the object will be copied using https://github.com/mohae/deepcopy 's Copy(). The return value must be consumed for the line to be logged.

func (*Line) AnyWithoutRedaction

func (line *Line) AnyWithoutRedaction(k xopat.K, v interface{}) *Line

AnyWithoutRedaction The return value must be consumed for the line to be logged.

func (*Line) Bool

func (line *Line) Bool(k xopat.K, v bool) *Line

Bool adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Duration

func (line *Line) Duration(k xopat.K, v time.Duration) *Line

Duration adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) EmbeddedEnum

func (line *Line) EmbeddedEnum(k xopat.EmbeddedEnum) *Line

EmbeddedEnum adds a key/value pair to the current log line. The type of the value implies the key. The return value must be consumed for the line to be logged.

func (*Line) Enum

func (line *Line) Enum(k *xopat.EnumAttribute, v xopat.Enum) *Line

Enum adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Error

func (line *Line) Error(k xopat.K, v error) *Line

Error adds a key/value pair to the current log line. The default logging of an error is simply err.Error() to change that, set a redaction function. The return value must be consumed for the line to be logged.

func (*Line) Float32

func (line *Line) Float32(k xopat.K, v float32) *Line

Float32 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Float64

func (line *Line) Float64(k xopat.K, v float64) *Line

Float64 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Int

func (line *Line) Int(k xopat.K, v int) *Line

Int adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Int16

func (line *Line) Int16(k xopat.K, v int16) *Line

Int16 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Int32

func (line *Line) Int32(k xopat.K, v int32) *Line

Int32 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Int64

func (line *Line) Int64(k xopat.K, v int64) *Line

Int64 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Int8

func (line *Line) Int8(k xopat.K, v int8) *Line

Int8 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (line *Line) Link(link xoptrace.Trace, msg string)

func (*Line) Linkf added in v0.3.0

func (line *Line) Linkf(link xoptrace.Trace, msg string, v ...interface{})

func (*Line) Model added in v0.3.0

func (line *Line) Model(obj interface{}, msg string)

Model and Any serve similar roles: both can log an arbitrary data object. Model terminates the log line where Any adds a key/value attribute to the log line.

Prefer Model() over Any() when the point of the log line is the model. Prefer Any() over Model() when the model is just one of several key/value attributes attached to the log line.

func (*Line) ModelImmutable added in v0.3.0

func (line *Line) ModelImmutable(obj interface{}, msg string)

ModelImmutable can be used to log something that is not going to be further modified after this call.

func (*Line) ModelImmutablef added in v0.3.0

func (line *Line) ModelImmutablef(obj interface{}, msg string, v ...interface{})

func (*Line) Modelf added in v0.3.0

func (line *Line) Modelf(obj interface{}, msg string, v ...interface{})

func (*Line) Msg

func (line *Line) Msg(msg string)

Msg sends a log line. After Msg(), no further use of the *Line is allowed. Without calling Msg(), Template(), Msgf(), Msgs(), or Link(), Linkf(), Modelf() or Model(), the log line will not be sent or output.

func (*Line) Msgf

func (line *Line) Msgf(msg string, v ...interface{})

Msgf sends a log line, using fmt.Sprintf()-style formatting.

func (*Line) Msgs

func (line *Line) Msgs(v ...interface{})

func (*Line) String

func (line *Line) String(k xopat.K, v string) *Line

String adds a key/value pair to the current log line. The string can be redacted if a redaction function has been set. The return value must be consumed for the line to be logged.

func (*Line) Stringer

func (line *Line) Stringer(k xopat.K, v fmt.Stringer) *Line

Stringer adds a key/value pair to the current log line. The string can be redacted if a redaction function has been set. The return value must be consumed for the line to be logged.

func (*Line) Template

func (line *Line) Template(template string)

Template is an alternative to Msg() that sends a log line. Template is a string that uses "{name}" substitutions from the data already sent with the line to format that data for human consumption.

Depending on the base logger in use, Template can be cheaper or more expensive than Msgf. It's cheaper for base loggers that do not expand the message string but more expensive for ones that do, like xoptest.

Unlike Msgf(), parameter to the message are preserved as data elements. Data elements do not have to be consumed by the template.

The names used for "{name}" substitutions are restricted: they may not include any characters that would be escapsed in a JSON string. No double quote. No linefeed. No backslash. Etc.

Prefilled text (PrefillText()) will be prepended to the template.

func (*Line) Time

func (line *Line) Time(k xopat.K, v time.Time) *Line

Time adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uint

func (line *Line) Uint(k xopat.K, v uint) *Line

Uint adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uint16

func (line *Line) Uint16(k xopat.K, v uint16) *Line

Uint16 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uint32

func (line *Line) Uint32(k xopat.K, v uint32) *Line

Uint32 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uint64

func (line *Line) Uint64(k xopat.K, v uint64) *Line

Uint64 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uint8

func (line *Line) Uint8(k xopat.K, v uint8) *Line

Uint8 adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

func (*Line) Uintptr added in v0.3.0

func (line *Line) Uintptr(k xopat.K, v uintptr) *Line

Uintptr adds a key/value pair to the current log line. The return value must be consumed for the line to be logged.

type LogSettings

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

func (LogSettings) Copy

func (settings LogSettings) Copy() LogSettings

func (LogSettings) GetMinLevel

func (settings LogSettings) GetMinLevel() xopnum.Level

func (*LogSettings) MinLevel

func (settings *LogSettings) MinLevel(level xopnum.Level)

MinLevel sets the minimum logging level below which logs will be discarded. The default minimum level comes from DefaultSettings.

func (*LogSettings) NoPrefill

func (settings *LogSettings) NoPrefill()

func (*LogSettings) PrefillAny

func (settings *LogSettings) PrefillAny(k xopat.K, v interface{})

PrefillAny is used to set a data element that is included on every log line. Values provided with PrefillAny will be copied using https://github.com/mohae/deepcopy 's Copy(). PrefillAny is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called. Redaction is not supported.

func (*LogSettings) PrefillBool

func (settings *LogSettings) PrefillBool(k xopat.K, v bool)

func (*LogSettings) PrefillDuration

func (settings *LogSettings) PrefillDuration(k xopat.K, v time.Duration)

func (*LogSettings) PrefillEmbeddedEnum

func (settings *LogSettings) PrefillEmbeddedEnum(k xopat.EmbeddedEnum)

func (*LogSettings) PrefillEnum

func (settings *LogSettings) PrefillEnum(k *xopat.EnumAttribute, v xopat.Enum)

func (*LogSettings) PrefillError

func (settings *LogSettings) PrefillError(k xopat.K, v error)

PrefillError is used to set a data element that is included on every log line. Errors will always be formatted with v.Error(). Redaction is not supported.

func (*LogSettings) PrefillFloat32

func (settings *LogSettings) PrefillFloat32(k xopat.K, v float32)

func (*LogSettings) PrefillFloat64

func (settings *LogSettings) PrefillFloat64(k xopat.K, v float64)

func (*LogSettings) PrefillInt

func (settings *LogSettings) PrefillInt(k xopat.K, v int)

func (*LogSettings) PrefillInt16

func (settings *LogSettings) PrefillInt16(k xopat.K, v int16)

func (*LogSettings) PrefillInt32

func (settings *LogSettings) PrefillInt32(k xopat.K, v int32)

func (*LogSettings) PrefillInt64

func (settings *LogSettings) PrefillInt64(k xopat.K, v int64)

func (*LogSettings) PrefillInt8

func (settings *LogSettings) PrefillInt8(k xopat.K, v int8)

func (*LogSettings) PrefillString

func (settings *LogSettings) PrefillString(k xopat.K, v string)

func (*LogSettings) PrefillText

func (settings *LogSettings) PrefillText(m string)

PrefillText is prepended to any eventual Line.Msg() or Line.Template() PrefillText will be ignored for Line.Model() and Line.Link().

func (*LogSettings) PrefillTime

func (settings *LogSettings) PrefillTime(k xopat.K, v time.Time)

func (*LogSettings) PrefillUint

func (settings *LogSettings) PrefillUint(k xopat.K, v uint)

func (*LogSettings) PrefillUint16

func (settings *LogSettings) PrefillUint16(k xopat.K, v uint16)

func (*LogSettings) PrefillUint32

func (settings *LogSettings) PrefillUint32(k xopat.K, v uint32)

func (*LogSettings) PrefillUint64

func (settings *LogSettings) PrefillUint64(k xopat.K, v uint64)

func (*LogSettings) PrefillUint8

func (settings *LogSettings) PrefillUint8(k xopat.K, v uint8)

func (*LogSettings) PrefillUintptr added in v0.3.0

func (settings *LogSettings) PrefillUintptr(k xopat.K, v uintptr)

func (*LogSettings) SetRedactAnyFunc

func (settings *LogSettings) SetRedactAnyFunc(f RedactAnyFunc)

SetRedactAnyFunc sets a redaction function to be used when Line.Any() is called.

func (*LogSettings) SetRedactErrorFunc

func (settings *LogSettings) SetRedactErrorFunc(f RedactErrorFunc)

SetRedactErrorFunc sets a redaction function to be used when Line.Error() is called.

func (*LogSettings) SetRedactStringFunc

func (settings *LogSettings) SetRedactStringFunc(f RedactStringFunc)

SetRedactStringFunc sets a redaction function to be used when Line.String() is called.

func (*LogSettings) StackFilenameRewrite added in v0.3.0

func (settings *LogSettings) StackFilenameRewrite(f func(string) string)

StackFilenameRewrite is used to rewrite filenames in stack traces. Generally this is used to eliminate path prefixes. An empty return value indicates that the rest of the stack trace should be discarded.

func (*LogSettings) StackFrames

func (settings *LogSettings) StackFrames(level xopnum.Level, frameCount int)

StackFrames sets the number of stack frames to include at a logging level. Levels above the given level will be set to get least this many. Levels below the given level will be set to receive at most this many.

func (LogSettings) String added in v0.3.0

func (settings LogSettings) String() string

String is for debugging purposes. It is not complete or preformant.

func (*LogSettings) SynchronousFlush

func (settings *LogSettings) SynchronousFlush(b bool)

SynchronousFlush sets the behavior for any Flush() triggered by a call to Done(). When true, the call to Done() will not return until the Flush() is complete.

func (*LogSettings) TagLinesWithSpanSequence

func (settings *LogSettings) TagLinesWithSpanSequence(b bool)

TagLinesWithSpanSequence controls if the span sequence indicator (see Fork() and Step()) should be included in the prefill data on each line.

type Logger added in v0.3.0

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

func FromContext

func FromContext(ctx context.Context) (*Logger, bool)

func FromContextOrDefault

func FromContextOrDefault(ctx context.Context) *Logger

func FromContextOrPanic

func FromContextOrPanic(ctx context.Context) *Logger

func (*Logger) Alert added in v0.3.0

func (logger *Logger) Alert() *Line

func (*Logger) Boring added in v0.3.0

func (logger *Logger) Boring()

Marks this request as boring. Any logger at the Alert or Error level will mark this request as not boring.

func (*Logger) Config added in v0.3.0

func (logger *Logger) Config() Config

func (*Logger) Debug added in v0.3.0

func (logger *Logger) Debug() *Line

func (*Logger) Done added in v0.3.0

func (logger *Logger) Done()

Done is used to indicate that a logger is complete. Buffered base loggers (implementing xopbase.Logger) wait for Done to be called before flushing their data.

Requests (Logger's created by seed.Request()) and detached logs (created by logger.Sub().Detach().Fork() or logger.Sub().Detah().Step()) are considered top-level logs. A call to Done() on a top-level logger marks all sub-spans as Done() if they were not already marked done.

Calling Done() on a logger that is already done generates a logged error message.

Non-detached sub-spans (created by logger.Sub().Fork() and logger.Sub().Step()) are done when either Done is called on the sub-span or when their associated top-level logger is done.

Sub-logs that are not spans (created by logger.Sub().Logger()) should not use Done(). Any call to Done on such a sub-logger will log an error and otherwise be ignored.

When all the logs associated with a Request are done, the Flush() is automatically triggered. The Flush() call can be synchronous or asynchronous depending on the SynchronousFlush settings of the request-level Logger.

Any logging activity after a Done() causes an error to be logged and may trigger a call to Flush().

func (*Logger) Error added in v0.3.0

func (logger *Logger) Error() *Line

func (*Logger) Flush added in v0.3.0

func (logger *Logger) Flush()

func (*Logger) Info added in v0.3.0

func (logger *Logger) Info() *Line

func (*Logger) IntoContext added in v0.3.0

func (logger *Logger) IntoContext(ctx context.Context) context.Context

func (*Logger) Line added in v0.3.0

func (logger *Logger) Line(level xopnum.Level) *Line

Line starts a log line at the specified log level. If the log level is below the minimum log level, the line will be discarded.

func (*Logger) Log added in v0.3.0

func (logger *Logger) Log() *Line

func (*Logger) Request added in v0.3.0

func (logger *Logger) Request() *Span

Request provides access to the span that describes the overall request. Metadata may be added at the request level.

func (*Logger) Settings added in v0.3.0

func (logger *Logger) Settings() LogSettings

func (*Logger) Span added in v0.3.0

func (logger *Logger) Span() *Span

Request provides access to the current span Metadata may be added at the span level.

func (*Logger) Sub added in v0.3.0

func (logger *Logger) Sub() *Sub

Sub is a first step in creating a sub-Log from the current logger. Sub allows log settings to be modified. The returned value must be used. It is used by a call to sub.Logger(), sub.Fork(), or sub.Step().

Logs created from Sub() are done when their parent is done.

func (*Logger) Trace added in v0.3.0

func (logger *Logger) Trace() *Line

func (*Logger) Warn added in v0.3.0

func (logger *Logger) Warn() *Line

type RedactAnyFunc

type RedactAnyFunc func(baseLine xopbase.Line, k xopat.K, v interface{}, alreadyImmutable bool)

RedactAnyFunc is used to redact models as they're being logged. It is RedactAnyFunc's responsibility to call

baseLine.Any(k, xopbase.ModelArg{
	Model: v,
})

if it wants the value to be logged. If it does make that call, it must pass an immutable value. Perhaps use "github.com/mohae/deepcopy" to make a copy?

The provided xopbase.Line may not be retained beyond the duration of the function call.

type RedactErrorFunc

type RedactErrorFunc func(baseLine xopbase.Line, k xopat.K, v error)

RedactErrorFunc is used to redact or format errors as they're being logged. It is RedactErrorFunc's responsibility to call

baseLine.String(k, v.Error(), xopbase.ErrorDataType)

if it wants the value to be logged. Alternatively, it could log the error as a model:

baseLine.Any(k, v)

The provided xopbase.Line may not be retained beyond the duration of the function call.

type RedactStringFunc

type RedactStringFunc func(baseLine xopbase.Line, k xopat.K, v string)

RedactStringFunc is used to redact strings as they're being logged. It is RedactStringFunc's responsiblity to call

baseLine.String(k, v, xopbase.StringDataType)

if it wants the value to be logged.

RedactStringFunc is applied only to String(), and Stringer() attributes. It is not applied to Msg(), Msgf(), or Msgs().

The provided xopbase.Line may not be retained beyond the duration of the function call.

type Seed

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

Seed is used to create a Logger. Seed contains the context of the log (trace parent, current trace, etc); the set of base loggers to use; and log settings (like minimum log level).

Seed is used to bridge between parent logs and their sub-spans. The functions that turn Seeds into Loggers are: Request(), which is used when the new logger is a "request" which is a top-level indexed span; and SubSpan(), which is used when the new logger is just a component of a parent Request().

Use Request() for incoming requests from other servers and for jobs processed out of a queue.

Seeds contain a xoptrace.Bundle. If the Trace is not net, then Request() will choose random values for the TraceID and/or SpanID.

func NewSeed

func NewSeed(mods ...SeedModifier) Seed

func (Seed) Bundle

func (seed Seed) Bundle() xoptrace.Bundle

func (Seed) Copy

func (seed Seed) Copy(mods ...SeedModifier) Seed

Copy makes a deep copy of a seed and also randomizes the SpanID.

func (Seed) Request

func (seed Seed) Request(descriptionOrName string) *Logger

Request creates a new top-level span (a request). Use when starting something new, like receiving an http request or starting a cron job.

func (Seed) SourceInfo added in v0.3.0

func (seed Seed) SourceInfo() xopbase.SourceInfo

func (Seed) String added in v0.3.0

func (seed Seed) String() string

func (Seed) SubSpan

func (seed Seed) SubSpan(descriptionOrName string) *Logger

SubSpan creates a new top-level span (a request) but initializes the span/trace data as if it were a subspan. The traceID must already be set. Use this with caution, it is meant for handing off from spans created elsewhere.

type SeedModifier

type SeedModifier func(*Seed)

func CombineSeedModifiers

func CombineSeedModifiers(mods ...SeedModifier) SeedModifier

func WithB3

func WithB3(b bool) SeedModifier

func WithBase

func WithBase(baseLogger xopbase.Logger) SeedModifier

func WithBundle

func WithBundle(bundle xoptrace.Bundle) SeedModifier

WithBundle overrides the span id, the trace id, and also the trace state and baggage. When used inside a reactive function, the override is does not propagate.

func WithConfig

func WithConfig(config Config) SeedModifier

func WithConfigChanges

func WithConfigChanges(mods ...ConfigModifier) SeedModifier

func WithContext

func WithContext(ctx context.Context) SeedModifier

WithContext puts a context into the seed. That context will be passed through to the base layer Request and Seed functions.

func WithFlushDelay

func WithFlushDelay(d time.Duration) SeedModifier

func WithNamespace added in v0.3.0

func WithNamespace(namespace string) SeedModifier

WithNamespace serves to provide informationa about where logs will come from. The best value for the namespace is either the go module name for the overall project or the repository path. If Xop was logging, it should use "github.com/xoplog/xop-go" as the source. The source can cal be versioned. Split on space or dash (eg. "github.com/xoplog/xop-go v1.3.10")

The namespace exists to establish the which semantic conventions are in use for whatever logging follows.

If not specified, namespace will default to xopat.DefaultNamespace

func WithReactive

func WithReactive(f SeedReactiveCallback) SeedModifier

WithReactive provides a callback that is used to modify seeds as they are in the process of sprouting. Just as a seed is being used to create a request of sub-span, all reactive functions will be called. Such functions must return a valid seed. The seed they start with will be valid, so they can simply return that seed.

When WithReactive is called from a SeedReactiveCallback, the new reactive function is only evaluated on descendent seeds.

func WithReactiveReplaced

func WithReactiveReplaced(f SeedReactiveCallback) SeedModifier

WithReactiveReplaced may only be used from within a call to a reactive function. The current reactive function is the one that will be replaced. To remove a reactive function, call WithReactiveReplaced with nil.

func WithSettings

func WithSettings(f func(*LogSettings)) SeedModifier

func WithSource added in v0.3.0

func WithSource(source string) SeedModifier

WithSource specifies the source of the the logs. This should be the program name or the program family if there are a group of related programs.

Versioning is supported.

If not specified, filepath.Base(os.Argv[0]) will be used.

func WithSpan

func WithSpan(spanID [8]byte) SeedModifier

WithSpan overrides the span in the seed. When used inside a reactive function, the override does not propagate.

func WithTrace

func WithTrace(trace xoptrace.Trace) SeedModifier

WithSpan overrides the trance and span in the seed. When used inside a reactive function, the override does not propagate.

func WithoutBase

func WithoutBase(baseLoggerToRemove xopbase.Logger) SeedModifier

type SeedReactiveCallback

type SeedReactiveCallback func(ctx context.Context, seed Seed, nameOrDescription string, isChildSpan bool, now time.Time) []SeedModifier

SeedReactiveCallback is used to modify seeds as they are just sprouting.

type Span

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

func (*Span) Any

func (span *Span) Any(k *xopat.AnyAttribute, v interface{}) *Span

Any adds a key/value attribute to the current Span. The provided value may be copied using github.com/mohae/deepcopy if any of the base loggers hold the value instead of immediately serializing it. While the AnyAttribute has an expectation for the type of the value, that type may or may not be checked depending on the base logger being used. The return value does not need to be used.

func (*Span) AnyImmutable

func (span *Span) AnyImmutable(k *xopat.AnyAttribute, v interface{}) *Span

AnyImmutable adds a key/value attribute to the current Span. The provided value must be immutable. If it is not, then there could be race conditions or the value that ends up logged could be different from the value at the time when AnyImmutible was called.

While the AnyAttribute has an expectation for the type of the value, that type may or may not be checked depending on the base logger being used. The return value does not need to be used.

func (*Span) Bool

func (span *Span) Bool(k *xopat.BoolAttribute, v bool) *Span

Bool adds a bool key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Bundle

func (span *Span) Bundle() xoptrace.Bundle

func (*Span) Duration

func (span *Span) Duration(k *xopat.DurationAttribute, v time.Duration) *Span

should skip Int64 Duration adds a time.Duration key/value attribute to the current Span. The return value does not need to be used.

func (*Span) EmbeddedEnum

func (span *Span) EmbeddedEnum(kv xopat.EmbeddedEnum) *Span

EmbeddedEnum adds a kev/value attribute to the Span. The key and the value are bundled together: the key is derrived from the type of the Enum. Alternatively, use xopat.KeyedEnumAttribute() to create functions to add enum key/value pairs where the key and value are specified separately. See xopconst.SpanType for an example of creating an EmbeddedEnum. The return value does not need to be used.

func (*Span) Enum

func (span *Span) Enum(k *xopat.EnumAttribute, v xopat.Enum) *Span

Enum adds a xopat.Enum key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Float64

func (span *Span) Float64(k *xopat.Float64Attribute, v float64) *Span

Float64 adds a float64 key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Int

func (span *Span) Int(k *xopat.IntAttribute, v int) *Span

Int adds a int key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Int16

func (span *Span) Int16(k *xopat.Int16Attribute, v int16) *Span

Int16 adds a int16 key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Int32

func (span *Span) Int32(k *xopat.Int32Attribute, v int32) *Span

Int32 adds a int32 key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Int64

func (span *Span) Int64(k *xopat.Int64Attribute, v int64) *Span

Int64 adds a int64 key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Int8

func (span *Span) Int8(k *xopat.Int8Attribute, v int8) *Span

Int8 adds a int8 key/value attribute to the current Span. The return value does not need to be used.

func (span *Span) Link(k *xopat.LinkAttribute, v xoptrace.Trace) *Span

Link adds a xoptrace.Trace key/value attribute to the current Span. The return value does not need to be used.

func (*Span) ParentTrace

func (span *Span) ParentTrace() xoptrace.Trace

func (*Span) String

func (span *Span) String(k *xopat.StringAttribute, v string) *Span

String adds a string key/value attribute to the current Span. The return value does not need to be used.

func (*Span) SubSeed added in v0.3.0

func (span *Span) SubSeed(mods ...SeedModifier) Seed

SubSeed provides a copy of the current span's seed, but the spanID is randomized and the Parent set to the now prior Trace

func (*Span) Time

func (span *Span) Time(k *xopat.TimeAttribute, v time.Time) *Span

Time adds a time.Time key/value attribute to the current Span. The return value does not need to be used.

func (*Span) Trace

func (span *Span) Trace() xoptrace.Trace

func (*Span) TraceBaggage

func (span *Span) TraceBaggage() xoptrace.Baggage

func (*Span) TraceState

func (span *Span) TraceState() xoptrace.State

type Sub

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

Sub holds an ephemeral state of a log being tranformed to a new log.

func (Sub) Detach

func (sub Sub) Detach() *Detaching

Detach followed by Fork() or Step() creates a sub-span/logger that is detached from it's parent. A Done() on the parent does not imply Done() on the detached logger.

func (*Sub) Fork

func (sub *Sub) Fork(msg string, mods ...SeedModifier) *Logger

Fork creates a new logger that does not need to be terminated because it is assumed to be done with the current logger is finished. The new logger has its own span.

func (*Sub) Logger added in v0.3.0

func (sub *Sub) Logger() *Logger

Logger creates a new Logger that does not need to be terminated because it is assumed to be done with the current logger is finished. The new logger shares a span with its parent logger. It can have different settings from its parent logger.

func (*Sub) MinLevel

func (sub *Sub) MinLevel(level xopnum.Level) *Sub

MinLevel sets the minimum logging level below which logs will be discarded. The default minimum level comes from DefaultSettings.

func (*Sub) NoPrefill

func (sub *Sub) NoPrefill() *Sub

func (*Sub) PrefillAny

func (sub *Sub) PrefillAny(k xopat.K, v interface{}) *Sub

PrefillAny is used to set a data element that is included on every log line. Values provided with PrefillAny will be copied using https://github.com/mohae/deepcopy 's Copy(). PrefillAny is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called. Redaction is not supported.

func (*Sub) PrefillBool

func (sub *Sub) PrefillBool(k xopat.K, v bool) *Sub

PrefillBool is used to set a data element that is included on every log line. PrefillBool is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillDuration

func (sub *Sub) PrefillDuration(k xopat.K, v time.Duration) *Sub

PrefillDuration is used to set a data element that is included on every log line. PrefillDuration is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillEmbeddedEnum

func (sub *Sub) PrefillEmbeddedEnum(k xopat.EmbeddedEnum) *Sub

PrefillEmbeddedEnum is used to set a data element that is included on every log line. PrefillEmbeddedEnum is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillEnum

func (sub *Sub) PrefillEnum(k *xopat.EnumAttribute, v xopat.Enum) *Sub

PrefillEnum is used to set a data element that is included on every log line. PrefillEnum is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillError

func (sub *Sub) PrefillError(k xopat.K, v error) *Sub

PrefillError is used to set a data element that is included on every log line. Errors will always be formatted with v.Error(). Redaction is not supported.

func (*Sub) PrefillFloat32

func (sub *Sub) PrefillFloat32(k xopat.K, v float32) *Sub

PrefillFloat32 is used to set a data element that is included on every log line. PrefillFloat32 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillFloat64

func (sub *Sub) PrefillFloat64(k xopat.K, v float64) *Sub

PrefillFloat64 is used to set a data element that is included on every log line. PrefillFloat64 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillInt

func (sub *Sub) PrefillInt(k xopat.K, v int) *Sub

PrefillInt is used to set a data element that is included on every log line. PrefillInt is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillInt16

func (sub *Sub) PrefillInt16(k xopat.K, v int16) *Sub

PrefillInt16 is used to set a data element that is included on every log line. PrefillInt16 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillInt32

func (sub *Sub) PrefillInt32(k xopat.K, v int32) *Sub

PrefillInt32 is used to set a data element that is included on every log line. PrefillInt32 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillInt64

func (sub *Sub) PrefillInt64(k xopat.K, v int64) *Sub

PrefillInt64 is used to set a data element that is included on every log line. PrefillInt64 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillInt8

func (sub *Sub) PrefillInt8(k xopat.K, v int8) *Sub

PrefillInt8 is used to set a data element that is included on every log line. PrefillInt8 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillString

func (sub *Sub) PrefillString(k xopat.K, v string) *Sub

PrefillString is used to set a data element that is included on every log line. PrefillString is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillText

func (sub *Sub) PrefillText(m string) *Sub

PrefillText is prepended to any eventual Line.Msg() or Line.Template(). PrefillText will be ignored for Line.Model() and Line.Link().

func (*Sub) PrefillTime

func (sub *Sub) PrefillTime(k xopat.K, v time.Time) *Sub

PrefillTime is used to set a data element that is included on every log line. PrefillTime is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUint

func (sub *Sub) PrefillUint(k xopat.K, v uint) *Sub

PrefillUint is used to set a data element that is included on every log line. PrefillUint is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUint16

func (sub *Sub) PrefillUint16(k xopat.K, v uint16) *Sub

PrefillUint16 is used to set a data element that is included on every log line. PrefillUint16 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUint32

func (sub *Sub) PrefillUint32(k xopat.K, v uint32) *Sub

PrefillUint32 is used to set a data element that is included on every log line. PrefillUint32 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUint64

func (sub *Sub) PrefillUint64(k xopat.K, v uint64) *Sub

PrefillUint64 is used to set a data element that is included on every log line. PrefillUint64 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUint8

func (sub *Sub) PrefillUint8(k xopat.K, v uint8) *Sub

PrefillUint8 is used to set a data element that is included on every log line. PrefillUint8 is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) PrefillUintptr added in v0.3.0

func (sub *Sub) PrefillUintptr(k xopat.K, v uintptr) *Sub

PrefillUintptr is used to set a data element that is included on every log line. PrefillUintptr is not threadsafe with respect to other calls on the same *Sub. Should not be used after Step(), Fork(), or Logger() is called.

func (*Sub) SetRedactAnyFunc

func (sub *Sub) SetRedactAnyFunc(f RedactAnyFunc) *Sub

SetRedactAnyFunc sets a redaction function to be used when Line.Any() is called.

func (*Sub) SetRedactErrorFunc

func (sub *Sub) SetRedactErrorFunc(f RedactErrorFunc) *Sub

SetRedactErrorFunc sets a redaction function to be used when Line.Error() is called.

func (*Sub) SetRedactStringFunc

func (sub *Sub) SetRedactStringFunc(f RedactStringFunc) *Sub

SetRedactStringFunc sets a redaction function to be used when Line.String() is called.

func (*Sub) StackFilenameRewrite added in v0.3.0

func (sub *Sub) StackFilenameRewrite(f func(string) string) *Sub

StackFilenameRewrite is used to rewrite filenames in stack traces. Generally this is used to eliminate path prefixes. An empty return value indicates that the rest of the stack trace should be discarded.

func (*Sub) StackFrames

func (sub *Sub) StackFrames(level xopnum.Level, count int) *Sub

StackFrames sets the number of stack frames to include at a logging level. Levels above the given level will be set to get least this many. Levels below the given level will be set to receive at most this many.

func (*Sub) Step

func (sub *Sub) Step(msg string, mods ...SeedModifier) *Logger

Step creates a new logger that does not need to be terminated -- it represents the continued execution of the current logger but doing something that is different and should be in a fresh span. The expectation is that there is a parent logger that is creating various sub-logs using Step over and over as it does different things.

func (*Sub) SynchronousFlush

func (sub *Sub) SynchronousFlush(b bool) *Sub

SynchronousFlush sets the behavior for any Flush() triggered by a call to Done(). When true, the call to Done() will not return until the Flush() is complete.

func (*Sub) TagLinesWithSpanSequence

func (sub *Sub) TagLinesWithSpanSequence(b bool) *Sub

TagLinesWithSpanSequence controls if the span sequence indicator (see Fork() and Step()) should be included in the prefill data on each line.

Directories

Path Synopsis
tools
Package xopat provides a mechanism to pre-register span attributes.
Package xopat provides a mechanism to pre-register span attributes.
Package xopbase defines the base-level loggers for xop.
Package xopbase defines the base-level loggers for xop.
xopbytes wrapes io.Writer with additional methods useful for wrting logs
xopbytes wrapes io.Writer with additional methods useful for wrting logs
Package xopcon provides a xopbase.Logger that is meant human consumption.
Package xopcon provides a xopbase.Logger that is meant human consumption.
Package xopconsole provides a xopbase.Logger that is partially meant for human consumption.
Package xopconsole provides a xopbase.Logger that is partially meant for human consumption.
xopconst provides pre-registered standard attributes for describing spans
xopconst provides pre-registered standard attributes for describing spans
xopjson is a xop base logger (xopbase.Logger) that encodes in JSON format.
xopjson is a xop base logger (xopbase.Logger) that encodes in JSON format.
xopnum provides constants used across the xop ecosystem
xopnum provides constants used across the xop ecosystem
Package xoprecorder provides an introspective xopbase.Logger.
Package xoprecorder provides an introspective xopbase.Logger.
Package xoptest combines two other base loggers: xopcon and xoprecorder.
Package xoptest combines two other base loggers: xopcon and xoprecorder.
trace is the data structures to describe trace_id and span_id
trace is the data structures to describe trace_id and span_id
Xoputil is a collection of utilities that are useful for writing base loggers (implementing the xopbase.Logger interface) and also potentially helpful interacting with xop.
Xoputil is a collection of utilities that are useful for writing base loggers (implementing the xopbase.Logger interface) and also potentially helpful interacting with xop.

Jump to

Keyboard shortcuts

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