diff --git a/README.md b/README.md index 3fc0dc4a..b83ae159 100644 --- a/README.md +++ b/README.md @@ -755,6 +755,8 @@ Log a static string, without any context or `printf`-style templating: ## Caveats +### Field duplication + Note that zerolog does no de-duplication of fields. Using the same key multiple times creates multiple keys in final JSON: ```go @@ -766,3 +768,19 @@ logger.Info(). ``` In this case, many consumers will take the last value, but this is not guaranteed; check yours if in doubt. + +### Concurrency safety + +Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger: + +```go +func handler(w http.ResponseWriter, r *http.Request) { + // Create a child logger for concurrency safety + logger := log.Logger.With().Logger() + + // Add context fields, for example User-Agent from HTTP headers + logger.UpdateContext(func(c zerolog.Context) zerolog.Context { + ... + }) +} +``` diff --git a/log.go b/log.go index 7c7c6a20..e7b5126e 100644 --- a/log.go +++ b/log.go @@ -84,6 +84,8 @@ // // # Caveats // +// Field duplication: +// // There is no fields deduplication out-of-the-box. // Using the same key multiple times creates new key in final JSON each time. // @@ -95,6 +97,20 @@ // // In this case, many consumers will take the last value, // but this is not guaranteed; check yours if in doubt. +// +// Concurrency safety: +// +// Be careful when calling UpdateContext. It is not concurrency safe. Use the With method to create a child logger: +// +// func handler(w http.ResponseWriter, r *http.Request) { +// // Create a child logger for concurrency safety +// logger := log.Logger.With().Logger() +// +// // Add context fields, for example User-Agent from HTTP headers +// logger.UpdateContext(func(c zerolog.Context) zerolog.Context { +// ... +// }) +// } package zerolog import ( @@ -276,7 +292,8 @@ func (l Logger) With() Context { // UpdateContext updates the internal logger's context. // -// Use this method with caution. If unsure, prefer the With method. +// Caution: This method is not concurrency safe. +// Use the With method to create a child logger before modifying the context from concurrent goroutines. func (l *Logger) UpdateContext(update func(c Context) Context) { if l == disabledLogger { return