Skip to content

Commit 7d9db06

Browse files
authored
Allow setting floating point precision in JSON. (#663)
1 parent e5aa7e3 commit 7d9db06

13 files changed

+101
-84
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,10 @@ Some settings can be changed and will be applied to all loggers:
642642
* `zerolog.DurationFieldUnit`: Can be set to customize the unit for time.Duration type fields added by `Dur` (default: `time.Millisecond`).
643643
* `zerolog.DurationFieldInteger`: If set to `true`, `Dur` fields are formatted as integers instead of floats (default: `false`).
644644
* `zerolog.ErrorHandler`: Called whenever zerolog fails to write an event on its output. If not set, an error is printed on the stderr. This handler must be thread safe and non-blocking.
645+
* `zerolog.FloatingPointPrecision`: If set to a value other than -1, controls the number
646+
of digits when formatting float numbers in JSON. See
647+
[strconv.FormatFloat](https://pkg.go.dev/strconv#FormatFloat)
648+
for more details.
645649

646650
## Field Types
647651

array.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,13 @@ func (a *Array) Uint64(i uint64) *Array {
183183

184184
// Float32 appends f as a float32 to the array.
185185
func (a *Array) Float32(f float32) *Array {
186-
a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f)
186+
a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f, FloatingPointPrecision)
187187
return a
188188
}
189189

190190
// Float64 appends f as a float64 to the array.
191191
func (a *Array) Float64(f float64) *Array {
192-
a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f)
192+
a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f, FloatingPointPrecision)
193193
return a
194194
}
195195

@@ -201,7 +201,7 @@ func (a *Array) Time(t time.Time) *Array {
201201

202202
// Dur appends d to the array.
203203
func (a *Array) Dur(d time.Duration) *Array {
204-
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
204+
a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
205205
return a
206206
}
207207

context.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -325,25 +325,25 @@ func (c Context) Uints64(key string, i []uint64) Context {
325325

326326
// Float32 adds the field key with f as a float32 to the logger context.
327327
func (c Context) Float32(key string, f float32) Context {
328-
c.l.context = enc.AppendFloat32(enc.AppendKey(c.l.context, key), f)
328+
c.l.context = enc.AppendFloat32(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
329329
return c
330330
}
331331

332332
// Floats32 adds the field key with f as a []float32 to the logger context.
333333
func (c Context) Floats32(key string, f []float32) Context {
334-
c.l.context = enc.AppendFloats32(enc.AppendKey(c.l.context, key), f)
334+
c.l.context = enc.AppendFloats32(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
335335
return c
336336
}
337337

338338
// Float64 adds the field key with f as a float64 to the logger context.
339339
func (c Context) Float64(key string, f float64) Context {
340-
c.l.context = enc.AppendFloat64(enc.AppendKey(c.l.context, key), f)
340+
c.l.context = enc.AppendFloat64(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
341341
return c
342342
}
343343

344344
// Floats64 adds the field key with f as a []float64 to the logger context.
345345
func (c Context) Floats64(key string, f []float64) Context {
346-
c.l.context = enc.AppendFloats64(enc.AppendKey(c.l.context, key), f)
346+
c.l.context = enc.AppendFloats64(enc.AppendKey(c.l.context, key), f, FloatingPointPrecision)
347347
return c
348348
}
349349

@@ -379,13 +379,13 @@ func (c Context) Times(key string, t []time.Time) Context {
379379

380380
// Dur adds the fields key with d divided by unit and stored as a float.
381381
func (c Context) Dur(key string, d time.Duration) Context {
382-
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
382+
c.l.context = enc.AppendDuration(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
383383
return c
384384
}
385385

386386
// Durs adds the fields key with d divided by unit and stored as a float.
387387
func (c Context) Durs(key string, d []time.Duration) Context {
388-
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger)
388+
c.l.context = enc.AppendDurations(enc.AppendKey(c.l.context, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
389389
return c
390390
}
391391

encoder.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ type encoder interface {
1313
AppendBool(dst []byte, val bool) []byte
1414
AppendBools(dst []byte, vals []bool) []byte
1515
AppendBytes(dst, s []byte) []byte
16-
AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte
17-
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte
16+
AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte
17+
AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte
1818
AppendEndMarker(dst []byte) []byte
19-
AppendFloat32(dst []byte, val float32) []byte
20-
AppendFloat64(dst []byte, val float64) []byte
21-
AppendFloats32(dst []byte, vals []float32) []byte
22-
AppendFloats64(dst []byte, vals []float64) []byte
19+
AppendFloat32(dst []byte, val float32, precision int) []byte
20+
AppendFloat64(dst []byte, val float64, precision int) []byte
21+
AppendFloats32(dst []byte, vals []float32, precision int) []byte
22+
AppendFloats64(dst []byte, vals []float64, precision int) []byte
2323
AppendHex(dst, s []byte) []byte
2424
AppendIPAddr(dst []byte, ip net.IP) []byte
2525
AppendIPPrefix(dst []byte, pfx net.IPNet) []byte

event.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ func (e *Event) Float32(key string, f float32) *Event {
644644
if e == nil {
645645
return e
646646
}
647-
e.buf = enc.AppendFloat32(enc.AppendKey(e.buf, key), f)
647+
e.buf = enc.AppendFloat32(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
648648
return e
649649
}
650650

@@ -653,7 +653,7 @@ func (e *Event) Floats32(key string, f []float32) *Event {
653653
if e == nil {
654654
return e
655655
}
656-
e.buf = enc.AppendFloats32(enc.AppendKey(e.buf, key), f)
656+
e.buf = enc.AppendFloats32(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
657657
return e
658658
}
659659

@@ -662,7 +662,7 @@ func (e *Event) Float64(key string, f float64) *Event {
662662
if e == nil {
663663
return e
664664
}
665-
e.buf = enc.AppendFloat64(enc.AppendKey(e.buf, key), f)
665+
e.buf = enc.AppendFloat64(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
666666
return e
667667
}
668668

@@ -671,7 +671,7 @@ func (e *Event) Floats64(key string, f []float64) *Event {
671671
if e == nil {
672672
return e
673673
}
674-
e.buf = enc.AppendFloats64(enc.AppendKey(e.buf, key), f)
674+
e.buf = enc.AppendFloats64(enc.AppendKey(e.buf, key), f, FloatingPointPrecision)
675675
return e
676676
}
677677

@@ -713,7 +713,7 @@ func (e *Event) Dur(key string, d time.Duration) *Event {
713713
if e == nil {
714714
return e
715715
}
716-
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
716+
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
717717
return e
718718
}
719719

@@ -724,7 +724,7 @@ func (e *Event) Durs(key string, d []time.Duration) *Event {
724724
if e == nil {
725725
return e
726726
}
727-
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
727+
e.buf = enc.AppendDurations(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
728728
return e
729729
}
730730

@@ -739,7 +739,7 @@ func (e *Event) TimeDiff(key string, t time.Time, start time.Time) *Event {
739739
if t.After(start) {
740740
d = t.Sub(start)
741741
}
742-
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger)
742+
e.buf = enc.AppendDuration(enc.AppendKey(e.buf, key), d, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
743743
return e
744744
}
745745

fields.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -139,13 +139,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
139139
case uint64:
140140
dst = enc.AppendUint64(dst, val)
141141
case float32:
142-
dst = enc.AppendFloat32(dst, val)
142+
dst = enc.AppendFloat32(dst, val, FloatingPointPrecision)
143143
case float64:
144-
dst = enc.AppendFloat64(dst, val)
144+
dst = enc.AppendFloat64(dst, val, FloatingPointPrecision)
145145
case time.Time:
146146
dst = enc.AppendTime(dst, val, TimeFieldFormat)
147147
case time.Duration:
148-
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
148+
dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
149149
case *string:
150150
if val != nil {
151151
dst = enc.AppendString(dst, *val)
@@ -220,13 +220,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
220220
}
221221
case *float32:
222222
if val != nil {
223-
dst = enc.AppendFloat32(dst, *val)
223+
dst = enc.AppendFloat32(dst, *val, FloatingPointPrecision)
224224
} else {
225225
dst = enc.AppendNil(dst)
226226
}
227227
case *float64:
228228
if val != nil {
229-
dst = enc.AppendFloat64(dst, *val)
229+
dst = enc.AppendFloat64(dst, *val, FloatingPointPrecision)
230230
} else {
231231
dst = enc.AppendNil(dst)
232232
}
@@ -238,7 +238,7 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
238238
}
239239
case *time.Duration:
240240
if val != nil {
241-
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
241+
dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
242242
} else {
243243
dst = enc.AppendNil(dst)
244244
}
@@ -267,13 +267,13 @@ func appendFieldList(dst []byte, kvList []interface{}, stack bool) []byte {
267267
case []uint64:
268268
dst = enc.AppendUints64(dst, val)
269269
case []float32:
270-
dst = enc.AppendFloats32(dst, val)
270+
dst = enc.AppendFloats32(dst, val, FloatingPointPrecision)
271271
case []float64:
272-
dst = enc.AppendFloats64(dst, val)
272+
dst = enc.AppendFloats64(dst, val, FloatingPointPrecision)
273273
case []time.Time:
274274
dst = enc.AppendTimes(dst, val, TimeFieldFormat)
275275
case []time.Duration:
276-
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
276+
dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger, FloatingPointPrecision)
277277
case nil:
278278
dst = enc.AppendNil(dst)
279279
case net.IP:

globals.go

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ var (
151151
// TriggerLevelWriterBufferReuseLimit is a limit in bytes that a buffer is dropped
152152
// from the TriggerLevelWriter buffer pool if the buffer grows above the limit.
153153
TriggerLevelWriterBufferReuseLimit = 64 * 1024
154+
155+
// FloatingPointPrecision, if set to a value other than -1, controls the number
156+
// of digits when formatting float numbers in JSON. See strconv.FormatFloat for
157+
// more details.
158+
FloatingPointPrecision = -1
154159
)
155160

156161
var (

internal/cbor/time.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (e Encoder) appendFloatTimestamp(dst []byte, t time.Time) []byte {
2929
nanos := t.Nanosecond()
3030
var val float64
3131
val = float64(secs)*1.0 + float64(nanos)*1e-9
32-
return e.AppendFloat64(dst, val)
32+
return e.AppendFloat64(dst, val, -1)
3333
}
3434

3535
// AppendTime encodes and adds a timestamp to the dst byte array.
@@ -64,17 +64,17 @@ func (e Encoder) AppendTimes(dst []byte, vals []time.Time, unused string) []byte
6464
// AppendDuration encodes and adds a duration to the dst byte array.
6565
// useInt field indicates whether to store the duration as seconds (integer) or
6666
// as seconds+nanoseconds (float).
67-
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
67+
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, unused int) []byte {
6868
if useInt {
6969
return e.AppendInt64(dst, int64(d/unit))
7070
}
71-
return e.AppendFloat64(dst, float64(d)/float64(unit))
71+
return e.AppendFloat64(dst, float64(d)/float64(unit), unused)
7272
}
7373

7474
// AppendDurations encodes and adds an array of durations to the dst byte array.
7575
// useInt field indicates whether to store the duration as seconds (integer) or
7676
// as seconds+nanoseconds (float).
77-
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
77+
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, unused int) []byte {
7878
major := majorTypeArray
7979
l := len(vals)
8080
if l == 0 {
@@ -87,7 +87,7 @@ func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Dur
8787
dst = appendCborTypePrefix(dst, major, uint64(l))
8888
}
8989
for _, d := range vals {
90-
dst = e.AppendDuration(dst, d, unit, useInt)
90+
dst = e.AppendDuration(dst, d, unit, useInt, unused)
9191
}
9292
return dst
9393
}

internal/cbor/types.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ func (e Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
352352
}
353353

354354
// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
355-
func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
355+
func (Encoder) AppendFloat32(dst []byte, val float32, unused int) []byte {
356356
switch {
357357
case math.IsNaN(float64(val)):
358358
return append(dst, "\xfa\x7f\xc0\x00\x00"...)
@@ -372,7 +372,7 @@ func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
372372
}
373373

374374
// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
375-
func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
375+
func (e Encoder) AppendFloats32(dst []byte, vals []float32, unused int) []byte {
376376
major := majorTypeArray
377377
l := len(vals)
378378
if l == 0 {
@@ -385,13 +385,13 @@ func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
385385
dst = appendCborTypePrefix(dst, major, uint64(l))
386386
}
387387
for _, v := range vals {
388-
dst = e.AppendFloat32(dst, v)
388+
dst = e.AppendFloat32(dst, v, unused)
389389
}
390390
return dst
391391
}
392392

393393
// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
394-
func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
394+
func (Encoder) AppendFloat64(dst []byte, val float64, unused int) []byte {
395395
switch {
396396
case math.IsNaN(val):
397397
return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
@@ -412,7 +412,7 @@ func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
412412
}
413413

414414
// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
415-
func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
415+
func (e Encoder) AppendFloats64(dst []byte, vals []float64, unused int) []byte {
416416
major := majorTypeArray
417417
l := len(vals)
418418
if l == 0 {
@@ -425,7 +425,7 @@ func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
425425
dst = appendCborTypePrefix(dst, major, uint64(l))
426426
}
427427
for _, v := range vals {
428-
dst = e.AppendFloat64(dst, v)
428+
dst = e.AppendFloat64(dst, v, unused)
429429
}
430430
return dst
431431
}

internal/cbor/types_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var float32TestCases = []struct {
169169

170170
func TestAppendFloat32(t *testing.T) {
171171
for _, tc := range float32TestCases {
172-
s := enc.AppendFloat32([]byte{}, tc.val)
172+
s := enc.AppendFloat32([]byte{}, tc.val, -1)
173173
got := string(s)
174174
if got != tc.binary {
175175
t.Errorf("AppendFloat32(%f)=0x%s, want: 0x%s",
@@ -306,9 +306,9 @@ func BenchmarkAppendFloat(b *testing.B) {
306306
for i := 0; i < b.N; i++ {
307307
switch str.sz {
308308
case 4:
309-
_ = enc.AppendFloat32(buf, float32(str.val))
309+
_ = enc.AppendFloat32(buf, float32(str.val), -1)
310310
case 8:
311-
_ = enc.AppendFloat64(buf, str.val)
311+
_ = enc.AppendFloat64(buf, str.val, -1)
312312
}
313313
}
314314
})

internal/json/time.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -88,24 +88,24 @@ func appendUnixNanoTimes(dst []byte, vals []time.Time, div int64) []byte {
8888

8989
// AppendDuration formats the input duration with the given unit & format
9090
// and appends the encoded string to the input byte slice.
91-
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
91+
func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool, precision int) []byte {
9292
if useInt {
9393
return strconv.AppendInt(dst, int64(d/unit), 10)
9494
}
95-
return e.AppendFloat64(dst, float64(d)/float64(unit))
95+
return e.AppendFloat64(dst, float64(d)/float64(unit), precision)
9696
}
9797

9898
// AppendDurations formats the input durations with the given unit & format
9999
// and appends the encoded string list to the input byte slice.
100-
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
100+
func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool, precision int) []byte {
101101
if len(vals) == 0 {
102102
return append(dst, '[', ']')
103103
}
104104
dst = append(dst, '[')
105-
dst = e.AppendDuration(dst, vals[0], unit, useInt)
105+
dst = e.AppendDuration(dst, vals[0], unit, useInt, precision)
106106
if len(vals) > 1 {
107107
for _, d := range vals[1:] {
108-
dst = e.AppendDuration(append(dst, ','), d, unit, useInt)
108+
dst = e.AppendDuration(append(dst, ','), d, unit, useInt, precision)
109109
}
110110
}
111111
dst = append(dst, ']')

0 commit comments

Comments
 (0)