or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

fields.mdindex.mdintegrations.mdlogger.mdtesting.mdzapcore.md
tile.json

integrations.mddocs/

Third-Party Integrations API

This document covers integration packages for using zap with gRPC and standard library IO operations.

gRPC Integration (zapgrpc)

The zapgrpc package provides a logger compatible with gRPC's logging interface.

Package Import

import "go.uber.org/zap/zapgrpc"

Logger Type

The zapgrpc Logger adapts zap's Logger to be compatible with grpclog.LoggerV2.

type Logger struct {
    // Has unexported fields
}

Logger Constructor

func NewLogger(l *zap.Logger, options ...Option) *Logger

Creates a new gRPC-compatible logger from a zap Logger.

Logger Methods

All methods implement the grpclog.LoggerV2 interface:

// Info-level logging
func (l *Logger) Info(args ...interface{})
func (l *Logger) Infof(format string, args ...interface{})
func (l *Logger) Infoln(args ...interface{})

// Warning-level logging
func (l *Logger) Warning(args ...interface{})
func (l *Logger) Warningf(format string, args ...interface{})
func (l *Logger) Warningln(args ...interface{})

// Error-level logging
func (l *Logger) Error(args ...interface{})
func (l *Logger) Errorf(format string, args ...interface{})
func (l *Logger) Errorln(args ...interface{})

// Fatal-level logging
func (l *Logger) Fatal(args ...interface{})
func (l *Logger) Fatalf(format string, args ...interface{})
func (l *Logger) Fatalln(args ...interface{})

// Verbosity check
func (l *Logger) V(level int) bool

Deprecated Methods

// Deprecated: use Info
func (l *Logger) Print(args ...interface{})

// Deprecated: use Infof
func (l *Logger) Printf(format string, args ...interface{})

// Deprecated: use Infoln
func (l *Logger) Println(args ...interface{})

Options

type Option interface {
    // Has unexported methods
}

// Deprecated: configures Logger to print at zap.DebugLevel
func WithDebug() Option

zapgrpc Usage Examples

Basic gRPC Logger Setup

import (
    "go.uber.org/zap"
    "go.uber.org/zap/zapgrpc"
    "google.golang.org/grpc/grpclog"
)

// Create zap logger
logger, _ := zap.NewProduction()

// Create gRPC logger from zap
grpcLogger := zapgrpc.NewLogger(logger)

// Set as global gRPC logger
grpclog.SetLoggerV2(grpcLogger)

// Now gRPC will use zap for all its logging

Custom gRPC Logger with Options

// Create zap logger at debug level for verbose gRPC logs
logger, _ := zap.NewDevelopment()

// Create gRPC logger
grpcLogger := zapgrpc.NewLogger(logger.Named("grpc"))

grpclog.SetLoggerV2(grpcLogger)

Structured gRPC Logging

// Create structured logger with context
logger, _ := zap.NewProduction()
contextLogger := logger.With(
    zap.String("service", "api"),
    zap.String("version", "v1.0"),
)

// gRPC will include context in all logs
grpcLogger := zapgrpc.NewLogger(contextLogger)
grpclog.SetLoggerV2(grpcLogger)

Per-Server gRPC Logger

// Create different loggers for different gRPC servers
prodLogger, _ := zap.NewProduction()
grpcProdLogger := zapgrpc.NewLogger(prodLogger.Named("grpc.prod"))

adminLogger, _ := zap.NewDevelopment()
grpcAdminLogger := zapgrpc.NewLogger(adminLogger.Named("grpc.admin"))

// Use different loggers for different servers
prodServer := grpc.NewServer(
    grpc.UnaryInterceptor(loggingInterceptor(grpcProdLogger)),
)
adminServer := grpc.NewServer(
    grpc.UnaryInterceptor(loggingInterceptor(grpcAdminLogger)),
)

IO Integration (zapio)

The zapio package provides tools for using zap with standard library IO operations.

Package Import

import "go.uber.org/zap/zapio"

Writer Type

Writer is an io.Writer that writes to a zap Logger, splitting output on line boundaries.

type Writer struct {
    Log   *zap.Logger
    Level zapcore.Level
    // Has unexported fields
}

Writer Methods

// Write bytes to logger (implements io.Writer)
func (w *Writer) Write(bs []byte) (n int, err error)

// Sync flushes buffered data to logger without waiting for newline
func (w *Writer) Sync() error

// Close flushes buffered data and closes writer
func (w *Writer) Close() error

zapio Usage Examples

Redirect Standard Library Logging

import (
    "log"
    "go.uber.org/zap"
    "go.uber.org/zap/zapio"
)

// Create zap logger
zapLogger, _ := zap.NewProduction()

// Create Writer at Info level
writer := &zapio.Writer{
    Log:   zapLogger,
    Level: zapcore.InfoLevel,
}
defer writer.Close()

// Set as output for standard library logger
log.SetOutput(writer)

// Standard library log calls now go through zap
log.Println("This message goes through zap")

Capture External Library Output

// Many libraries write to io.Writer
// Capture their output in structured logs

zapLogger, _ := zap.NewProduction()
logWriter := &zapio.Writer{
    Log:   zapLogger.Named("external.lib"),
    Level: zapcore.WarnLevel,
}
defer logWriter.Close()

// Pass to library expecting io.Writer
externalLib.SetOutput(logWriter)

// Library's output appears in zap logs

Multi-Level Writers

zapLogger, _ := zap.NewProduction()

// Create writers at different levels
infoWriter := &zapio.Writer{
    Log:   zapLogger,
    Level: zapcore.InfoLevel,
}

errorWriter := &zapio.Writer{
    Log:   zapLogger,
    Level: zapcore.ErrorLevel,
}

// Use appropriate writer based on context
cmd := exec.Command("some-command")
cmd.Stdout = infoWriter
cmd.Stderr = errorWriter

// Command output logged at appropriate levels
cmd.Run()

Buffer Management

// Writer buffers until newline or explicit flush

writer := &zapio.Writer{
    Log:   logger,
    Level: zapcore.InfoLevel,
}

// These writes are buffered
writer.Write([]byte("partial "))
writer.Write([]byte("line "))

// Force flush without newline
writer.Sync()

// Or flush on close
writer.Close()

Using with os/exec

import (
    "os/exec"
    "go.uber.org/zap"
    "go.uber.org/zap/zapio"
)

logger, _ := zap.NewProduction()

// Create writers for command output
stdoutWriter := &zapio.Writer{
    Log:   logger.Named("cmd.stdout"),
    Level: zapcore.InfoLevel,
}
defer stdoutWriter.Close()

stderrWriter := &zapio.Writer{
    Log:   logger.Named("cmd.stderr"),
    Level: zapcore.ErrorLevel,
}
defer stderrWriter.Close()

// Run command with logging
cmd := exec.Command("some-command", "arg1", "arg2")
cmd.Stdout = stdoutWriter
cmd.Stderr = stderrWriter

if err := cmd.Run(); err != nil {
    logger.Error("command failed", zap.Error(err))
}

// Command output appears in structured logs

Integration with HTTP Servers

import (
    "net/http"
    "go.uber.org/zap"
    "go.uber.org/zap/zapio"
)

logger, _ := zap.NewProduction()

// Log HTTP server errors
errorWriter := &zapio.Writer{
    Log:   logger.Named("http.server"),
    Level: zapcore.ErrorLevel,
}

server := &http.Server{
    Addr:     ":8080",
    ErrorLog: log.New(errorWriter, "", 0),
}

// Server errors logged through zap
server.ListenAndServe()

Custom Line Handling

// Writer splits on newlines by default
// For different behavior, wrap in custom writer

type CustomWriter struct {
    writer *zapio.Writer
}

func (cw *CustomWriter) Write(p []byte) (n int, err error) {
    // Custom processing before writing
    processed := processLines(p)
    return cw.writer.Write(processed)
}

zapLogger, _ := zap.NewProduction()
baseWriter := &zapio.Writer{
    Log:   zapLogger,
    Level: zapcore.InfoLevel,
}

customWriter := &CustomWriter{writer: baseWriter}
// Use customWriter where io.Writer is needed

Integration Best Practices

gRPC Integration

  1. Use named loggers: Create separate named loggers for gRPC to distinguish gRPC logs from application logs
  2. Control verbosity: gRPC can be verbose; use appropriate log levels
  3. Add context: Use With() to add service context to gRPC loggers
  4. Per-service loggers: Use different loggers for different gRPC services

IO Integration

  1. Always close: Call Close() or defer close on zapio.Writers to flush buffers
  2. Sync for completeness: Call Sync() when you need to ensure partial lines are logged
  3. Named loggers: Use named loggers to identify the source of IO logs
  4. Appropriate levels: Choose levels that match the importance of the IO source
  5. Error handling: Remember that Write() can return errors; handle appropriately

Performance Considerations

  1. zapio.Writer buffers: Each Writer maintains a buffer; this is efficient but means logs may be delayed until newline
  2. gRPC logging overhead: gRPC can generate many logs; consider sampling or filtering in production
  3. Writer lifecycle: Create Writers once and reuse them rather than creating new Writers for each operation