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

Add slog structured logging wrapper package #34

Merged
merged 3 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
main
/bin/
.idea
63 changes: 63 additions & 0 deletions pkg/slogs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# slogs

This is a wrapper around the stdlib Golang slog package that just creates a slog logger in some standard way, with a configurable log level.

Slog was introduced in Go 1.21, so that is the minimum required Go version to use this module.

## Usage

```go
package main

import "github.com/chia-network/go-modules/pkg/slogs"

func main() {
// Init the logger with a log-level string (debug, info, warn, error)
// defaults to "info" if empty or unsupported string
slogs.Init("info")

// Logs a hello world message at the info level
slogs.Logger.Info("hello world")

// Logs an error message at the error level
slogs.Logger.Error("we received an error")
}
```

In a Cobra/Viper CLI app this might look more like:

```go
package cmd

import (
"log"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/chia-network/go-modules/pkg/slogs"
)

var rootCmd = &cobra.Command{
Use: "cmd",
Short: "Short help message for cmd",

Run: func(cmd *cobra.Command, args []string) {
// Init logger
slogs.Init(viper.GetString("log-level"))

// Application logic below
},
}

func Execute() {
cobra.CheckErr(rootCmd.Execute())
}

func init() {
rootCmd.PersistentFlags().String("log-level", "info", "The log-level for the application, can be one of info, warn, error, debug.")
err := viper.BindPFlag("log-level", rootCmd.PersistentFlags().Lookup("log-level"))
if err != nil {
log.Fatalln(err.Error()) // Have to log with standard logger until the slog logger is initialized
}
}
```
40 changes: 40 additions & 0 deletions pkg/slogs/slogs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package slogs

import (
"log"
"log/slog"
"os"
"strings"
)

// Logger is a custom text logger from the stdlib slog package
var Logger *slog.Logger

// Init custom init function that accepts the log level for the application and initializes a stdout slog logger
func Init(level string) {
Logger = slog.New(
slog.NewTextHandler(
os.Stdout,
&slog.HandlerOptions{
Level: parseLogLevel(level),
},
),
)
}

// Function to convert log level string to slog.Level
func parseLogLevel(level string) slog.Level {
switch strings.ToLower(level) {
case "debug":
return slog.LevelDebug
case "info":
return slog.LevelInfo
case "warn", "warning":
return slog.LevelWarn
case "error":
return slog.LevelError
default:
log.Printf("unknown log level specified \"%s\", defaulting to info level", level)
return slog.LevelInfo
}
}