Collecting Zap logs with OpenTelemetry
With OpenTelemetry Zap, you can automatically generate OpenTelemetry events from your logging statements. This can be useful for understanding how your application is behaving in production and diagnosing issues.
OpenTelemetry Zap automatically injects trace and span IDs for each logging statement, allowing you to correlate your logs with other telemetry data from your application.
What is OpenTelemetry?
OpenTelemetry is an open source observability framework hosted by Cloud Native Computing Foundation. It is a merger of OpenCensus and OpenTracing projects.
OpenTelemetry aims to provide a single standard across all types of observability signals such as OpenTemetry logs, distributed tracing, and metrics.
OpenTelemetry specifies how to collect and send telemetry data to backend platforms. With OpenTelemetry, you can instrument your application once and then add or change vendors without changing the instrumentation.
Zap instrumentation
To install otelzap instrumentation:
go get github.com/uptrace/opentelemetry-go-extra/otelzap
Usage
otelzap instrumentation records Zap log messages as events on the existing span from the passed context.Context
. It does not record anything if the context does not contain a span.
You need to create an otelzap.Logger
using this package and pass a context to propagate the active span.
import (
"go.uber.org/zap"
"github.com/uptrace/opentelemetry-go-extra/otelzap"
)
// Wrap zap logger to extend Zap with API that accepts a context.Context.
log := otelzap.New(zap.NewExample())
// And then pass ctx to propagate the span.
log.Ctx(ctx).Error("hello from zap",
zap.Error(errors.New("hello world")),
zap.String("foo", "bar"))
// Alternatively.
log.ErrorContext(ctx, "hello from zap",
zap.Error(errors.New("hello world")),
zap.String("foo", "bar"))
Both variants are fast and don't allocate. See example for details.
Global logger
Just like Zap, otelzap provides a global logger that can be set with otelzap.ReplaceGlobals
:
package main
import (
"go.uber.org/zap"
"github.com/uptrace/opentelemetry-go-extra/otelzap"
)
func main() {
logger := otelzap.New(zap.NewExample())
defer logger.Sync()
undo := otelzap.ReplaceGlobals(logger)
defer undo()
otelzap.L().Info("replaced zap's global loggers")
otelzap.Ctx(context.TODO()).Info("... and with context")
}
Sugared logger
You can also use sugared logger API in a similar way:
log := otelzap.New(zap.NewExample())
sugar := log.Sugar()
sugar.Ctx(ctx).Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.InfowContext(ctx, "failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Ctx(ctx).Infof("Failed to fetch URL: %s", url)
sugar.InfofContext(ctx, "Failed to fetch URL: %s", url)
What is Uptrace?
Uptrace is a distributed tracing tool that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues.
Uptrace comes with an intuitive query builder, rich dashboards, alerting rules with notifications, and integrations for most languages and frameworks.
Uptrace can process billions of spans and metrics on a single server and allows you to monitor your applications at 10x lower cost.
In just a few minutes, you can try Uptrace by visiting the cloud demo (no login required) or running it locally with Docker. The source code is available on GitHub.
What's next?
Next, instrument more operations to get a more detailed picture. Try to prioritize network calls, disk operations, database queries, error and logs.
You can also create your own instrumentations using OpenTelemetry Go Tracing API.