Skip to content

Commit e094ac7

Browse files
authored
Merge pull request #1 from injeniero/main
Adding TimeFormat option and other changes
2 parents 30dd520 + 428d018 commit e094ac7

File tree

3 files changed

+53
-23
lines changed

3 files changed

+53
-23
lines changed

encoding.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ import (
99
)
1010

1111
type encoder struct {
12-
nocolor bool
12+
noColor bool
13+
timeFormat string
1314
}
1415

1516
func (e *encoder) NewLine(buf *buffer) {
16-
buf.AppendString("\r\n")
17+
buf.AppendByte('\n')
1718
}
1819

1920
func (e *encoder) withColor(b *buffer, c color, f func()) {
20-
if c == "" || e.nocolor {
21+
if c == "" || e.noColor {
2122
f()
2223
return
2324
}
@@ -69,7 +70,7 @@ func (e *encoder) writeColoredDuration(w *buffer, d time.Duration, seq color) {
6970
}
7071

7172
func (e *encoder) writeTimestamp(buf *buffer, tt time.Time) {
72-
e.writeColoredTime(buf, tt, time.DateTime, colorTimestamp)
73+
e.writeColoredTime(buf, tt, e.timeFormat, colorTimestamp)
7374
buf.AppendByte(' ')
7475
}
7576

@@ -125,7 +126,7 @@ func (e *encoder) writeValue(buf *buffer, value slog.Value) {
125126
case slog.KindFloat64:
126127
e.writeColoredFloat(buf, value.Float64(), colorAttrValue)
127128
case slog.KindTime:
128-
e.writeColoredTime(buf, value.Time(), time.RFC3339, colorAttrValue)
129+
e.writeColoredTime(buf, value.Time(), e.timeFormat, colorAttrValue)
129130
case slog.KindUint64:
130131
e.writeColoredUint(buf, value.Uint64(), colorAttrValue)
131132
case slog.KindDuration:
@@ -150,22 +151,31 @@ func (e *encoder) writeValue(buf *buffer, value slog.Value) {
150151
func (e *encoder) writeLevel(buf *buffer, l slog.Level) {
151152
var style color
152153
var str string
154+
var delta int
153155
switch {
154156
case l >= slog.LevelError:
155157
style = colorLevelError
156158
str = "ERR"
159+
delta = int(l - slog.LevelError)
157160
case l >= slog.LevelWarn:
158161
style = colorLevelWarn
159162
str = "WRN"
163+
delta = int(l - slog.LevelWarn)
160164
case l >= slog.LevelInfo:
161165
style = colorLevelInfo
162166
str = "INF"
167+
delta = int(l - slog.LevelInfo)
163168
case l >= slog.LevelDebug:
164169
style = colorLevelDebug
165170
str = "DBG"
171+
delta = int(l - slog.LevelDebug)
166172
default:
167173
style = bold
168-
str = "???"
174+
str = "DBG"
175+
delta = int(l - slog.LevelDebug)
176+
}
177+
if delta != 0 {
178+
str = fmt.Sprintf("%s%+d", str, delta)
169179
}
170180
e.writeColoredString(buf, str, style)
171181
buf.AppendByte(' ')

handler.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"strings"
99
"sync"
10+
"time"
1011
)
1112

1213
var bufferPool = &sync.Pool{
@@ -31,6 +32,9 @@ type HandlerOptions struct {
3132

3233
// Disable colorized output
3334
NoColor bool
35+
36+
// TimeFormat is the format used for time.DateTime
37+
TimeFormat string
3438
}
3539

3640
type Handler struct {
@@ -53,13 +57,16 @@ func NewHandler(out io.Writer, opts *HandlerOptions) *Handler {
5357
if opts.Level == nil {
5458
opts.Level = slog.LevelInfo
5559
}
60+
if opts.TimeFormat == "" {
61+
opts.TimeFormat = time.DateTime
62+
}
5663
opt := *opts // Copy struct
5764
return &Handler{
5865
opts: &opt,
5966
out: out,
6067
group: "",
6168
context: nil,
62-
enc: &encoder{nocolor: opt.NoColor},
69+
enc: &encoder{noColor: opt.NoColor, timeFormat: opt.TimeFormat},
6370
}
6471
}
6572

handler_test.go

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,20 @@ func TestHandler_colors(t *testing.T) {
2020
rec := slog.NewRecord(now, slog.LevelInfo, "foobar", 0)
2121
AssertNoError(t, h.Handle(context.Background(), rec))
2222

23-
expected := fmt.Sprintf("\x1b[90m%s\x1b[0m \x1b[92mINF\x1b[0m \x1b[97mfoobar\x1b[0m\r\n", now.Format(time.DateTime))
23+
expected := fmt.Sprintf("\x1b[90m%s\x1b[0m \x1b[92mINF\x1b[0m \x1b[97mfoobar\x1b[0m\n", now.Format(time.DateTime))
24+
AssertEqual(t, expected, buf.String())
25+
}
26+
27+
func TestHandler_TimeFormat(t *testing.T) {
28+
buf := bytes.Buffer{}
29+
h := NewHandler(&buf, &HandlerOptions{TimeFormat: time.RFC3339Nano, NoColor: true})
30+
now := time.Now()
31+
rec := slog.NewRecord(now, slog.LevelInfo, "foobar", 0)
32+
endTime := now.Add(time.Second)
33+
rec.AddAttrs(slog.Time("endtime", endTime))
34+
AssertNoError(t, h.Handle(context.Background(), rec))
35+
36+
expected := fmt.Sprintf("%s INF foobar endtime=%s\n", now.Format(time.RFC3339Nano), endTime.Format(time.RFC3339Nano))
2437
AssertEqual(t, expected, buf.String())
2538
}
2639

@@ -31,7 +44,7 @@ func TestHandler_NoColor(t *testing.T) {
3144
rec := slog.NewRecord(now, slog.LevelInfo, "foobar", 0)
3245
AssertNoError(t, h.Handle(context.Background(), rec))
3346

34-
expected := fmt.Sprintf("%s INF foobar\r\n", now.Format(time.DateTime))
47+
expected := fmt.Sprintf("%s INF foobar\n", now.Format(time.DateTime))
3548
AssertEqual(t, expected, buf.String())
3649
}
3750

@@ -63,7 +76,7 @@ func TestHandler_Attr(t *testing.T) {
6376
)
6477
AssertNoError(t, h.Handle(context.Background(), rec))
6578

66-
expected := fmt.Sprintf("%s INF foobar bool=true int=-12 uint=12 float=3.14 foo=bar time=%s dur=1s group.foo=bar group.subgroup.foo=bar err=the error stringer=stringer nostringer={bar}\r\n", now.Format(time.DateTime), now.Format(time.RFC3339))
79+
expected := fmt.Sprintf("%s INF foobar bool=true int=-12 uint=12 float=3.14 foo=bar time=%s dur=1s group.foo=bar group.subgroup.foo=bar err=the error stringer=stringer nostringer={bar}\n", now.Format(time.DateTime), now.Format(time.DateTime))
6780
AssertEqual(t, expected, buf.String())
6881
}
6982

@@ -84,12 +97,12 @@ func TestHandler_WithAttr(t *testing.T) {
8497
})
8598
AssertNoError(t, h2.Handle(context.Background(), rec))
8699

87-
expected := fmt.Sprintf("%s INF foobar bool=true int=-12 uint=12 float=3.14 foo=bar time=%s dur=1s group.foo=bar group.subgroup.foo=bar\r\n", now.Format(time.DateTime), now.Format(time.RFC3339))
100+
expected := fmt.Sprintf("%s INF foobar bool=true int=-12 uint=12 float=3.14 foo=bar time=%s dur=1s group.foo=bar group.subgroup.foo=bar\n", now.Format(time.DateTime), now.Format(time.DateTime))
88101
AssertEqual(t, expected, buf.String())
89102

90103
buf.Reset()
91104
AssertNoError(t, h.Handle(context.Background(), rec))
92-
AssertEqual(t, fmt.Sprintf("%s INF foobar\r\n", now.Format(time.DateTime)), buf.String())
105+
AssertEqual(t, fmt.Sprintf("%s INF foobar\n", now.Format(time.DateTime)), buf.String())
93106
}
94107

95108
func TestHandler_WithGroup(t *testing.T) {
@@ -100,31 +113,31 @@ func TestHandler_WithGroup(t *testing.T) {
100113
rec.Add("int", 12)
101114
h2 := h.WithGroup("group1").WithAttrs([]slog.Attr{slog.String("foo", "bar")})
102115
AssertNoError(t, h2.Handle(context.Background(), rec))
103-
expected := fmt.Sprintf("%s INF foobar group1.foo=bar group1.int=12\r\n", now.Format(time.DateTime))
116+
expected := fmt.Sprintf("%s INF foobar group1.foo=bar group1.int=12\n", now.Format(time.DateTime))
104117
AssertEqual(t, expected, buf.String())
105118
buf.Reset()
106119

107120
h3 := h2.WithGroup("group2")
108121
AssertNoError(t, h3.Handle(context.Background(), rec))
109-
expected = fmt.Sprintf("%s INF foobar group1.foo=bar group1.group2.int=12\r\n", now.Format(time.DateTime))
122+
expected = fmt.Sprintf("%s INF foobar group1.foo=bar group1.group2.int=12\n", now.Format(time.DateTime))
110123
AssertEqual(t, expected, buf.String())
111124

112125
buf.Reset()
113126
AssertNoError(t, h.Handle(context.Background(), rec))
114-
AssertEqual(t, fmt.Sprintf("%s INF foobar int=12\r\n", now.Format(time.DateTime)), buf.String())
127+
AssertEqual(t, fmt.Sprintf("%s INF foobar int=12\n", now.Format(time.DateTime)), buf.String())
115128
}
116129

117130
func TestHandler_Levels(t *testing.T) {
118131
levels := map[slog.Level]string{
119-
slog.LevelDebug - 1: "???",
132+
slog.LevelDebug - 1: "DBG-1",
120133
slog.LevelDebug: "DBG",
121-
slog.LevelDebug + 1: "DBG",
134+
slog.LevelDebug + 1: "DBG+1",
122135
slog.LevelInfo: "INF",
123-
slog.LevelInfo + 1: "INF",
136+
slog.LevelInfo + 1: "INF+1",
124137
slog.LevelWarn: "WRN",
125-
slog.LevelWarn + 1: "WRN",
138+
slog.LevelWarn + 1: "WRN+1",
126139
slog.LevelError: "ERR",
127-
slog.LevelError + 1: "ERR",
140+
slog.LevelError + 1: "ERR+1",
128141
}
129142

130143
for l := range levels {
@@ -137,7 +150,7 @@ func TestHandler_Levels(t *testing.T) {
137150
rec := slog.NewRecord(now, ll, "foobar", 0)
138151
if ll >= l {
139152
AssertNoError(t, h.Handle(context.Background(), rec))
140-
AssertEqual(t, fmt.Sprintf("%s %s foobar\r\n", now.Format(time.DateTime), s), buf.String())
153+
AssertEqual(t, fmt.Sprintf("%s %s foobar\n", now.Format(time.DateTime), s), buf.String())
141154
buf.Reset()
142155
}
143156
}
@@ -155,10 +168,10 @@ func TestHandler_Source(t *testing.T) {
155168
AssertNoError(t, h.Handle(context.Background(), rec))
156169
cwd, _ := os.Getwd()
157170
file, _ = filepath.Rel(cwd, file)
158-
AssertEqual(t, fmt.Sprintf("%s INF %s:%d > foobar\r\n", now.Format(time.DateTime), file, line), buf.String())
171+
AssertEqual(t, fmt.Sprintf("%s INF %s:%d > foobar\n", now.Format(time.DateTime), file, line), buf.String())
159172
buf.Reset()
160173
AssertNoError(t, h2.Handle(context.Background(), rec))
161-
AssertEqual(t, fmt.Sprintf("%s INF foobar\r\n", now.Format(time.DateTime)), buf.String())
174+
AssertEqual(t, fmt.Sprintf("%s INF foobar\n", now.Format(time.DateTime)), buf.String())
162175
}
163176

164177
func TestHandler_Err(t *testing.T) {

0 commit comments

Comments
 (0)