https://github.com/corvax/slogtfmt
A handler for slog that allows you to customize timestamp formats.
https://github.com/corvax/slogtfmt
go golang logger slog slog-handler
Last synced: 3 months ago
JSON representation
A handler for slog that allows you to customize timestamp formats.
- Host: GitHub
- URL: https://github.com/corvax/slogtfmt
- Owner: corvax
- License: mit
- Created: 2024-07-01T05:46:49.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-11-28T03:30:09.000Z (7 months ago)
- Last Synced: 2025-11-30T15:22:15.984Z (7 months ago)
- Topics: go, golang, logger, slog, slog-handler
- Language: Go
- Homepage:
- Size: 22.5 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# slogtfmt
`slogtfmt` is a handler for slog that allows you to customize timestamp formats for both log timestamps and time attributes. This package also provides a helper function to add tags to log entries.
## Features
- Customizable time value formatting for both log timestamps and time attributes
- Support for log record tagging, tags are shown in square brackets before the message
- Optional inclusion of source code information (file and line number)
## Installation
To install `slogtfmt`, use `go get`:
```bash
go get github.com/corvax/slogtfmt
```
## Usage
### Creating a New Handler
To create a new slog handler, use the `NewHandler` function. This function requires an `io.Writer` where the logs will be written and an `Options` struct to configure the handler.
```go
package main
import (
"time"
"os"
"github.com/corvax/slogtfmt"
)
func main() {
opts := &slogtfmt.Options{
Level: slog.LevelInfo,
AddSource: false,
TimeFormat: "2006-01-02T15:04:05.999Z07:00",
TimeInUTC: true,
TimeAttributeFormat: time.RFC3339,
TimeAttributeInUTC: true,
}
logger := slog.New(slogtfmt.NewHandler(os.Stdout, opts))
slog.SetDefault(logger)
slog.Info("Started", slog.Time("time", time.Now()))
// To create a logger with an added tag, use With(slogtfmt.Tag("tag_name")
serviceLogger := logger.With(slogtfmt.Tag("service"))
serviceLogger.Info("Started")
}
```
#### Sample output
The output of the sample code above would be as following:
```text
2024-07-01T04:23:30.557Z INFO Started time=2024-07-01T03:41:05Z
2024-07-01T04:23:30.557Z INFO [service] Started
```
### Without a timestamp
In order to omit the log timestamp, set `TimeFormat` to an empty string.
```go
opts := &slogtfmt.Options{
Level: slog.LevelDebug,
TimeFormat: "",
}
slog.SetDefault(slog.New(slogtfmt.NewHandler(os.Stdout, opts)))
slog.Info("Started", slog.Time("time", time.Now())
slog.Debug("User connected", slog.String("user", "username"))
slog.Warn("Access denied", slog.String("role", "readOnly"))
slog.Error("Service is unavailable")
slog.Info("Finished")
```
#### Output:
Note that the time attribute format is not affected and uses the default formatting `slogtfmt.RFC3339Milli`.
```
INFO Started time=2024-07-01T15:02:50.720+10:00
DEBUG User connected user="username"
WARN Access denied role="readOnly"
ERROR Service is unavailable
INFO Finished
```
### Using `With` Option functions
You can also use the `slogtfmt.NewHandlerWithOptions()` constructor with Option functions.
To achieve the same log formatting as shown above, you can use the following snippet:
```go
slog.SetDefault(slog.New(slogtfmt.NewHandlerWithOptions(
os.Stdout,
slogtfmt.WithLevel(slog.LevelDebug),
slogtfmt.WithTimeFormat(""),
)))
```
`With` functions are available for all `Options`.
### Default options
The constructor `slogtfmt.NewHandlerWithOptions()` creates the handler with the default `Options` and then updates them using the provided `With` option functions.
If `nil` as `Options` is passed to `slogtfmt.NewHandler()`, the handler will be created with the default options.
##### Default options
```go
defaultOptions := &Options{
Level: slog.LevelInfo,
AddSource: false,
TimeFormat: slogtfmt.RFC3339Milli,
TimeInUTC: false,
TimeAttributeFormat: slogtfmt.RFC3339Milli,
TimeAttributeInUTC: false,
}
```
## Time formats
In addition to the standard time format, there are some additional time formats available in the package that can be used for formatting timestamps.
```go
const (
RFC3339Milli = "2006-01-02T15:04:05.000Z07:00"
RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
)
```
## Options
The `Options` struct allows you to customize the behavior of the handler. Below is a detailed explanation of each field in the `Options` struct:
* **`Level`**: Specifies the minimum level to log. Logs with a lower level are discarded. If `nil`, the handler uses `slog.LevelInfo`.
* **`AddSource`**: If set to `true`, the handler computes the source code position of the log statement and adds the file name and the position to the output.
* **`TimeFormat`**: The format used for log timestamps in the output. If empty, the handler will omit the timestamps.
* **`TimeInUTC`**: Specifies whether the time format should use UTC instead of the local time zone.
* **`TimeAttributeFormat`**: Specifies the time format used for the time attribute in the log record. If empty, the default time format of `time.RFC3339` is used.
* **`TimeAttributeInUTC`**: Specifies whether the time attribute in the log record should use UTC instead of the local time zone.
## `loggerf.Logger`
The `loggerf.Logger` is a wrapper around the standard `slog.Logger` structure that provides additional functions to format log messages. These functions allow you to log messages with formatted strings, similar to `fmt.Printf`.
### Formatting functions
The `loggerf.Logger` provides the following functions to format the log message:
- `Debugf(format string, args ...any)`: Log a debug message with formatting.
- `Infof(format string, args ...any)`: Log an info message with formatting.
- `Warnf(format string, args ...any)`: Log a warning message with formatting.
- `Errorf(format string, args ...any)`: Log an error message with formatting.
- `Logf(ctx context.Context, level slog.Level, format string, args ...any)`: Log a formatted message at the specified log level.
### Usage
To use the `loggerf.Logger`, add the `loggerf` import to your code:
```bash
go get github.com/corvax/slogtfmt/loggerf
```
Create a new instance of `loggerf.Logger` based on any `slog.Logger`:
```go
import (
"errors"
"log/slog"
"os"
"github.com/corvax/slogtfmt"
"github.com/corvax/slogtfmt/loggerf"
)
func main() {
handler := slogtfmt.NewHandler(os.Stdout, &slogtfmt.Options{
Level: slog.LevelDebug,
TimeFormat: "",
})
slogger := slog.New(handler)
logger := loggerf.NewLogger(slogger)
// Now you can use the functions to format the log messages.
// For example:
username := "user"
ipAddress := "localhost"
diskUsage := 98
err := errors.New("test error")
logger.Debugf("Debug message: %s", "Hello, World!")
logger.Infof("User %s logged in from %s", username, ipAddress)
logger.Warnf("Warning: disk usage is at %d%%", diskUsage)
logger.Errorf("Error occurred: %v", err)
}
```
Output:
```
DEBUG Debug message: Hello, World!
INFO User user logged in from localhost
WARN Warning: disk usage is at 98%
ERROR Error occured: test error
```
### With context
You can also create a new logger with additional context using the `With` method:
```go
import (
"errors"
"log/slog"
"os"
"github.com/corvax/slogtfmt"
"github.com/corvax/slogtfmt/loggerf"
)
func main() {
handler := slogtfmt.NewHandler(os.Stdout, &slogtfmt.Options{
Level: slog.LevelDebug,
TimeFormat: "",
})
slogger := slog.New(handler)
logger := loggerf.NewLogger(slogger.With(slogtfmt.Tag("service")))
// Now you can use the functions to format the log message.
// For example:
username := "user"
ipAddress := "localhost"
diskUsage := 98
err := errors.New("test error")
logger.Debugf("Debug message: %s", "Hello, World!")
logger.Infof("User %s logged in from %s", username, ipAddress)
logger.Warnf("Warning: disk usage is at %d%%", diskUsage)
logger.Errorf("Error occurred: %v", err)
}
```
Output:
```
DEBUG [service] Debug message: Hello, World!
INFO [service] User user logged in from localhost
WARN [service] Warning: disk usage is at 98%
ERROR [service] Error occured: test error
```
`WithGroup` can also be used to create a new logger with additional context and a group name.
### Notes
Please be aware that the formatting log message functions use `args` to format the message. `args` values are not used to build `slog.Attr`.
If you want to add additional attributes to your log message, you can still use the `slog.Logger` methods, for example:
```go
logger.Info("User is logged in", "username", username, "host", ipAddress)
```
Output:
```
INFO User is logged in username="user" host="localhost"
```
`loggerf.Logger` embeds the `slog.Logger` structure, so you can use any of the `slog.Logger` methods.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.