Documentation
¶
Overview ¶
Package log provides a pre-configured slog.Logger that follows GitLab logging conventions: JSON output to stderr, UTC timestamps in RFC 3339 format, and structured logging with slog.
Quick start ¶
logger := log.New()
logger.Info("server started", slog.String("addr", ":8080"))
New returns a logger with sensible defaults. Use NewWithConfig to customise the output writer, format, or log level:
logger := log.NewWithConfig(&log.Config{
UseTextFormat: true,
})
Log level ¶
The minimum log level is controlled by the GITLAB_LOG_LEVEL environment variable. Supported values are DEBUG, INFO, WARN, and ERROR (case-insensitive). When unset or invalid, defaults to INFO. Override programmatically via [Config.LogLevel].
Structured logging ¶
Use slog.Logger's built-in [With] method to attach structured attributes to a logger. This is the canonical pattern for propagating request-scoped fields throughout a request lifecycle:
logger := log.New()
enriched := logger.With(
slog.String(fields.CorrelationID, corrID),
slog.String(fields.GitLabUserName, username),
)
enriched.Info("request completed")
For storing and retrieving loggers from context, use WithLogger and FromContext:
ctx = log.WithLogger(ctx, logger) logger := log.FromContext(ctx)
File output ¶
NewWithFile creates a logger that writes to a file. If the file cannot be opened, it gracefully degrades to stderr and returns an error, allowing the caller to decide how to proceed without blocking application startup.
Example ¶
Example shows basic logger creation and usage. New() produces a JSON logger writing to stderr at INFO level. The log level can be overridden at runtime with the GITLAB_LOG_LEVEL environment variable.
package main
import (
"log/slog"
"gitlab.com/gitlab-org/labkit/v2/log"
)
func main() {
logger := log.New()
logger.Info("service started", slog.String("addr", ":8080"))
}
Output:
Index ¶
- Constants
- func ContentType(ct string) slog.Attr
- func CorrelationID(id string) slog.Attr
- func DurationS(d time.Duration) slog.Attr
- func Error(err error) slog.Attr
- func ErrorMessage(msg string) slog.Attr
- func ErrorType(errType string) slog.Attr
- func FromContext(ctx context.Context) *slog.Logger
- func GitLabUserID(id int) slog.Attr
- func GitLabUserName(name string) slog.Attr
- func HTTPHost(host string) slog.Attr
- func HTTPMethod(method string) slog.Attr
- func HTTPProto(proto string) slog.Attr
- func HTTPReferrer(referrer string) slog.Attr
- func HTTPStatusCode(code int) slog.Attr
- func HTTPURI(uri string) slog.Attr
- func HTTPURL(url string) slog.Attr
- func HTTPUserAgent(ua string) slog.Attr
- func New() *slog.Logger
- func NewWithConfig(cfg *Config) *slog.Logger
- func NewWithFile(filePath string, cfg *Config) (*slog.Logger, io.Closer, error)
- func RemoteAddr(addr string) slog.Attr
- func RemoteIP(ip string) slog.Attr
- func TCPAddress(addr string) slog.Attr
- func TTFBS(d time.Duration) slog.Attr
- func WithLogger(ctx context.Context, logger *slog.Logger) context.Context
- func WrittenBytes(n int64) slog.Attr
- type Config
- type TimeFunc
Examples ¶
Constants ¶
const GitLabLogFormatEnvVar = "GITLAB_LOG_FORMAT"
GitLabLogFormatEnvVar is the environment variable used to control the log output format. Supported values are "json" (default) and "text".
const GitLabLogLevelEnvVar = "GITLAB_LOG_LEVEL"
GitLabLogLevelEnvVar is the environment variable used to control the minimum log level. Supported values are "DEBUG", "INFO", "WARN", and "ERROR" (case-insensitive). Defaults to "INFO" if unset or invalid.
const GitLabLogTimezoneEnvVar = "GITLAB_LOG_TIMEZONE"
GitLabLogTimezoneEnvVar is the environment variable used to control the timezone for log timestamps. Supported values are IANA timezone names (e.g., "UTC", "America/New_York", "Europe/London"). Defaults to "UTC" if unset or invalid.
Variables ¶
This section is empty.
Functions ¶
func ContentType ¶
ContentType returns an slog.Attr for the content_type field.
func CorrelationID ¶
CorrelationID returns an slog.Attr for the correlation_id field.
func DurationS ¶
DurationS returns an slog.Attr for the duration_s field. The duration is converted to seconds automatically.
func Error ¶
Error returns an slog.Attr for the error_message field. The error message is evaluated lazily: err.Error() is only called if the log record is actually handled (i.e. the log level is enabled). This avoids unnecessary work when the log level is below the threshold. Use this in preference to ErrorMessage(err.Error()).
Example ¶
ExampleError shows the lazy error helper. The error string is only evaluated if the log level is enabled, avoiding unnecessary allocation on hot paths.
package main
import (
"context"
"errors"
"log/slog"
"gitlab.com/gitlab-org/labkit/v2/log"
)
func main() {
logger := log.New()
err := errors.New("connection refused")
logger.LogAttrs(context.Background(), slog.LevelError, "database unreachable",
log.Error(err),
)
}
Output:
func ErrorMessage ¶
ErrorMessage returns an slog.Attr for the error_message field.
func FromContext ¶
FromContext retrieves a logger from context. Panics if no logger was stored.
func GitLabUserID ¶
GitLabUserID returns an slog.Attr for the gl_user_id field.
func GitLabUserName ¶
GitLabUserName returns an slog.Attr for the gl_user_name field.
func HTTPMethod ¶
HTTPMethod returns an slog.Attr for the method field.
func HTTPReferrer ¶
HTTPReferrer returns an slog.Attr for the referrer field. The referrer should have sensitive query parameters masked before passing.
func HTTPStatusCode ¶
HTTPStatusCode returns an slog.Attr for the status field.
func HTTPURI ¶
HTTPURI returns an slog.Attr for the uri field. The URI should have sensitive query parameters masked before passing.
func HTTPUserAgent ¶
HTTPUserAgent returns an slog.Attr for the user_agent field.
func New ¶
New - a handy wrapper that configures the slog.Logger in a consistent fashion. Engineers should always default to using this constructor to ensure that they can take advantage of future global enhancements to our logging setup.
func NewWithConfig ¶
NewWithConfig - a constructor that allows you to overwrite some of the core constructs within the Logger for your own nefarious purposes.
Example ¶
ExampleNewWithConfig shows how to create a human-readable text logger at DEBUG level — useful during local development.
package main
import (
"log/slog"
"gitlab.com/gitlab-org/labkit/v2/log"
)
func main() {
level := slog.LevelDebug
logger := log.NewWithConfig(&log.Config{
UseTextFormat: true,
LogLevel: &level,
})
logger.Debug("debug logging enabled")
_ = logger
}
Output:
func NewWithFile ¶
NewWithFile creates a logger writing to a file. Caller is responsible for closing the returned file. Should there be an error with the opening of the filePath this will gracefully degrade and provide a Stderr logger alongside an error. This allows the consumer to decide how they wish to proceed rather than outright blocking application startup.
func RemoteAddr ¶
RemoteAddr returns an slog.Attr for the remote_addr field.
func TCPAddress ¶
TCPAddress returns an slog.Attr for the tcp_address field.
func TTFBS ¶
TTFBS returns an slog.Attr for the ttfb_s field. The duration is converted to seconds automatically.
func WithLogger ¶
WithLogger stores a logger in context.
Example ¶
ExampleWithLogger demonstrates the canonical logging pattern: create a logger with request-scoped fields once and reuse it for all log lines, without repeating them at each call site.
package main
import (
"log/slog"
"gitlab.com/gitlab-org/labkit/v2/log"
)
func main() {
logger := log.New()
// Create an enriched logger with request-scoped fields
enriched := logger.With(
log.CorrelationID("req-abc-123"),
log.GitLabUserID(42),
)
// correlation_id and gl_user_id are included on every line from this logger
enriched.Info("project created", slog.Int("project_id", 99))
enriched.Info("webhook dispatched", slog.Int("project_id", 99))
}
Output:
func WrittenBytes ¶
WrittenBytes returns an slog.Attr for the written_bytes field.
Types ¶
type Config ¶
type Config struct {
// Writer - a lower level construct that allows
// engineers to have finer-grained control over
// how and where logs are written to file.
Writer io.Writer
// UseTextFormat - set this to true if you require
// text formatted logs.
UseTextFormat bool
// Clock - allows the consumer to provide their own
// TimeFunc that is used to provide the timestamp when
// emitting logs.
// The logger defaults to UTC to try and ensure
// consistency across our services.
Clock TimeFunc
// Location - the timezone location for log timestamps.
// Defaults to UTC. Can be overridden by passing a specific location
// or via the GITLAB_LOG_TIMEZONE environment variable.
// When nil, the location from the environment variable is used,
// falling back to UTC if unset or invalid.
Location *time.Location
// LogLevel - represents the minimum log level that should be output by
// the logger. When nil, the value of GITLAB_LOG_LEVEL is used, falling
// back to slog.LevelInfo if the environment variable is unset or invalid.
// Set this explicitly to override the environment variable.
LogLevel *slog.Level
}
Config holds the configuration for creating a new logger.