logger

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2025 License: Apache-2.0 Imports: 4 Imported by: 4

README

Kart Logger

Go Version License Go Report Card

高性能、统一接口的 Go 日志库,支持智能 OTLP 配置、多源配置管理,以及跨框架的统一日志记录。

✨ 核心特性

  • 🚀 双引擎架构: 同时支持 Zap (高性能) 和 Slog (标准库),统一接口,透明切换
  • 📊 字段标准化: 确保不同引擎输出完全一致的日志格式和字段名
  • 🔧 智能 OTLP 配置: 基于端点自动启用,消除冗余配置,支持多种后端
  • ⚙️ 多源配置管理: 环境变量、配置文件、API 配置的智能冲突处理
  • 🔄 动态配置重载: 文件监控、信号处理、API 触发的运行时配置更新
  • 🌐 框架集成: 开箱即用的 Gin、Echo、GORM、Kratos 等框架适配
  • 🎯 三种调用风格: 支持简单参数、Printf 格式化、结构化键值对三种日志方式
  • 📈 性能优化: Zap 引擎支持零分配高性能日志记录
  • 🔍 可观测性: 完整的分布式追踪、上下文传递和 OpenTelemetry 集成

🚀 快速开始

安装
go get github.com/kart-io/logger
最简示例
package main

import "github.com/kart-io/logger"

func main() {
    // 使用默认配置 (Slog 引擎, INFO 级别, JSON 格式)
    logger.Info("Hello, World!")

    // 结构化日志记录
    logger.Infow("用户登录成功",
        "user_id", "12345",
        "ip", "192.168.1.100",
        "duration", "200ms")
}
自定义配置
package main

import (
    "github.com/kart-io/logger"
    "github.com/kart-io/logger/option"
)

func main() {
    // 创建高性能 Zap 日志器
    opt := &option.LogOption{
        Engine: "zap",           // 使用 Zap 引擎
        Level:  "debug",         // 调试级别
        Format: "json",          // JSON 格式
        OutputPaths: []string{
            "stdout",            // 控制台输出
            "/var/log/app.log",  // 文件输出
        },
        // 自动启用 OTLP (智能配置)
        OTLPEndpoint: "http://localhost:4317",
    }

    // 添加初始字段(会自动包含在每个日志条目中)
    opt.WithInitialFields(map[string]interface{}{
        "service.name":    "my-service",
        "service.version": "v1.0.0",
        "environment":     "production",
    }).AddInitialField("instance_id", "web-001")

    coreLogger, err := logger.New(opt)
    if err != nil {
        panic(err)
    }

    // 三种调用风格(所有日志都会包含上面设置的初始字段)
    coreLogger.Info("简单消息")
    coreLogger.Infof("格式化消息: %s", "hello")
    coreLogger.Infow("结构化消息", "key", "value")
}

📊 三种调用风格

1. 简单参数风格
logger.Debug("调试消息", "额外信息")
logger.Info("信息消息")
logger.Warn("警告消息")
logger.Error("错误消息")
2. Printf 格式化风格
logger.Debugf("用户 %s 执行 %s 操作", userName, action)
logger.Infof("处理了 %d 个请求,耗时 %v", count, duration)
logger.Errorf("连接 %s:%d 失败: %v", host, port, err)
3. 结构化风格 (推荐)
logger.Debugw("API 请求开始",
    "method", "POST",
    "path", "/api/users",
    "user_id", userID)

logger.Infow("数据库查询完成",
    "table", "users",
    "duration", duration.Milliseconds(),
    "rows", count)

logger.Errorw("支付处理失败",
    "order_id", orderID,
    "error", err.Error(),
    "amount", 99.99)

🏷️ 初始字段管理 (InitialFields)

InitialFields 是一个强大的功能,允许你在创建日志器时设置一组字段,这些字段会自动包含在每个日志条目中,无需重复添加。

基础用法
import "github.com/kart-io/logger/option"

// 创建配置并添加初始字段
opt := option.DefaultLogOption()

// 方法1: 批量添加字段
opt.WithInitialFields(map[string]interface{}{
    "service.name":    "user-api",
    "service.version": "v2.1.0",
    "environment":     "production",
})

// 方法2: 逐个添加字段(支持链式调用)
opt.AddInitialField("datacenter", "us-west-2").
    AddInitialField("instance_id", "web-003").
    AddInitialField("team", "platform")

// 方法3: 混合使用
opt.WithInitialFields(map[string]interface{}{
    "project": "e-commerce",
    "component": "payment",
}).AddInitialField("build_id", "build-12345")

logger, err := logger.New(opt)
自动包含示例
// 设置初始字段
opt := option.DefaultLogOption()
opt.WithInitialFields(map[string]interface{}{
    "service.name": "payment-service",
    "version": "v1.0.0",
    "region": "us-east-1",
})

logger, _ := logger.New(opt)

// 所有日志都会自动包含初始字段
logger.Info("服务启动")
// 输出: {"time":"...", "level":"info", "msg":"服务启动", "service.name":"payment-service", "version":"v1.0.0", "region":"us-east-1", ...}

logger.Infow("处理支付请求", 
    "order_id", "ord-123", 
    "amount", 99.99)
// 输出: {"time":"...", "level":"info", "msg":"处理支付请求", "service.name":"payment-service", "version":"v1.0.0", "region":"us-east-1", "order_id":"ord-123", "amount":99.99, ...}
字段优先级

InitialFields 具有明确的优先级规则:

opt := option.DefaultLogOption()
opt.WithInitialFields(map[string]interface{}{
    "service.name": "original-service",
    "environment": "production",
})

logger, _ := logger.New(opt)

// With() 方法的字段可以覆盖 InitialFields
childLogger := logger.With("service.name", "child-service")

// 当前日志调用的字段具有最高优先级
childLogger.Infow("测试优先级",
    "service.name", "current-call-service",
    "additional", "data")

// 最终优先级: 当前调用 > With() 方法 > InitialFields
// 输出中 service.name 将是 "current-call-service"
实用场景

1. 微服务标识

opt.WithInitialFields(map[string]interface{}{
    "service.name":    "user-service",
    "service.version": "v1.2.3", 
    "service.instance": os.Getenv("HOSTNAME"),
})

2. 部署环境信息

opt.WithInitialFields(map[string]interface{}{
    "environment": "production",
    "datacenter":  "us-west-2",
    "cluster":     "production-cluster",
    "namespace":   "default",
})

3. 构建和版本信息

opt.WithInitialFields(map[string]interface{}{
    "build_date":   "2023-12-01T10:30:00Z",
    "git_commit":   "abc123def456",
    "git_branch":   "main",
    "build_number": "1234",
})
获取已配置字段
// 获取所有初始字段(返回副本,安全访问)
fields := opt.GetInitialFields()
for key, value := range fields {
    fmt.Printf("%s: %v\n", key, value)
}
⚠️ 注意事项
  1. OTLP 兼容: InitialFields 会自动传递给 OTLP 导出器,确保分布式追踪中的服务标识正确
  2. 内存效率: 字段在日志器创建时设置,不会在每次日志调用时复制
  3. 类型安全: 支持任意类型的值,会在输出时自动序列化
  4. 不可变性: GetInitialFields() 返回副本,防止意外修改

🏗️ 项目架构

包结构图
github.com/kart-io/logger/
├── core/           # 核心接口定义 (Logger, Level)
├── engines/        # 双引擎实现
│   ├── slog/       # Go 标准库 slog 引擎
│   └── zap/        # Uber Zap 高性能引擎
├── factory/        # 工厂模式,动态创建日志器
├── option/         # 配置选项和验证
├── fields/         # 字段标准化系统
├── otlp/           # OpenTelemetry 集成
├── reload/         # 动态配置重载
├── integrations/   # 框架集成适配器
│   ├── gorm/       # GORM ORM 集成
│   └── kratos/     # Kratos 微服务框架集成
├── errors/         # 错误处理和恢复
└── example/        # 12+ 完整使用示例
系统设计图
graph TB
    %% 用户层
    subgraph "用户接口层"
        APP[应用程序]
        CLI[命令行工具]
        WEB[Web框架]
    end

    %% 核心层
    subgraph "核心接口层"
        CORE[core.Logger 统一接口]
        LEVEL[core.Level 日志级别]
    end

    %% 配置层
    subgraph "配置管理层"
        OPT[option.LogOption 配置结构]
        VALID[配置验证和智能默认值]
        RELOAD[reload.ConfigReloader 动态重载]
    end

    %% 工厂层
    subgraph "工厂层"
        FACTORY[factory.LoggerFactory]
        CREATE[动态引擎创建]
    end

    %% 引擎层
    subgraph "双引擎实现层"
        SLOG[engines/slog 标准库引擎]
        ZAP[engines/zap 高性能引擎]
    end

    %% 标准化层
    subgraph "字段标准化层"
        FIELDS[fields.StandardEncoder]
        UNIFIED[统一字段格式]
    end

    %% 集成层
    subgraph "框架集成层"
        GORM[integrations/gorm]
        KRATOS[integrations/kratos]
        MIDDLEWARE[Web中间件]
    end

    %% 输出层
    subgraph "输出处理层"
        CONSOLE[控制台输出]
        FILE[文件输出]
        OTLP[OTLP导出器]
    end

    %% 可观测性后端
    subgraph "可观测性后端"
        JAEGER[Jaeger]
        VICTORIA[VictoriaLogs]
        OTEL[OpenTelemetry Collector]
    end

    %% 连接关系
    APP --> CORE
    CLI --> OPT
    WEB --> MIDDLEWARE

    CORE --> FACTORY
    OPT --> VALID
    VALID --> FACTORY
    RELOAD --> FACTORY

    FACTORY --> CREATE
    CREATE --> SLOG
    CREATE --> ZAP

    SLOG --> FIELDS
    ZAP --> FIELDS
    FIELDS --> UNIFIED

    UNIFIED --> CONSOLE
    UNIFIED --> FILE
    UNIFIED --> OTLP

    GORM --> CORE
    KRATOS --> CORE
    MIDDLEWARE --> CORE

    OTLP --> JAEGER
    OTLP --> VICTORIA
    OTLP --> OTEL

    %% 样式
    classDef userLayer fill:#e1f5fe
    classDef coreLayer fill:#f3e5f5
    classDef configLayer fill:#e8f5e8
    classDef factoryLayer fill:#fff3e0
    classDef engineLayer fill:#fce4ec
    classDef integrationLayer fill:#e0f2f1
    classDef outputLayer fill:#f1f8e9
    classDef backendLayer fill:#e3f2fd

    class APP,CLI,WEB userLayer
    class CORE,LEVEL coreLayer
    class OPT,VALID,RELOAD configLayer
    class FACTORY,CREATE factoryLayer
    class SLOG,ZAP,FIELDS,UNIFIED engineLayer
    class GORM,KRATOS,MIDDLEWARE integrationLayer
    class CONSOLE,FILE,OTLP outputLayer
    class JAEGER,VICTORIA,OTEL backendLayer
配置优先级流程图
graph TD
    START([配置加载开始])

    %% 配置源
    ENV[环境变量]
    API[HTTP API]
    CENTER[配置中心]
    FILE[配置文件]
    DEFAULT[系统默认值]

    %% 处理逻辑
    MERGE[配置合并处理器]
    CONFLICT[冲突解决算法]
    OTLP_AUTO[OTLP智能检测]
    VALIDATE[配置验证]

    %% 结果
    FINAL[最终配置]
    LOGGER[日志器实例]

    START --> ENV
    START --> API
    START --> CENTER
    START --> FILE
    START --> DEFAULT

    ENV --> MERGE
    API --> MERGE
    CENTER --> MERGE
    FILE --> MERGE
    DEFAULT --> MERGE

    MERGE --> CONFLICT
    CONFLICT --> OTLP_AUTO
    OTLP_AUTO --> VALIDATE
    VALIDATE --> FINAL
    FINAL --> LOGGER

    %% 优先级标注
    ENV -.->|优先级: 1| MERGE
    API -.->|优先级: 2| MERGE
    CENTER -.->|优先级: 3| MERGE
    FILE -.->|优先级: 4| MERGE
    DEFAULT -.->|优先级: 5| MERGE

    %% 样式
    classDef highPriority fill:#ffcdd2
    classDef mediumPriority fill:#fff9c4
    classDef lowPriority fill:#e8f5e8
    classDef processNode fill:#e1f5fe
    classDef resultNode fill:#f3e5f5

    class ENV highPriority
    class API,CENTER mediumPriority
    class FILE,DEFAULT lowPriority
    class MERGE,CONFLICT,OTLP_AUTO,VALIDATE processNode
    class FINAL,LOGGER resultNode

🎯 核心概念

双引擎架构设计
graph LR
    subgraph "用户代码"
        USER[logger.Info/Infof/Infow]
    end

    subgraph "统一接口层"
        INTERFACE[core.Logger Interface]
    end

    subgraph "引擎选择"
        FACTORY[factory.LoggerFactory]
    end

    subgraph "双引擎实现"
        SLOG_ENGINE[engines/slog]
        ZAP_ENGINE[engines/zap]
    end

    subgraph "字段标准化"
        ENCODER[fields.StandardEncoder]
    end

    subgraph "统一输出"
        OUTPUT[相同的JSON/Console格式]
    end

    USER --> INTERFACE
    INTERFACE --> FACTORY
    FACTORY --> SLOG_ENGINE
    FACTORY --> ZAP_ENGINE
    SLOG_ENGINE --> ENCODER
    ZAP_ENGINE --> ENCODER
    ENCODER --> OUTPUT

    classDef userCode fill:#e1f5fe
    classDef interface fill:#f3e5f5
    classDef factory fill:#fff3e0
    classDef engine fill:#fce4ec
    classDef output fill:#e8f5e8

    class USER userCode
    class INTERFACE interface
    class FACTORY factory
    class SLOG_ENGINE,ZAP_ENGINE engine
    class ENCODER,OUTPUT output
引擎 适用场景 性能 特点
Slog 通用应用,标准化 标准 Go 1.21+ 标准库,兼容性好
Zap 高性能场景 极高 零分配,生产环境首选

关键优势: 相同的代码,不同的引擎,完全一致的输出格式!

字段标准化

确保不同引擎输出完全一致的字段名和格式:

// Slog 和 Zap 引擎输出完全相同
{
  "timestamp": "2023-12-01T10:30:00.123456789Z",
  "level": "info",
  "message": "用户登录成功",
  "caller": "main.go:42",
  "user_id": "12345",
  "trace_id": "abc123def456"
}
智能 OTLP 配置

无需繁琐的 enabled: true 配置,有端点即自动启用:

# 最简配置,自动启用 OTLP
otlp-endpoint: "http://localhost:4317"

# 高级配置
otlp:
  endpoint: "https://jaeger.company.com:4317"
  protocol: "grpc"
  timeout: "15s"
  headers:
    Authorization: "Bearer token123"

🛠️ 高级功能

动态配置重载
import "github.com/kart-io/logger/reload"

// 文件监控 + 信号处理 + API 触发
reloadConfig := &reload.ReloadConfig{
    ConfigFile: "logger.yaml",
    Triggers:   reload.TriggerAll,
    Signals:    []os.Signal{syscall.SIGUSR1},
}

reloader, _ := reload.NewConfigReloader(reloadConfig, initialConfig, factory)
reloader.Start()

// 现在支持:
// 1. 修改 logger.yaml 文件自动重载
// 2. kill -USR1 <pid> 信号重载
// 3. HTTP API 调用重载
Web 框架集成
// Gin 集成
import "github.com/kart-io/logger/integrations"

router := gin.Default()
logger, _ := logger.NewWithDefaults()
router.Use(integrations.GinMiddleware(logger))

// Echo 集成
e := echo.New()
e.Use(integrations.EchoMiddleware(logger))

// GORM 集成
db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
    Logger: integrations.NewGormLogger(logger),
})
上下文和追踪
// 创建带上下文的日志器
ctx := context.WithValue(context.Background(), "request_id", "req-12345")
contextLogger := logger.WithCtx(ctx,
    "service", "user-api",
    "version", "v1.2.3")

// 分布式追踪
contextLogger.Infow("处理用户请求",
    "trace_id", "abc123def456",
    "span_id", "span789xyz",
    "user_id", userID,
    "operation", "get_profile")

// 创建子日志器
userLogger := logger.With(
    "user_id", userID,
    "session_id", sessionID)

// 所有后续日志都包含这些字段
userLogger.Info("用户进入页面")
userLogger.Warn("权限检查失败")

📖 使用示例

项目包含 13+ 个完整的使用示例,每个示例都是独立的 Go 模块:

运行示例
# 综合功能演示
cd example/comprehensive && go run main.go

# InitialFields 使用演示
cd example/initial_fields && go run main.go

# Web 框架集成
cd example/echo && go run main.go    # http://localhost:8081
cd example/gin && go run main.go     # http://localhost:8080

# OTLP 集成测试
cd example/otlp && go run main.go

# 性能基准测试
cd example/performance && go run main.go

🔧 配置选项

基本配置
engine: "zap"                    # 引擎选择: "zap" | "slog"
level: "info"                    # 日志级别: "debug" | "info" | "warn" | "error" | "fatal"
format: "json"                   # 输出格式: "json" | "console"
output-paths: ["stdout"]         # 输出路径: 控制台、文件路径
development: false               # 开发模式 (影响格式和堆栈跟踪)
OTLP 配置
# 扁平化配置 (常用)
otlp-endpoint: "http://localhost:4317"

# 嵌套配置 (高级)
otlp:
  enabled: true                  # 明确启用/禁用
  endpoint: "http://jaeger:4317" # OTLP 收集器端点
  protocol: "grpc"               # 协议: "grpc" | "http"
  timeout: "10s"                 # 连接超时
  headers:                       # 自定义请求头
    Authorization: "Bearer token"
    X-Tenant-ID: "tenant-123"
环境变量
export LOG_ENGINE="zap"
export LOG_LEVEL="debug"
export LOG_FORMAT="json"
export LOG_OTLP_ENDPOINT="http://localhost:4317"
export LOG_DEVELOPMENT="true"

🚦 OTLP 后端支持

Jaeger
# docker-compose.yml
services:
  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"    # Web UI
      - "4317:4317"      # OTLP gRPC
      - "4318:4318"      # OTLP HTTP
VictoriaLogs
services:
  victorialogs:
    image: victoriametrics/victoria-logs:latest
    ports:
      - "9428:9428"      # HTTP API
      - "4317:4317"      # OTLP gRPC
OpenTelemetry Collector
# otel-collector.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

exporters:
  logging:
  jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: true

service:
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [logging, jaeger]

🎛️ 命令行集成

import (
    "github.com/spf13/pflag"
    "github.com/kart-io/logger/option"
)

func main() {
    opt := option.DefaultLogOption()

    // 自动添加所有日志配置标志
    fs := pflag.NewFlagSet("myapp", pflag.ExitOnError)
    opt.AddFlags(fs)
    fs.Parse(os.Args[1:])

    logger, _ := logger.New(opt)
}
# 命令行使用
./myapp --engine=zap \
        --level=debug \
        --format=console \
        --otlp-endpoint=http://localhost:4317 \
        --development

🏭 生产环境配置

高性能配置
opt := &option.LogOption{
    Engine:      "zap",                      // 高性能引擎
    Level:       "info",                     // 生产级别
    Format:      "json",                     // 结构化输出
    OutputPaths: []string{"/var/log/app.log"}, // 文件输出
    Development: false,                      // 生产模式

    // OTLP 配置
    OTLPEndpoint: os.Getenv("OTLP_ENDPOINT"),
    OTLP: &option.OTLPOption{
        Protocol: "grpc",
        Timeout:  30 * time.Second,
        Headers: map[string]string{
            "Authorization": "Bearer " + os.Getenv("OTLP_TOKEN"),
        },
    },
}
多环境配置
func createLogger(env string) (core.Logger, error) {
    var opt *option.LogOption

    switch env {
    case "production":
        opt = &option.LogOption{
            Engine: "zap",
            Level:  "info",
            Format: "json",
            OutputPaths: []string{"/var/log/app.log"},
            OTLPEndpoint: "https://otlp.company.com:4317",
        }
    case "development":
        opt = &option.LogOption{
            Engine: "slog",
            Level:  "debug",
            Format: "console",
            OutputPaths: []string{"stdout"},
            Development: true,
        }
    case "test":
        opt = &option.LogOption{
            Engine: "slog",
            Level:  "error",
            OutputPaths: []string{"stderr"},
        }
    }

    return logger.New(opt)
}

📊 性能基准

基于内置的 performance example

cd example/performance && go run main.go

典型结果 (M1 Pro, 8 cores):

引擎 操作 速度 分配
Zap 结构化日志 ~2M ops/sec 0 allocs/op
Zap 格式化日志 ~1M ops/sec 1 alloc/op
Slog 结构化日志 ~800K ops/sec 3 allocs/op
Slog 格式化日志 ~600K ops/sec 4 allocs/op

🧪 测试

# 运行所有测试
go test ./...

# 运行基准测试
go test -bench=. ./...

# 查看覆盖率
go test -cover ./...

# 生成覆盖率报告
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

📚 文档

每个包都有详细的中文文档:

🤝 贡献

我们欢迎各种形式的贡献!

  1. Fork 本项目
  2. 创建功能分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 创建 Pull Request
开发指南
# 克隆项目
git clone https://github.com/kart-io/logger.git
cd logger

# 安装依赖
go mod tidy

# 运行测试
go test ./...

# 运行示例
cd example/comprehensive && go run main.go

🐛 问题反馈

如果您遇到问题或有建议,请:

  1. 查看 Issues
  2. 查看 文档 和各包的 README
  3. 运行相关 示例
  4. 提交新的 Issue

📄 许可证

本项目采用 Apache 2.0 许可证。

🙏 致谢


⭐ 如果这个项目对您有帮助,请给个 Star!

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Debug

func Debug(args ...interface{})

Debug logs a debug message using the global logger.

func Debugf

func Debugf(template string, args ...interface{})

Debugf logs a debug message with formatting using the global logger.

func Debugw

func Debugw(msg string, keysAndValues ...interface{})

Debugw logs a debug message with structured fields using the global logger.

func Error

func Error(args ...interface{})

Error logs an error message using the global logger.

func Errorf

func Errorf(template string, args ...interface{})

Errorf logs an error message with formatting using the global logger.

func Errorw

func Errorw(msg string, keysAndValues ...interface{})

Errorw logs an error message with structured fields using the global logger.

func Fatal

func Fatal(args ...interface{})

Fatal logs a fatal message using the global logger.

func Fatalf

func Fatalf(template string, args ...interface{})

Fatalf logs a fatal message with formatting using the global logger.

func Fatalw

func Fatalw(msg string, keysAndValues ...interface{})

Fatalw logs a fatal message with structured fields using the global logger.

func Flush added in v0.2.0

func Flush() error

Flush flushes any buffered log entries using the global logger.

func Global

func Global() core.Logger

Global returns the global logger instance. If no global logger is set, it returns a logger with default configuration. This function is thread-safe and ensures only one default logger is created.

func Info

func Info(args ...interface{})

Info logs an info message using the global logger.

func Infof

func Infof(template string, args ...interface{})

Infof logs an info message with formatting using the global logger.

func Infow

func Infow(msg string, keysAndValues ...interface{})

Infow logs an info message with structured fields using the global logger.

func New

func New(opt *option.LogOption) (core.Logger, error)

New creates a new logger with the provided configuration.

func NewWithDefaults

func NewWithDefaults() (core.Logger, error)

NewWithDefaults creates a new logger with default configuration.

func SetGlobal

func SetGlobal(logger core.Logger)

SetGlobal sets the global logger instance.

func Warn

func Warn(args ...interface{})

Warn logs a warning message using the global logger.

func Warnf

func Warnf(template string, args ...interface{})

Warnf logs a warning message with formatting using the global logger.

func Warnw

func Warnw(msg string, keysAndValues ...interface{})

Warnw logs a warning message with structured fields using the global logger.

func With

func With(keysAndValues ...interface{}) core.Logger

With creates a child logger with the specified key-value pairs using the global logger.

Types

This section is empty.

Directories

Path Synopsis
cmd
demo command
engines
zap
example
initial_fields command
gin

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL