Documentation ¶
Overview ¶
Package otellogrus provides a function to extend structured logs using logrus with the Open Telemetry trace related context.
The github.com/sirupsen/logrus logrus logs are decorated with standard metadata extracted from the trace.SpanContext, a traceID, spanID and additional information is injected into a log.
The initialization uses file level configuration to set defaults for the function to use. SetLogOptions can overwrite the defaults.
When the configuration is done AddTracingContext and AddTracingContextWithAttributes decorate logrus logs with data from the trace context. Adding trace context ata to logs can be achieved by using logrus.WithFields(AddTracingContext(span)).Info("test") for example.
Functions
func SetLogOptions(options ...LogOption) func WithTraceID(traceID string) LogOption func WithSpanID(spanID string) LogOption func WithServiceName(serviceName string) LogOption func WithAttributePrefix(prefix string) LogOption func WithAttributes(attributes ...attribute.KeyValue) LogOption func AddTracingContext(span trace.Span, err ...error) logrus.Fields func AddTracingContextWithAttributes(span trace.Span, attributes []attribute.KeyValue, err ...error) logrus.Fields func WithLevel(level logrus.Level) LoggerOption func WithFormatter(formatter logrus.Formatter) LoggerOption func New(options ...LoggerOption) *Logger func (l Logger) WithTracingContext(span trace.Span, err ...error) *logrus.Entry func (l Logger) WithTracingContextAndAttributes(span trace.Span, attributes []attribute.KeyValue, err ...error) *logrus.Entry
Types
type LogOption func(*logConfig)
Structs
type logConfig struct { attributes []attribute.KeyValue serviceName string traceId string spanId string attributePrefix string } type Logger struct { *logrus.Logger } type loggerConfig struct { formatter *logrus.Formatter level logrus.Level }
import "github.com/vincentfree/opentelemetry/otellogrus"
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddTracingContext ¶
AddTracingContext lets you add the trace context to a structured log
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" ) func main() { tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") logrus.WithFields(otellogrus.AddTracingContext(span)).Info("in case of a success") // or in the case of an error err := errors.New("example error") logrus.WithFields(otellogrus.AddTracingContext(span, err)).Info("in case of a failure") }
Output:
func AddTracingContextWithAttributes ¶
func AddTracingContextWithAttributes(span trace.Span, attributes []attribute.KeyValue, err ...error) logrus.Fields
AddTracingContextWithAttributes lets you add the trace context to a structured log, including attribute.KeyValue's to extend the log
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) func main() { tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") attributes := []attribute.KeyValue{ attribute.String("exampleKey", "exampleValue"), attribute.Bool("isValid", true), } logrus.WithFields(otellogrus.AddTracingContextWithAttributes(span, attributes)).Info("in case of a success") // or in the case of an error err := errors.New("example error") logrus.WithFields(otellogrus.AddTracingContextWithAttributes(span, attributes, err)).Info("in case of a failure") }
Output:
func SetLogOptions ¶
func SetLogOptions(options ...LogOption)
SetLogOptions takes LogOption's and overwrites library defaults
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) func main() { option := otellogrus.WithAttributes(attribute.String("test", "value"), attribute.Bool("isValid", true)) // use of SetLogOptions otellogrus.SetLogOptions(option) // set up tracer tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") logrus.WithFields(otellogrus.AddTracingContext(span)).Info("in case of a success") // or in the case of an error err := errors.New("example error") logrus.WithFields(otellogrus.AddTracingContext(span, err)).Info("in case of a failure") }
Output:
Types ¶
type LogOption ¶
type LogOption func(*logConfig)
LogOption takes a logConfig struct and applies changes. It can be passed to the SetLogOptions function to configure a logConfig struct.
func WithAttributePrefix ¶
WithAttributePrefix updates the default 'trace.attribute' attribute prefix
Example ¶
package main import ( "github.com/vincentfree/opentelemetry/otellogrus" ) func main() { otellogrus.SetLogOptions(otellogrus.WithAttributePrefix("prefix")) // use AddTracingContext or AddTracingContextWithAttributes }
Output:
func WithAttributes ¶
WithAttributes adds global attributes that will be added to all structured logs. attributes have a prefix followed by the key of the attribute.
Example: if the attribute is of type string and the key is: 'http.method' then in the log it uses the default(but over-writable) 'trace.attribute' followed by 'http.method' so the end result is: 'trace.attribute.http.method'
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) func main() { option := otellogrus.WithAttributes(attribute.String("test", "value"), attribute.Bool("isValid", true)) otellogrus.SetLogOptions(option) tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") logrus.WithFields(otellogrus.AddTracingContext(span)).Info("in case of a success") // or in the case of an error err := errors.New("example error") logrus.WithFields(otellogrus.AddTracingContext(span, err)).Info("in case of a failure") }
Output:
func WithServiceName ¶
WithServiceName adds a service name to the field 'service.name' in your structured logs
Example ¶
package main import ( "github.com/vincentfree/opentelemetry/otellogrus" ) func main() { otellogrus.SetLogOptions(otellogrus.WithServiceName("example-service")) // use AddTracingContext or AddTracingContextWithAttributes }
Output:
func WithSpanID ¶
WithSpanID overwrites the default 'spanID' field in the structured logs with your own key
Example ¶
package main import ( "github.com/vincentfree/opentelemetry/otellogrus" ) func main() { otellogrus.SetLogOptions(otellogrus.WithSpanID("span-id")) // use AddTracingContext or AddTracingContextWithAttributes }
Output:
func WithTraceID ¶
WithTraceID overwrites the default 'traceID' field in the structured logs with your own key
Example ¶
package main import ( "github.com/vincentfree/opentelemetry/otellogrus" ) func main() { otellogrus.SetLogOptions(otellogrus.WithTraceID("trace-id")) // use AddTracingContext or AddTracingContextWithAttributes }
Output:
type Logger ¶
func New ¶
func New(options ...LoggerOption) *Logger
New creates a new Logger with given options.
Parameters:
- options (LoggerOption): Variadic configuration options for Logger.
Return:
- A pointer to new Logger.
Example ¶
package main import ( "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" ) func main() { logger := otellogrus.New(otellogrus.WithLevel(logrus.ErrorLevel), otellogrus.WithFormatter(&logrus.JSONFormatter{})) logger.Info("message") }
Output:
func (Logger) WithTracingContext ¶
WithTracingContext is a method on the Logger type. It uses the AddTracingContext helper function to gather tracing context from the given span and error, then creates a logrus.Entry with the context using the WithFields method of the Logger.
The span is of the type trace.Span that provides the tracing information.
A variadic parameter of error values is also provided which can be optionally used. only the first error is actually used, the variadic nature of this parameter is used to make it optional.
It ultimately returns a pointer to a logrus.Entry populated with the tracing context.
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" ) func main() { tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") logger := otellogrus.New(otellogrus.WithLevel(logrus.ErrorLevel), otellogrus.WithFormatter(&logrus.JSONFormatter{})) // the logger returned by the otellogrus lib extends logrus but only does it if you use the logger.WithTracingContext(...) function as the first entry // the function returns a logrus.Entry which has not been extended logger.WithTracingContext(span).Info("example message") err := errors.New("example error") // with error is not used due to WithTracingContext doing the same thing internally logger.WithTracingContext(span, err).Error("example error message") }
Output:
func (Logger) WithTracingContextAndAttributes ¶
func (l Logger) WithTracingContextAndAttributes(span trace.Span, attributes []attribute.KeyValue, err ...error) *logrus.Entry
WithTracingContextAndAttributes is a method on the Logger type. Similar to WithTracingContext, this method uses a helper function (AddTracingContextWithAttributes in this case) to gather tracing context and attributes from the given span and error. It then creates a logrus.Entry with the context and attributes using the WithFields method of the Logger.
The span is of the type trace.Span that provides the tracing information.
Additionally, this method takes an array of attribute.KeyValue pairs (attributes). Each pair contains key-value attribute information that is added to the logging.
Lastly, a variadic parameter of error values is provided which can be optionally used. Despite the parameter being variadic, only the first error is actually used; the variadic nature of this parameter is used to make it optional.
It ultimately returns a pointer to a logrus.Entry populated with the tracing context and attributes.
Example ¶
package main import ( "context" "errors" "github.com/sirupsen/logrus" "github.com/vincentfree/opentelemetry/otellogrus" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" ) func main() { attributes := []attribute.KeyValue{ attribute.String("exampleKey", "exampleValue"), attribute.Bool("isValid", true), } tracer := otel.Tracer("otellogrus/example") _, span := tracer.Start(context.Background(), "example-span") logger := otellogrus.New(otellogrus.WithLevel(logrus.ErrorLevel), otellogrus.WithFormatter(&logrus.JSONFormatter{})) // the logger returned by the otellogrus lib extends logrus but only does it if you use the logger.WithTracingContext(...) function as the first entry // the function returns a logrus.Entry which has not been extended logger.WithTracingContextAndAttributes(span, attributes).Info("example message") err := errors.New("example error") // with error is not used due to WithTracingContextAndAttributes doing the same thing internally logger.WithTracingContextAndAttributes(span, attributes, err).Error("example error message") }
Output:
type LoggerOption ¶
type LoggerOption func(*loggerConfig)
func WithFormatter ¶
func WithFormatter(formatter logrus.Formatter) LoggerOption
WithFormatter sets a formatter. The formatter is used by the Logger.
It receives a logrus.Formatter value as a parameter.
Args:
formatter (logrus.Formatter): The formatter required for logging.
Returns:
LoggerOption: Returns a function which modifies the 'formatter' attribute of a loggerConfig instance.
func WithLevel ¶
func WithLevel(level logrus.Level) LoggerOption
WithLevel sets the log level of the Logger instance.
It receives a logrus.Level value as a parameter.
Args:
level (logrus.Level): The level of logging required.
Returns:
LoggerOption: Returns a function which modifies the 'level' attribute of a loggerConfig instance.