How to instrument your application with OTel logs (Go)
Logs are the quickest way to get insights into your application. With OTel standardization, users can easily collate, correlate and visualize telemetry data.
For this demo, we are choosing zap library by Uber and stdout as the exporter. You can also export your logs to an OTLP endpoint.
1. Initialize a LoggerProvider
go get go.opentelemetry.io/otel \
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp \
go.opentelemetry.io/otel/sdk \
go.opentelemetry.io/otel/sdk/log
// from original OTel documentation
package main
// omitted imports here
func main() {
ctx := context.Background()
// Create resource.
res, err := newResource()
if err != nil {
panic(err)
}
// Create a logger provider.
// You can pass this instance directly when creating bridges.
loggerProvider, err := newLoggerProvider(ctx, res)
if err != nil {
panic(err)
}
// Handle shutdown properly so nothing leaks.
defer func() {
if err := loggerProvider.Shutdown(ctx); err != nil {
fmt.Println(err)
}
}()
// Register as global logger provider so that it can be accessed global.LoggerProvider.
// Most log bridges use the global logger provider as default.
// If the global logger provider is not set then a no-op implementation
// is used, which fails to generate data.
global.SetLoggerProvider(loggerProvider)
}
func newResource() (*resource.Resource, error) {
return resource.Merge(resource.Default(),
resource.NewWithAttributes(semconv.SchemaURL,
semconv.ServiceName("my-service"),
semconv.ServiceVersion("0.1.0"),
))
}
func newLoggerProvider(ctx context.Context, res *resource.Resource) (*log.LoggerProvider, error) {
exporter, err := stdoutlog.New(ctx)
if err != nil {
return nil, err
}
processor := log.NewBatchProcessor(exporter)
provider := log.NewLoggerProvider(
log.WithResource(res),
log.WithProcessor(processor),
)
return provider, nil
}
2. Import otelzap
go get "go.opentelemetry.io/contrib/bridges/otelzap"
Initialize the logger
// Add this logic to the main function above
func main(){
// This will use globally set LoggerProvider
// If not set, it uses no-op implementation and fails to generate data
logger := zap.New(otelzap.NewCore("my/pkg/name")
// You can now use your logger in your code.
logger.Info("something really cool")
// Add context for trace correlation
logger.Info("Add trace context", zap.Reflect("ctx", ctx.Background()))
}
This is how you can set up logging with OTel and zap. I hope you find this useful.