Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format the log #1178

Open
yanmxa opened this issue Oct 23, 2024 · 3 comments
Open

Format the log #1178

yanmxa opened this issue Oct 23, 2024 · 3 comments

Comments

@yanmxa
Copy link
Member

yanmxa commented Oct 23, 2024

Here's a comprehensive comparison of the specified logging libraries based on various features, including log format, log level configuration, dynamic change log level, log code location, and time formatting:

Library Log Format Log Level Configuration Code Location Time Formatting Dynamic Level Support GitHub Stars Notes
glog Text-based Via -v flag for verbosity levels Yes, with log.V() calls Default format (RFC3339) No 3.4k Simple interface, widely used in Go​GitHub​GitHub.
zap JSON or text Configurable at initialization with log levels Yes, includes caller information Customizable format Yes 19.2k High performance, structured logging​GitHub.
zapr JSON or text Follows zap’s configuration via logr Yes, includes caller information Customizable format Yes 127 Adapter for zap, integrates with logr​GitHub​GitHub.
logr Varies by backend Controlled via context or runtime configuration Yes, via WithValues Format varies by backend Yes 836 Flexible, interface for structured logging​GitHub.
klog Text-based Set via --v flag for verbosity levels Yes, provides file and line details Default format (RFC3339) No 526 Designed for Kubernetes, simpler format​GitHub.
  • We want to configure the LogLevel at run time and format the time to make it readable! So glog and klog are not suitable, I will remove them from the list.
  • zap provides advanced features like structured logging and customizable formats, making it suitable for high-performance applications.
  • zapr and logr offer flexibility through their interfaces, integrating well with other logging systems while providing features like context-based logging.
@yanmxa
Copy link
Member Author

yanmxa commented Oct 23, 2024

zap Vs zapr ?

  • zap is highly flexible and allows you to configure multiple log levels, providing detailed control over how logs are recorded. However, when logging key-value pairs, you must use zapcore.Filed to structure the key/value entries
    logger.Info("Info log", zap.String("username", "john_doe"))
    2024-10-24T10:12:48.259+0800    DEBUG   log-zap/main.go:38      Debug message with custom encoder - debug level
    2024-10-24T10:12:48.259+0800    INFO    log-zap/main.go:39      Info message - debug level      {"username": "john_doe"}
    2024-10-24T10:12:48.259+0800    WARN    log-zap/main.go:40      Warning message - debug level
    main.main
            /Users/yanmeng/Workspace/redhat/hub-of-hubs/samples/log-zap/main.go:40
    runtime.main
            /Users/yanmeng/go/pkg/mod/golang.org/[email protected]/src/runtime/proc.go:271
    2024-10-24T10:12:48.259+0800    INFO    log-zap/main.go:44      Info message - info level
    2024-10-24T10:12:48.259+0800    WARN    log-zap/main.go:45      Warning message - info level
    main.main
            /Users/yanmeng/Workspace/redhat/hub-of-hubs/samples/log-zap/main.go:45
    runtime.main
            /Users/yanmeng/go/pkg/mod/golang.org/[email protected]/src/runtime/proc.go:271
  • zapr builds on zap's flexibility, reusing the same configuration. The key difference is that zapr exposes a higher-level, user-friendly interface for logging key-value pairs. Instead of manually using zapcore.Field, you can directly log with a cleaner syntax:
    log.V(0).Info("info", "key", "val")
    The cons
    • dynamic log level changes in zapr are managed by the underlying zap logger. while V(0) typically corresponds to INFO, and V(1) to DEBUG, levels beyond V(1) may not behave as expected, as zap doesn't directly map them.
    • This limitation makes higher verbosity levels (V(2) and above) less useful or unsupported. For the global hub, sticking to standard DEBUG, INFO, and ERROR levels are sufficient and works well for typical use cases.
    • The -2 in the above snippet means that log.V(2).Info() calls will be active. -3 would enable log.V(3).Info(), etc. Note that zap's levels are int8 which means the most verbose level you can give it is -128. The zapr implementation will cap V() levels greater than 127 to 127, so setting the zap level to -128 really means "activate all logs".
      zc.Level.SetLevel(-2)
      ...
      log.V(2).Info("-2heloo2", "ni", "hao")
      ...
      2024-10-23T21:00:22.363+0800    LEVEL(-2)       log-zapr/main.go:83     -2heloo2        {"ni": "hao"}
    • controller runtime
    • sample
    2024-10-24T10:18:10.630+0800    LEVEL(-2)       log-zapr/main.go:81     V2 message      {"ni": "hao"}
    2024-10-24T10:18:10.630+0800    DEBUG   log-zapr/main.go:82     V1 message(Debug)       {"ni": "hao"}
    2024-10-24T10:18:10.630+0800    INFO    log-zapr/main.go:83     Info message    {"key": "val"}
    

@yanmxa
Copy link
Member Author

yanmxa commented Oct 23, 2024

  1. Using the zapr, which can be invoked by the interface logr easily. The only concern is it only supports DEBUG, INFO, and ERROR
  2. Using the zap is straightforward! However, we need to change the way we log structured information. For example, log the key value with zap.String("username", "john_doe")

@yanmxa
Copy link
Member Author

yanmxa commented Oct 24, 2024

The only concern with using the Zap is the structured API. To avoid using its strict print mode, we can use its subpackage, sugar!

Reference: uber-go/zap#138

Sugar wraps the Logger to provide a more ergonomic, but slightly slower, API. Sugaring a Logger is quite inexpensive, so it's reasonable for a single application to use both Loggers and SugaredLoggers, converting between them on the boundaries of performance-sensitive code

logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
  // Structured context as loosely typed key-value pairs.
  "url", url,
  "attempt", 3,
  "backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant