Compare commits

..

2 Commits

Author SHA1 Message Date
f960fcc768 chore: upgrade dependencies 2023-10-15 11:34:50 +02:00
fb20ef0d06 feat: implement copilot drive mode 2023-10-15 11:33:10 +02:00
24 changed files with 674 additions and 433 deletions

4
go.mod
View File

@ -4,10 +4,10 @@ go 1.21
require ( require (
github.com/cyrilix/robocar-base v0.1.8 github.com/cyrilix/robocar-base v0.1.8
github.com/cyrilix/robocar-protobuf/go v1.3.1 github.com/cyrilix/robocar-protobuf/go v1.4.0
github.com/eclipse/paho.mqtt.golang v1.4.3 github.com/eclipse/paho.mqtt.golang v1.4.3
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
go.uber.org/zap v1.25.0 go.uber.org/zap v1.26.0
google.golang.org/protobuf v1.31.0 google.golang.org/protobuf v1.31.0
) )

10
go.sum
View File

@ -1,9 +1,7 @@
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cyrilix/robocar-base v0.1.8 h1:9hfH9rCcyGXR0dtESIhI9tCrK9juq+dSnJXCxCF2LVw= github.com/cyrilix/robocar-base v0.1.8 h1:9hfH9rCcyGXR0dtESIhI9tCrK9juq+dSnJXCxCF2LVw=
github.com/cyrilix/robocar-base v0.1.8/go.mod h1:oJnfYjoz2PX16BD8I8LJ14kRQt1zbFb7XaUHtUEZgjg= github.com/cyrilix/robocar-base v0.1.8/go.mod h1:oJnfYjoz2PX16BD8I8LJ14kRQt1zbFb7XaUHtUEZgjg=
github.com/cyrilix/robocar-protobuf/go v1.3.1 h1:SSKf2g3H7V0PBaecowk6GuWLHhDlMQbo6q6PlgJcZsA= github.com/cyrilix/robocar-protobuf/go v1.4.0 h1:ZMN2zjn2iplsbHoBrjiI7d3HdNutWUB+NcVDh2mFcqM=
github.com/cyrilix/robocar-protobuf/go v1.3.1/go.mod h1:69ZGmxS2JufIxGZPEKvAMZj5b1fVMVG3QTyFlCCHGtg= github.com/cyrilix/robocar-protobuf/go v1.4.0/go.mod h1:69ZGmxS2JufIxGZPEKvAMZj5b1fVMVG3QTyFlCCHGtg=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
@ -23,8 +21,8 @@ go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=

View File

@ -287,7 +287,12 @@ func (a *Part) processChannel6(v string) {
// No value, ignore it // No value, ignore it
return return
} }
if value > 1800 { if value <= 1800 && value > 1200 {
if a.driveMode != events.DriveMode_COPILOT {
zap.S().Infof("Update channel 6 'drive-mode' with value %v, new user_mode: %v", value, events.DriveMode_PILOT)
a.driveMode = events.DriveMode_COPILOT
}
} else if value > 1800 {
if a.driveMode != events.DriveMode_PILOT { if a.driveMode != events.DriveMode_PILOT {
zap.S().Infof("Update channel 6 'drive-mode' with value %v, new user_mode: %v", value, events.DriveMode_PILOT) zap.S().Infof("Update channel 6 'drive-mode' with value %v, new user_mode: %v", value, events.DriveMode_PILOT)
a.driveMode = events.DriveMode_PILOT a.driveMode = events.DriveMode_PILOT

View File

@ -118,6 +118,10 @@ func TestArduinoPart_Update(t *testing.T) {
{"DriveMode: user", {"DriveMode: user",
fmt.Sprintf("12390,%d,%d,%d,%d,%d,%d,%d,%d,%d,50\n", channel1, channel2, channel3, channel4, channel5, 1003, channel7, channel8, channel9), fmt.Sprintf("12390,%d,%d,%d,%d,%d,%d,%d,%d,%d,50\n", channel1, channel2, channel3, channel4, channel5, 1003, channel7, channel8, channel9),
defaultPwmThrottleConfig, -1., -1., events.DriveMode_USER, false}, defaultPwmThrottleConfig, -1., -1., events.DriveMode_USER, false},
// DriveMode: copilot
{"DriveMode: copilot",
fmt.Sprintf("12390,%d,%d,%d,%d,%d,%d,%d,%d,%d,50\n", channel1, channel2, channel3, channel4, channel5, 1250, channel7, channel8, channel9),
defaultPwmThrottleConfig, -1., -1., events.DriveMode_COPILOT, false},
{"Sterring: over left", fmt.Sprintf("12395,%d,%d,%d,%d,%d,%d,%d,%d,%d,50\n", 99, channel2, channel3, channel4, channel5, channel6, channel7, channel8, channel9), {"Sterring: over left", fmt.Sprintf("12395,%d,%d,%d,%d,%d,%d,%d,%d,%d,50\n", 99, channel2, channel3, channel4, channel5, channel6, channel7, channel8, channel9),
defaultPwmThrottleConfig, -1., -1., events.DriveMode_USER, false}, defaultPwmThrottleConfig, -1., -1., events.DriveMode_USER, false},

View File

@ -79,6 +79,7 @@ const (
DriveMode_INVALID DriveMode = 0 DriveMode_INVALID DriveMode = 0
DriveMode_USER DriveMode = 1 DriveMode_USER DriveMode = 1
DriveMode_PILOT DriveMode = 2 DriveMode_PILOT DriveMode = 2
DriveMode_COPILOT DriveMode = 3
) )
// Enum value maps for DriveMode. // Enum value maps for DriveMode.
@ -87,11 +88,13 @@ var (
0: "INVALID", 0: "INVALID",
1: "USER", 1: "USER",
2: "PILOT", 2: "PILOT",
3: "COPILOT",
} }
DriveMode_value = map[string]int32{ DriveMode_value = map[string]int32{
"INVALID": 0, "INVALID": 0,
"USER": 1, "USER": 1,
"PILOT": 2, "PILOT": 2,
"COPILOT": 3,
} }
) )
@ -1114,14 +1117,15 @@ var file_events_events_proto_rawDesc = []byte{
0x38, 0x0a, 0x09, 0x53, 0x70, 0x65, 0x65, 0x64, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x38, 0x0a, 0x09, 0x53, 0x70, 0x65, 0x65, 0x64, 0x5a, 0x6f, 0x6e, 0x65, 0x12, 0x0b, 0x0a, 0x07,
0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4c, 0x4f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x4c, 0x4f,
0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x57, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12,
0x08, 0x0a, 0x04, 0x46, 0x41, 0x53, 0x54, 0x10, 0x03, 0x2a, 0x2d, 0x0a, 0x09, 0x44, 0x72, 0x69, 0x08, 0x0a, 0x04, 0x46, 0x41, 0x53, 0x54, 0x10, 0x03, 0x2a, 0x3a, 0x0a, 0x09, 0x44, 0x72, 0x69,
0x76, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49,
0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x09, 0x0a,
0x05, 0x50, 0x49, 0x4c, 0x4f, 0x54, 0x10, 0x02, 0x2a, 0x32, 0x0a, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x05, 0x50, 0x49, 0x4c, 0x4f, 0x54, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x50, 0x49,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x4c, 0x4f, 0x54, 0x10, 0x03, 0x2a, 0x32, 0x0a, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x4f, 0x62, 0x6a,
0x07, 0x0a, 0x03, 0x43, 0x41, 0x52, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x55, 0x4d, 0x50, 0x65, 0x63, 0x74, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4e, 0x59, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03,
0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x4c, 0x4f, 0x54, 0x10, 0x03, 0x42, 0x0a, 0x5a, 0x08, 0x43, 0x41, 0x52, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x55, 0x4d, 0x50, 0x10, 0x02, 0x12,
0x2e, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x08, 0x0a, 0x04, 0x50, 0x4c, 0x4f, 0x54, 0x10, 0x03, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

77
vendor/go.uber.org/zap/.golangci.yml generated vendored Normal file
View File

@ -0,0 +1,77 @@
output:
# Make output more digestible with quickfix in vim/emacs/etc.
sort-results: true
print-issued-lines: false
linters:
# We'll track the golangci-lint default linters manually
# instead of letting them change without our control.
disable-all: true
enable:
# golangci-lint defaults:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
# Our own extras:
- gofmt
- nolintlint # lints nolint directives
- revive
linters-settings:
govet:
# These govet checks are disabled by default, but they're useful.
enable:
- niliness
- reflectvaluecompare
- sortslice
- unusedwrite
errcheck:
exclude-functions:
# These methods can not fail.
# They operate on an in-memory buffer.
- (*go.uber.org/zap/buffer.Buffer).Write
- (*go.uber.org/zap/buffer.Buffer).WriteByte
- (*go.uber.org/zap/buffer.Buffer).WriteString
- (*go.uber.org/zap/zapio.Writer).Close
- (*go.uber.org/zap/zapio.Writer).Sync
- (*go.uber.org/zap/zapio.Writer).Write
# Write to zapio.Writer cannot fail,
# so io.WriteString on it cannot fail.
- io.WriteString(*go.uber.org/zap/zapio.Writer)
# Writing a plain string to a fmt.State cannot fail.
- io.WriteString(fmt.State)
issues:
# Print all issues reported by all linters.
max-issues-per-linter: 0
max-same-issues: 0
# Don't ignore some of the issues that golangci-lint considers okay.
# This includes documenting all exported entities.
exclude-use-default: false
exclude-rules:
# Don't warn on unused parameters.
# Parameter names are useful; replacing them with '_' is undesirable.
- linters: [revive]
text: 'unused-parameter: parameter \S+ seems to be unused, consider removing or renaming it as _'
# staticcheck already has smarter checks for empty blocks.
# revive's empty-block linter has false positives.
# For example, as of writing this, the following is not allowed.
# for foo() { }
- linters: [revive]
text: 'empty-block: this block is empty, you can remove it'
# Ignore logger.Sync() errcheck failures in example_test.go
# since those are intended to be uncomplicated examples.
- linters: [errcheck]
path: example_test.go
text: 'Error return value of `logger.Sync` is not checked'

221
vendor/go.uber.org/zap/CHANGELOG.md generated vendored
View File

@ -1,7 +1,18 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.26.0 (14 Sep 2023)
Enhancements:
* [#1319][]: Add `WithLazy` method to `Logger` which lazily evaluates the structured
context.
* [#1350][]: String encoding is much (~50%) faster now.
Thanks to @jquirke, @cdvr1993 for their contributions to this release.
[#1319]: https://github.com/uber-go/zap/pull/1319
[#1350]: https://github.com/uber-go/zap/pull/1350
## 1.25.0 (1 Aug 2023) ## 1.25.0 (1 Aug 2023)
@ -48,7 +59,6 @@ Enhancements:
[#1147]: https://github.com/uber-go/zap/pull/1147 [#1147]: https://github.com/uber-go/zap/pull/1147
[#1155]: https://github.com/uber-go/zap/pull/1155 [#1155]: https://github.com/uber-go/zap/pull/1155
## 1.22.0 (8 Aug 2022) ## 1.22.0 (8 Aug 2022)
Enhancements: Enhancements:
@ -197,6 +207,16 @@ Enhancements:
Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release. Thanks to @ash2k, @FMLS, @jimmystewpot, @Oncilla, @tsoslow, @tylitianrui, @withshubh, and @wziww for their contributions to this release.
[#865]: https://github.com/uber-go/zap/pull/865
[#867]: https://github.com/uber-go/zap/pull/867
[#881]: https://github.com/uber-go/zap/pull/881
[#903]: https://github.com/uber-go/zap/pull/903
[#912]: https://github.com/uber-go/zap/pull/912
[#913]: https://github.com/uber-go/zap/pull/913
[#928]: https://github.com/uber-go/zap/pull/928
[#931]: https://github.com/uber-go/zap/pull/931
[#936]: https://github.com/uber-go/zap/pull/936
## 1.16.0 (1 Sep 2020) ## 1.16.0 (1 Sep 2020)
Bugfixes: Bugfixes:
@ -218,6 +238,17 @@ Enhancements:
Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release. Thanks to @SteelPhase, @tmshn, @lixingwang, @wyxloading, @moul, @segevfiner, @andy-retailnext and @jcorbin for their contributions to this release.
[#629]: https://github.com/uber-go/zap/pull/629
[#697]: https://github.com/uber-go/zap/pull/697
[#828]: https://github.com/uber-go/zap/pull/828
[#835]: https://github.com/uber-go/zap/pull/835
[#843]: https://github.com/uber-go/zap/pull/843
[#844]: https://github.com/uber-go/zap/pull/844
[#852]: https://github.com/uber-go/zap/pull/852
[#854]: https://github.com/uber-go/zap/pull/854
[#861]: https://github.com/uber-go/zap/pull/861
[#862]: https://github.com/uber-go/zap/pull/862
## 1.15.0 (23 Apr 2020) ## 1.15.0 (23 Apr 2020)
Bugfixes: Bugfixes:
@ -234,6 +265,11 @@ Enhancements:
Thanks to @danielbprice for their contributions to this release. Thanks to @danielbprice for their contributions to this release.
[#804]: https://github.com/uber-go/zap/pull/804
[#812]: https://github.com/uber-go/zap/pull/812
[#806]: https://github.com/uber-go/zap/pull/806
[#813]: https://github.com/uber-go/zap/pull/813
## 1.14.1 (14 Mar 2020) ## 1.14.1 (14 Mar 2020)
Bugfixes: Bugfixes:
@ -246,6 +282,10 @@ Bugfixes:
Thanks to @YashishDua for their contributions to this release. Thanks to @YashishDua for their contributions to this release.
[#791]: https://github.com/uber-go/zap/pull/791
[#795]: https://github.com/uber-go/zap/pull/795
[#799]: https://github.com/uber-go/zap/pull/799
## 1.14.0 (20 Feb 2020) ## 1.14.0 (20 Feb 2020)
Enhancements: Enhancements:
@ -256,6 +296,11 @@ Enhancements:
Thanks to @caibirdme for their contributions to this release. Thanks to @caibirdme for their contributions to this release.
[#771]: https://github.com/uber-go/zap/pull/771
[#773]: https://github.com/uber-go/zap/pull/773
[#775]: https://github.com/uber-go/zap/pull/775
[#786]: https://github.com/uber-go/zap/pull/786
## 1.13.0 (13 Nov 2019) ## 1.13.0 (13 Nov 2019)
Enhancements: Enhancements:
@ -264,11 +309,15 @@ Enhancements:
Thanks to @jbizzle for their contributions to this release. Thanks to @jbizzle for their contributions to this release.
[#758]: https://github.com/uber-go/zap/pull/758
## 1.12.0 (29 Oct 2019) ## 1.12.0 (29 Oct 2019)
Enhancements: Enhancements:
* [#751][]: Migrate to Go modules. * [#751][]: Migrate to Go modules.
[#751]: https://github.com/uber-go/zap/pull/751
## 1.11.0 (21 Oct 2019) ## 1.11.0 (21 Oct 2019)
Enhancements: Enhancements:
@ -277,6 +326,9 @@ Enhancements:
Thanks to @juicemia, @uhthomas for their contributions to this release. Thanks to @juicemia, @uhthomas for their contributions to this release.
[#725]: https://github.com/uber-go/zap/pull/725
[#736]: https://github.com/uber-go/zap/pull/736
## 1.10.0 (29 Apr 2019) ## 1.10.0 (29 Apr 2019)
Bugfixes: Bugfixes:
@ -294,12 +346,20 @@ Enhancements:
Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions Thanks to @iaroslav-ciupin, @lelenanam, @joa, @NWilson for their contributions
to this release. to this release.
[#657]: https://github.com/uber-go/zap/pull/657
[#706]: https://github.com/uber-go/zap/pull/706
[#610]: https://github.com/uber-go/zap/pull/610
[#675]: https://github.com/uber-go/zap/pull/675
[#704]: https://github.com/uber-go/zap/pull/704
## v1.9.1 (06 Aug 2018) ## v1.9.1 (06 Aug 2018)
Bugfixes: Bugfixes:
* [#614][]: MapObjectEncoder should not ignore empty slices. * [#614][]: MapObjectEncoder should not ignore empty slices.
[#614]: https://github.com/uber-go/zap/pull/614
## v1.9.0 (19 Jul 2018) ## v1.9.0 (19 Jul 2018)
Enhancements: Enhancements:
@ -309,6 +369,10 @@ Enhancements:
Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and Thanks to @nfarah86, @AlekSi, @JeanMertz, @philippgille, @etsangsplk, and
@dimroc for their contributions to this release. @dimroc for their contributions to this release.
[#602]: https://github.com/uber-go/zap/pull/602
[#572]: https://github.com/uber-go/zap/pull/572
[#606]: https://github.com/uber-go/zap/pull/606
## v1.8.0 (13 Apr 2018) ## v1.8.0 (13 Apr 2018)
Enhancements: Enhancements:
@ -322,11 +386,18 @@ Bugfixes:
Thanks to @DiSiqueira and @djui for their contributions to this release. Thanks to @DiSiqueira and @djui for their contributions to this release.
[#508]: https://github.com/uber-go/zap/pull/508
[#518]: https://github.com/uber-go/zap/pull/518
[#577]: https://github.com/uber-go/zap/pull/577
[#574]: https://github.com/uber-go/zap/pull/574
## v1.7.1 (25 Sep 2017) ## v1.7.1 (25 Sep 2017)
Bugfixes: Bugfixes:
* [#504][]: Store strings when using AddByteString with the map encoder. * [#504][]: Store strings when using AddByteString with the map encoder.
[#504]: https://github.com/uber-go/zap/pull/504
## v1.7.0 (21 Sep 2017) ## v1.7.0 (21 Sep 2017)
Enhancements: Enhancements:
@ -334,6 +405,8 @@ Enhancements:
* [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user * [#487][]: Add `NewStdLogAt`, which extends `NewStdLog` by allowing the user
to specify the level of the logged messages. to specify the level of the logged messages.
[#487]: https://github.com/uber-go/zap/pull/487
## v1.6.0 (30 Aug 2017) ## v1.6.0 (30 Aug 2017)
Enhancements: Enhancements:
@ -342,6 +415,9 @@ Enhancements:
* [#490][]: Add a `ContextMap` method to observer logs for simpler * [#490][]: Add a `ContextMap` method to observer logs for simpler
field validation in tests. field validation in tests.
[#490]: https://github.com/uber-go/zap/pull/490
[#491]: https://github.com/uber-go/zap/pull/491
## v1.5.0 (22 Jul 2017) ## v1.5.0 (22 Jul 2017)
Enhancements: Enhancements:
@ -355,6 +431,11 @@ Bugfixes:
Thanks to @richard-tunein and @pavius for their contributions to this release. Thanks to @richard-tunein and @pavius for their contributions to this release.
[#477]: https://github.com/uber-go/zap/pull/477
[#465]: https://github.com/uber-go/zap/pull/465
[#460]: https://github.com/uber-go/zap/pull/460
[#470]: https://github.com/uber-go/zap/pull/470
## v1.4.1 (08 Jun 2017) ## v1.4.1 (08 Jun 2017)
This release fixes two bugs. This release fixes two bugs.
@ -364,6 +445,9 @@ Bugfixes:
* [#435][]: Support a variety of case conventions when unmarshaling levels. * [#435][]: Support a variety of case conventions when unmarshaling levels.
* [#444][]: Fix a panic in the observer. * [#444][]: Fix a panic in the observer.
[#435]: https://github.com/uber-go/zap/pull/435
[#444]: https://github.com/uber-go/zap/pull/444
## v1.4.0 (12 May 2017) ## v1.4.0 (12 May 2017)
This release adds a few small features and is fully backward-compatible. This release adds a few small features and is fully backward-compatible.
@ -376,6 +460,10 @@ Enhancements:
* [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a * [#431][]: Make `zap.AtomicLevel` implement `fmt.Stringer`, which makes a
variety of operations a bit simpler. variety of operations a bit simpler.
[#424]: https://github.com/uber-go/zap/pull/424
[#425]: https://github.com/uber-go/zap/pull/425
[#431]: https://github.com/uber-go/zap/pull/431
## v1.3.0 (25 Apr 2017) ## v1.3.0 (25 Apr 2017)
This release adds an enhancement to zap's testing helpers as well as the This release adds an enhancement to zap's testing helpers as well as the
@ -387,6 +475,9 @@ Enhancements:
particularly useful when testing the `SugaredLogger`. particularly useful when testing the `SugaredLogger`.
* [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`. * [#416][]: Make `AtomicLevel` implement `encoding.TextMarshaler`.
[#415]: https://github.com/uber-go/zap/pull/415
[#416]: https://github.com/uber-go/zap/pull/416
## v1.2.0 (13 Apr 2017) ## v1.2.0 (13 Apr 2017)
This release adds a gRPC compatibility wrapper. It is fully backward-compatible. This release adds a gRPC compatibility wrapper. It is fully backward-compatible.
@ -396,6 +487,8 @@ Enhancements:
* [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements * [#402][]: Add a `zapgrpc` package that wraps zap's Logger and implements
`grpclog.Logger`. `grpclog.Logger`.
[#402]: https://github.com/uber-go/zap/pull/402
## v1.1.0 (31 Mar 2017) ## v1.1.0 (31 Mar 2017)
This release fixes two bugs and adds some enhancements to zap's testing helpers. This release fixes two bugs and adds some enhancements to zap's testing helpers.
@ -413,6 +506,10 @@ Enhancements:
Thanks to @moitias for contributing to this release. Thanks to @moitias for contributing to this release.
[#385]: https://github.com/uber-go/zap/pull/385
[#396]: https://github.com/uber-go/zap/pull/396
[#386]: https://github.com/uber-go/zap/pull/386
## v1.0.0 (14 Mar 2017) ## v1.0.0 (14 Mar 2017)
This is zap's first stable release. All exported APIs are now final, and no This is zap's first stable release. All exported APIs are now final, and no
@ -458,6 +555,20 @@ Enhancements:
Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their Thanks to @suyash, @htrendev, @flisky, @Ulexus, and @skipor for their
contributions to this release. contributions to this release.
[#366]: https://github.com/uber-go/zap/pull/366
[#364]: https://github.com/uber-go/zap/pull/364
[#371]: https://github.com/uber-go/zap/pull/371
[#362]: https://github.com/uber-go/zap/pull/362
[#369]: https://github.com/uber-go/zap/pull/369
[#347]: https://github.com/uber-go/zap/pull/347
[#373]: https://github.com/uber-go/zap/pull/373
[#348]: https://github.com/uber-go/zap/pull/348
[#327]: https://github.com/uber-go/zap/pull/327
[#376]: https://github.com/uber-go/zap/pull/376
[#346]: https://github.com/uber-go/zap/pull/346
[#365]: https://github.com/uber-go/zap/pull/365
[#372]: https://github.com/uber-go/zap/pull/372
## v1.0.0-rc.3 (7 Mar 2017) ## v1.0.0-rc.3 (7 Mar 2017)
This is the third release candidate for zap's stable release. There are no This is the third release candidate for zap's stable release. There are no
@ -479,6 +590,11 @@ Enhancements:
Thanks to @ansel1 and @suyash for their contributions to this release. Thanks to @ansel1 and @suyash for their contributions to this release.
[#339]: https://github.com/uber-go/zap/pull/339
[#307]: https://github.com/uber-go/zap/pull/307
[#353]: https://github.com/uber-go/zap/pull/353
[#311]: https://github.com/uber-go/zap/pull/311
## v1.0.0-rc.2 (21 Feb 2017) ## v1.0.0-rc.2 (21 Feb 2017)
This is the second release candidate for zap's stable release. It includes two This is the second release candidate for zap's stable release. It includes two
@ -516,6 +632,15 @@ Enhancements:
Thanks to @skipor and @chapsuk for their contributions to this release. Thanks to @skipor and @chapsuk for their contributions to this release.
[#316]: https://github.com/uber-go/zap/pull/316
[#309]: https://github.com/uber-go/zap/pull/309
[#317]: https://github.com/uber-go/zap/pull/317
[#321]: https://github.com/uber-go/zap/pull/321
[#325]: https://github.com/uber-go/zap/pull/325
[#333]: https://github.com/uber-go/zap/pull/333
[#326]: https://github.com/uber-go/zap/pull/326
[#300]: https://github.com/uber-go/zap/pull/300
## v1.0.0-rc.1 (14 Feb 2017) ## v1.0.0-rc.1 (14 Feb 2017)
This is the first release candidate for zap's stable release. There are multiple This is the first release candidate for zap's stable release. There are multiple
@ -544,95 +669,3 @@ backward compatibility concerns and all functionality is new.
Early zap adopters should pin to the 0.1.x minor version until they're ready to Early zap adopters should pin to the 0.1.x minor version until they're ready to
upgrade to the upcoming stable release. upgrade to the upcoming stable release.
[#316]: https://github.com/uber-go/zap/pull/316
[#309]: https://github.com/uber-go/zap/pull/309
[#317]: https://github.com/uber-go/zap/pull/317
[#321]: https://github.com/uber-go/zap/pull/321
[#325]: https://github.com/uber-go/zap/pull/325
[#333]: https://github.com/uber-go/zap/pull/333
[#326]: https://github.com/uber-go/zap/pull/326
[#300]: https://github.com/uber-go/zap/pull/300
[#339]: https://github.com/uber-go/zap/pull/339
[#307]: https://github.com/uber-go/zap/pull/307
[#353]: https://github.com/uber-go/zap/pull/353
[#311]: https://github.com/uber-go/zap/pull/311
[#366]: https://github.com/uber-go/zap/pull/366
[#364]: https://github.com/uber-go/zap/pull/364
[#371]: https://github.com/uber-go/zap/pull/371
[#362]: https://github.com/uber-go/zap/pull/362
[#369]: https://github.com/uber-go/zap/pull/369
[#347]: https://github.com/uber-go/zap/pull/347
[#373]: https://github.com/uber-go/zap/pull/373
[#348]: https://github.com/uber-go/zap/pull/348
[#327]: https://github.com/uber-go/zap/pull/327
[#376]: https://github.com/uber-go/zap/pull/376
[#346]: https://github.com/uber-go/zap/pull/346
[#365]: https://github.com/uber-go/zap/pull/365
[#372]: https://github.com/uber-go/zap/pull/372
[#385]: https://github.com/uber-go/zap/pull/385
[#396]: https://github.com/uber-go/zap/pull/396
[#386]: https://github.com/uber-go/zap/pull/386
[#402]: https://github.com/uber-go/zap/pull/402
[#415]: https://github.com/uber-go/zap/pull/415
[#416]: https://github.com/uber-go/zap/pull/416
[#424]: https://github.com/uber-go/zap/pull/424
[#425]: https://github.com/uber-go/zap/pull/425
[#431]: https://github.com/uber-go/zap/pull/431
[#435]: https://github.com/uber-go/zap/pull/435
[#444]: https://github.com/uber-go/zap/pull/444
[#477]: https://github.com/uber-go/zap/pull/477
[#465]: https://github.com/uber-go/zap/pull/465
[#460]: https://github.com/uber-go/zap/pull/460
[#470]: https://github.com/uber-go/zap/pull/470
[#487]: https://github.com/uber-go/zap/pull/487
[#490]: https://github.com/uber-go/zap/pull/490
[#491]: https://github.com/uber-go/zap/pull/491
[#504]: https://github.com/uber-go/zap/pull/504
[#508]: https://github.com/uber-go/zap/pull/508
[#518]: https://github.com/uber-go/zap/pull/518
[#577]: https://github.com/uber-go/zap/pull/577
[#574]: https://github.com/uber-go/zap/pull/574
[#602]: https://github.com/uber-go/zap/pull/602
[#572]: https://github.com/uber-go/zap/pull/572
[#606]: https://github.com/uber-go/zap/pull/606
[#614]: https://github.com/uber-go/zap/pull/614
[#657]: https://github.com/uber-go/zap/pull/657
[#706]: https://github.com/uber-go/zap/pull/706
[#610]: https://github.com/uber-go/zap/pull/610
[#675]: https://github.com/uber-go/zap/pull/675
[#704]: https://github.com/uber-go/zap/pull/704
[#725]: https://github.com/uber-go/zap/pull/725
[#736]: https://github.com/uber-go/zap/pull/736
[#751]: https://github.com/uber-go/zap/pull/751
[#758]: https://github.com/uber-go/zap/pull/758
[#771]: https://github.com/uber-go/zap/pull/771
[#773]: https://github.com/uber-go/zap/pull/773
[#775]: https://github.com/uber-go/zap/pull/775
[#786]: https://github.com/uber-go/zap/pull/786
[#791]: https://github.com/uber-go/zap/pull/791
[#795]: https://github.com/uber-go/zap/pull/795
[#799]: https://github.com/uber-go/zap/pull/799
[#804]: https://github.com/uber-go/zap/pull/804
[#812]: https://github.com/uber-go/zap/pull/812
[#806]: https://github.com/uber-go/zap/pull/806
[#813]: https://github.com/uber-go/zap/pull/813
[#629]: https://github.com/uber-go/zap/pull/629
[#697]: https://github.com/uber-go/zap/pull/697
[#828]: https://github.com/uber-go/zap/pull/828
[#835]: https://github.com/uber-go/zap/pull/835
[#843]: https://github.com/uber-go/zap/pull/843
[#844]: https://github.com/uber-go/zap/pull/844
[#852]: https://github.com/uber-go/zap/pull/852
[#854]: https://github.com/uber-go/zap/pull/854
[#861]: https://github.com/uber-go/zap/pull/861
[#862]: https://github.com/uber-go/zap/pull/862
[#865]: https://github.com/uber-go/zap/pull/865
[#867]: https://github.com/uber-go/zap/pull/867
[#881]: https://github.com/uber-go/zap/pull/881
[#903]: https://github.com/uber-go/zap/pull/903
[#912]: https://github.com/uber-go/zap/pull/912
[#913]: https://github.com/uber-go/zap/pull/913
[#928]: https://github.com/uber-go/zap/pull/928
[#931]: https://github.com/uber-go/zap/pull/931
[#936]: https://github.com/uber-go/zap/pull/936

78
vendor/go.uber.org/zap/Makefile generated vendored
View File

@ -1,64 +1,62 @@
export GOBIN ?= $(shell pwd)/bin # Directory containing the Makefile.
PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
export GOBIN ?= $(PROJECT_ROOT)/bin
export PATH := $(GOBIN):$(PATH)
REVIVE = $(GOBIN)/revive
STATICCHECK = $(GOBIN)/staticcheck
GOVULNCHECK = $(GOBIN)/govulncheck GOVULNCHECK = $(GOBIN)/govulncheck
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
# Directories containing independent Go modules. # Directories containing independent Go modules.
#
# We track coverage only for the main module.
MODULE_DIRS = . ./exp ./benchmarks ./zapgrpc/internal/test MODULE_DIRS = . ./exp ./benchmarks ./zapgrpc/internal/test
# Many Go tools take file globs or directories as arguments instead of packages. # Directories that we want to track coverage for.
GO_FILES := $(shell \ COVER_DIRS = . ./exp
find . '(' -path '*/.*' -o -path './vendor' ')' -prune \
-o -name '*.go' -print | cut -b3-)
.PHONY: all .PHONY: all
all: lint test all: lint test
.PHONY: lint .PHONY: lint
lint: $(REVIVE) $(STATICCHECK) lint: golangci-lint tidy-lint license-lint
@rm -rf lint.log
@echo "Checking formatting..."
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
@echo "Checking vet..."
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log
@echo "Checking lint..."
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && \
$(REVIVE) -set_exit_status ./... 2>&1) &&) true | tee -a lint.log
@echo "Checking staticcheck..."
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log
@echo "Checking for unresolved FIXMEs..."
@git grep -i fixme | grep -v -e Makefile | tee -a lint.log
@echo "Checking for license headers..."
@./checklicense.sh | tee -a lint.log
@[ ! -s lint.log ]
@echo "Checking 'go mod tidy'..."
@make tidy
@if ! git diff --quiet; then \
echo "'go mod tidy' resulted in changes or working tree is dirty:"; \
git --no-pager diff; \
fi
$(REVIVE): .PHONY: golangci-lint
cd tools && go install github.com/mgechev/revive golangci-lint:
@$(foreach mod,$(MODULE_DIRS), \
(cd $(mod) && \
echo "[lint] golangci-lint: $(mod)" && \
golangci-lint run --path-prefix $(mod)) &&) true
.PHONY: tidy
tidy:
@$(foreach dir,$(MODULE_DIRS), \
(cd $(dir) && go mod tidy) &&) true
.PHONY: tidy-lint
tidy-lint:
@$(foreach mod,$(MODULE_DIRS), \
(cd $(mod) && \
echo "[lint] tidy: $(mod)" && \
go mod tidy && \
git diff --exit-code -- go.mod go.sum) &&) true
.PHONY: license-lint
license-lint:
./checklicense.sh
$(GOVULNCHECK): $(GOVULNCHECK):
cd tools && go install golang.org/x/vuln/cmd/govulncheck cd tools && go install golang.org/x/vuln/cmd/govulncheck
$(STATICCHECK):
cd tools && go install honnef.co/go/tools/cmd/staticcheck
.PHONY: test .PHONY: test
test: test:
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true @$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go test -race ./...) &&) true
.PHONY: cover .PHONY: cover
cover: cover:
go test -race -coverprofile=cover.out -coverpkg=./... ./... @$(foreach dir,$(COVER_DIRS), ( \
go tool cover -html=cover.out -o cover.html cd $(dir) && \
go test -race -coverprofile=cover.out -coverpkg=./... ./... \
&& go tool cover -html=cover.out -o cover.html) &&) true
.PHONY: bench .PHONY: bench
BENCH ?= . BENCH ?= .
@ -73,10 +71,6 @@ updatereadme:
rm -f README.md rm -f README.md
cat .readme.tmpl | go run internal/readme/readme.go > README.md cat .readme.tmpl | go run internal/readme/readme.go > README.md
.PHONY: tidy
tidy:
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true
.PHONY: vulncheck .PHONY: vulncheck
vulncheck: $(GOVULNCHECK) vulncheck: $(GOVULNCHECK)
$(GOVULNCHECK) ./... $(GOVULNCHECK) ./...

127
vendor/go.uber.org/zap/array.go generated vendored
View File

@ -21,6 +21,7 @@
package zap package zap
import ( import (
"fmt"
"time" "time"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
@ -94,11 +95,137 @@ func Int8s(key string, nums []int8) Field {
return Array(key, int8s(nums)) return Array(key, int8s(nums))
} }
// Objects constructs a field with the given key, holding a list of the
// provided objects that can be marshaled by Zap.
//
// Note that these objects must implement zapcore.ObjectMarshaler directly.
// That is, if you're trying to marshal a []Request, the MarshalLogObject
// method must be declared on the Request type, not its pointer (*Request).
// If it's on the pointer, use ObjectValues.
//
// Given an object that implements MarshalLogObject on the value receiver, you
// can log a slice of those objects with Objects like so:
//
// type Author struct{ ... }
// func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var authors []Author = ...
// logger.Info("loading article", zap.Objects("authors", authors))
//
// Similarly, given a type that implements MarshalLogObject on its pointer
// receiver, you can log a slice of pointers to that object with Objects like
// so:
//
// type Request struct{ ... }
// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var requests []*Request = ...
// logger.Info("sending requests", zap.Objects("requests", requests))
//
// If instead, you have a slice of values of such an object, use the
// ObjectValues constructor.
//
// var requests []Request = ...
// logger.Info("sending requests", zap.ObjectValues("requests", requests))
func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {
return Array(key, objects[T](values))
}
type objects[T zapcore.ObjectMarshaler] []T
func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for _, o := range os {
if err := arr.AppendObject(o); err != nil {
return err
}
}
return nil
}
// ObjectMarshalerPtr is a constraint that specifies that the given type
// implements zapcore.ObjectMarshaler on a pointer receiver.
type ObjectMarshalerPtr[T any] interface {
*T
zapcore.ObjectMarshaler
}
// ObjectValues constructs a field with the given key, holding a list of the
// provided objects, where pointers to these objects can be marshaled by Zap.
//
// Note that pointers to these objects must implement zapcore.ObjectMarshaler.
// That is, if you're trying to marshal a []Request, the MarshalLogObject
// method must be declared on the *Request type, not the value (Request).
// If it's on the value, use Objects.
//
// Given an object that implements MarshalLogObject on the pointer receiver,
// you can log a slice of those objects with ObjectValues like so:
//
// type Request struct{ ... }
// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var requests []Request = ...
// logger.Info("sending requests", zap.ObjectValues("requests", requests))
//
// If instead, you have a slice of pointers of such an object, use the Objects
// field constructor.
//
// var requests []*Request = ...
// logger.Info("sending requests", zap.Objects("requests", requests))
func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field {
return Array(key, objectValues[T, P](values))
}
type objectValues[T any, P ObjectMarshalerPtr[T]] []T
func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for i := range os {
// It is necessary for us to explicitly reference the "P" type.
// We cannot simply pass "&os[i]" to AppendObject because its type
// is "*T", which the type system does not consider as
// implementing ObjectMarshaler.
// Only the type "P" satisfies ObjectMarshaler, which we have
// to convert "*T" to explicitly.
var p P = &os[i]
if err := arr.AppendObject(p); err != nil {
return err
}
}
return nil
}
// Strings constructs a field that carries a slice of strings. // Strings constructs a field that carries a slice of strings.
func Strings(key string, ss []string) Field { func Strings(key string, ss []string) Field {
return Array(key, stringArray(ss)) return Array(key, stringArray(ss))
} }
// Stringers constructs a field with the given key, holding a list of the
// output provided by the value's String method
//
// Given an object that implements String on the value receiver, you
// can log a slice of those objects with Objects like so:
//
// type Request struct{ ... }
// func (a Request) String() string
//
// var requests []Request = ...
// logger.Info("sending requests", zap.Stringers("requests", requests))
//
// Note that these objects must implement fmt.Stringer directly.
// That is, if you're trying to marshal a []Request, the String method
// must be declared on the Request type, not its pointer (*Request).
func Stringers[T fmt.Stringer](key string, values []T) Field {
return Array(key, stringers[T](values))
}
type stringers[T fmt.Stringer] []T
func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for _, o := range os {
arr.AppendString(o.String())
}
return nil
}
// Times constructs a field that carries a slice of time.Times. // Times constructs a field that carries a slice of time.Times.
func Times(key string, ts []time.Time) Field { func Times(key string, ts []time.Time) Field {
return Array(key, times(ts)) return Array(key, times(ts))

156
vendor/go.uber.org/zap/array_go118.go generated vendored
View File

@ -1,156 +0,0 @@
// Copyright (c) 2022 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//go:build go1.18
// +build go1.18
package zap
import (
"fmt"
"go.uber.org/zap/zapcore"
)
// Objects constructs a field with the given key, holding a list of the
// provided objects that can be marshaled by Zap.
//
// Note that these objects must implement zapcore.ObjectMarshaler directly.
// That is, if you're trying to marshal a []Request, the MarshalLogObject
// method must be declared on the Request type, not its pointer (*Request).
// If it's on the pointer, use ObjectValues.
//
// Given an object that implements MarshalLogObject on the value receiver, you
// can log a slice of those objects with Objects like so:
//
// type Author struct{ ... }
// func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var authors []Author = ...
// logger.Info("loading article", zap.Objects("authors", authors))
//
// Similarly, given a type that implements MarshalLogObject on its pointer
// receiver, you can log a slice of pointers to that object with Objects like
// so:
//
// type Request struct{ ... }
// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var requests []*Request = ...
// logger.Info("sending requests", zap.Objects("requests", requests))
//
// If instead, you have a slice of values of such an object, use the
// ObjectValues constructor.
//
// var requests []Request = ...
// logger.Info("sending requests", zap.ObjectValues("requests", requests))
func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {
return Array(key, objects[T](values))
}
type objects[T zapcore.ObjectMarshaler] []T
func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for _, o := range os {
if err := arr.AppendObject(o); err != nil {
return err
}
}
return nil
}
// ObjectMarshalerPtr is a constraint that specifies that the given type
// implements zapcore.ObjectMarshaler on a pointer receiver.
type ObjectMarshalerPtr[T any] interface {
*T
zapcore.ObjectMarshaler
}
// ObjectValues constructs a field with the given key, holding a list of the
// provided objects, where pointers to these objects can be marshaled by Zap.
//
// Note that pointers to these objects must implement zapcore.ObjectMarshaler.
// That is, if you're trying to marshal a []Request, the MarshalLogObject
// method must be declared on the *Request type, not the value (Request).
// If it's on the value, use Objects.
//
// Given an object that implements MarshalLogObject on the pointer receiver,
// you can log a slice of those objects with ObjectValues like so:
//
// type Request struct{ ... }
// func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
//
// var requests []Request = ...
// logger.Info("sending requests", zap.ObjectValues("requests", requests))
//
// If instead, you have a slice of pointers of such an object, use the Objects
// field constructor.
//
// var requests []*Request = ...
// logger.Info("sending requests", zap.Objects("requests", requests))
func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field {
return Array(key, objectValues[T, P](values))
}
type objectValues[T any, P ObjectMarshalerPtr[T]] []T
func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for i := range os {
// It is necessary for us to explicitly reference the "P" type.
// We cannot simply pass "&os[i]" to AppendObject because its type
// is "*T", which the type system does not consider as
// implementing ObjectMarshaler.
// Only the type "P" satisfies ObjectMarshaler, which we have
// to convert "*T" to explicitly.
var p P = &os[i]
if err := arr.AppendObject(p); err != nil {
return err
}
}
return nil
}
// Stringers constructs a field with the given key, holding a list of the
// output provided by the value's String method
//
// Given an object that implements String on the value receiver, you
// can log a slice of those objects with Objects like so:
//
// type Request struct{ ... }
// func (a Request) String() string
//
// var requests []Request = ...
// logger.Info("sending requests", zap.Stringers("requests", requests))
//
// Note that these objects must implement fmt.Stringer directly.
// That is, if you're trying to marshal a []Request, the String method
// must be declared on the Request type, not its pointer (*Request).
func Stringers[T fmt.Stringer](key string, values []T) Field {
return Array(key, stringers[T](values))
}
type stringers[T fmt.Stringer] []T
func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
for _, o := range os {
arr.AppendString(o.String())
}
return nil
}

View File

@ -42,6 +42,11 @@ func (b *Buffer) AppendByte(v byte) {
b.bs = append(b.bs, v) b.bs = append(b.bs, v)
} }
// AppendBytes writes a single byte to the Buffer.
func (b *Buffer) AppendBytes(v []byte) {
b.bs = append(b.bs, v...)
}
// AppendString writes a string to the Buffer. // AppendString writes a string to the Buffer.
func (b *Buffer) AppendString(s string) { func (b *Buffer) AppendString(s string) {
b.bs = append(b.bs, s...) b.bs = append(b.bs, s...)

5
vendor/go.uber.org/zap/error.go generated vendored
View File

@ -61,9 +61,12 @@ func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
// allocating, pool the wrapper type. // allocating, pool the wrapper type.
elem := _errArrayElemPool.Get() elem := _errArrayElemPool.Get()
elem.error = errs[i] elem.error = errs[i]
arr.AppendObject(elem) err := arr.AppendObject(elem)
elem.error = nil elem.error = nil
_errArrayElemPool.Put(elem) _errArrayElemPool.Put(elem)
if err != nil {
return err
}
} }
return nil return nil
} }

25
vendor/go.uber.org/zap/field.go generated vendored
View File

@ -25,6 +25,7 @@ import (
"math" "math"
"time" "time"
"go.uber.org/zap/internal/stacktrace"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
@ -374,7 +375,7 @@ func StackSkip(key string, skip int) Field {
// from expanding the zapcore.Field union struct to include a byte slice. Since // from expanding the zapcore.Field union struct to include a byte slice. Since
// taking a stacktrace is already so expensive (~10us), the extra allocation // taking a stacktrace is already so expensive (~10us), the extra allocation
// is okay. // is okay.
return String(key, takeStacktrace(skip+1)) // skip StackSkip return String(key, stacktrace.Take(skip+1)) // skip StackSkip
} }
// Duration constructs a field with the given key and value. The encoder // Duration constructs a field with the given key and value. The encoder
@ -410,6 +411,26 @@ func Inline(val zapcore.ObjectMarshaler) Field {
} }
} }
// Dict constructs a field containing the provided key-value pairs.
// It acts similar to [Object], but with the fields specified as arguments.
func Dict(key string, val ...Field) Field {
return dictField(key, val)
}
// We need a function with the signature (string, T) for zap.Any.
func dictField(key string, val []Field) Field {
return Object(key, dictObject(val))
}
type dictObject []Field
func (d dictObject) MarshalLogObject(enc zapcore.ObjectEncoder) error {
for _, f := range d {
f.AddTo(enc)
}
return nil
}
// We discovered an issue where zap.Any can cause a performance degradation // We discovered an issue where zap.Any can cause a performance degradation
// when used in new goroutines. // when used in new goroutines.
// //
@ -462,6 +483,8 @@ func Any(key string, value interface{}) Field {
c = anyFieldC[zapcore.ObjectMarshaler](Object) c = anyFieldC[zapcore.ObjectMarshaler](Object)
case zapcore.ArrayMarshaler: case zapcore.ArrayMarshaler:
c = anyFieldC[zapcore.ArrayMarshaler](Array) c = anyFieldC[zapcore.ArrayMarshaler](Array)
case []Field:
c = anyFieldC[[]Field](dictField)
case bool: case bool:
c = anyFieldC[bool](Bool) c = anyFieldC[bool](Bool)
case *bool: case *bool:

View File

@ -69,6 +69,13 @@ import (
// //
// curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}' // curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}'
func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if err := lvl.serveHTTP(w, r); err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintf(w, "internal error: %v", err)
}
}
func (lvl AtomicLevel) serveHTTP(w http.ResponseWriter, r *http.Request) error {
type errorResponse struct { type errorResponse struct {
Error string `json:"error"` Error string `json:"error"`
} }
@ -80,19 +87,20 @@ func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method { switch r.Method {
case http.MethodGet: case http.MethodGet:
enc.Encode(payload{Level: lvl.Level()}) return enc.Encode(payload{Level: lvl.Level()})
case http.MethodPut: case http.MethodPut:
requestedLvl, err := decodePutRequest(r.Header.Get("Content-Type"), r) requestedLvl, err := decodePutRequest(r.Header.Get("Content-Type"), r)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
enc.Encode(errorResponse{Error: err.Error()}) return enc.Encode(errorResponse{Error: err.Error()})
return
} }
lvl.SetLevel(requestedLvl) lvl.SetLevel(requestedLvl)
enc.Encode(payload{Level: lvl.Level()}) return enc.Encode(payload{Level: lvl.Level()})
default: default:
w.WriteHeader(http.StatusMethodNotAllowed) w.WriteHeader(http.StatusMethodNotAllowed)
enc.Encode(errorResponse{ return enc.Encode(errorResponse{
Error: "Only GET and PUT are supported.", Error: "Only GET and PUT are supported.",
}) })
} }
@ -129,5 +137,4 @@ func decodePutJSON(body io.Reader) (zapcore.Level, error) {
return 0, errors.New("must specify logging level") return 0, errors.New("must specify logging level")
} }
return *pld.Level, nil return *pld.Level, nil
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2016 Uber Technologies, Inc. // Copyright (c) 2023 Uber Technologies, Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
@ -18,7 +18,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
package zap // Package stacktrace provides support for gathering stack traces
// efficiently.
package stacktrace
import ( import (
"runtime" "runtime"
@ -28,13 +30,14 @@ import (
"go.uber.org/zap/internal/pool" "go.uber.org/zap/internal/pool"
) )
var _stacktracePool = pool.New(func() *stacktrace { var _stackPool = pool.New(func() *Stack {
return &stacktrace{ return &Stack{
storage: make([]uintptr, 64), storage: make([]uintptr, 64),
} }
}) })
type stacktrace struct { // Stack is a captured stack trace.
type Stack struct {
pcs []uintptr // program counters; always a subslice of storage pcs []uintptr // program counters; always a subslice of storage
frames *runtime.Frames frames *runtime.Frames
@ -48,30 +51,30 @@ type stacktrace struct {
storage []uintptr storage []uintptr
} }
// stacktraceDepth specifies how deep of a stack trace should be captured. // Depth specifies how deep of a stack trace should be captured.
type stacktraceDepth int type Depth int
const ( const (
// stacktraceFirst captures only the first frame. // First captures only the first frame.
stacktraceFirst stacktraceDepth = iota First Depth = iota
// stacktraceFull captures the entire call stack, allocating more // Full captures the entire call stack, allocating more
// storage for it if needed. // storage for it if needed.
stacktraceFull Full
) )
// captureStacktrace captures a stack trace of the specified depth, skipping // Capture captures a stack trace of the specified depth, skipping
// the provided number of frames. skip=0 identifies the caller of // the provided number of frames. skip=0 identifies the caller of
// captureStacktrace. // Capture.
// //
// The caller must call Free on the returned stacktrace after using it. // The caller must call Free on the returned stacktrace after using it.
func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace { func Capture(skip int, depth Depth) *Stack {
stack := _stacktracePool.Get() stack := _stackPool.Get()
switch depth { switch depth {
case stacktraceFirst: case First:
stack.pcs = stack.storage[:1] stack.pcs = stack.storage[:1]
case stacktraceFull: case Full:
stack.pcs = stack.storage stack.pcs = stack.storage
} }
@ -85,7 +88,7 @@ func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
// runtime.Callers truncates the recorded stacktrace if there is no // runtime.Callers truncates the recorded stacktrace if there is no
// room in the provided slice. For the full stack trace, keep expanding // room in the provided slice. For the full stack trace, keep expanding
// storage until there are fewer frames than there is room. // storage until there are fewer frames than there is room.
if depth == stacktraceFull { if depth == Full {
pcs := stack.pcs pcs := stack.pcs
for numFrames == len(pcs) { for numFrames == len(pcs) {
pcs = make([]uintptr, len(pcs)*2) pcs = make([]uintptr, len(pcs)*2)
@ -107,50 +110,54 @@ func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
// Free releases resources associated with this stacktrace // Free releases resources associated with this stacktrace
// and returns it back to the pool. // and returns it back to the pool.
func (st *stacktrace) Free() { func (st *Stack) Free() {
st.frames = nil st.frames = nil
st.pcs = nil st.pcs = nil
_stacktracePool.Put(st) _stackPool.Put(st)
} }
// Count reports the total number of frames in this stacktrace. // Count reports the total number of frames in this stacktrace.
// Count DOES NOT change as Next is called. // Count DOES NOT change as Next is called.
func (st *stacktrace) Count() int { func (st *Stack) Count() int {
return len(st.pcs) return len(st.pcs)
} }
// Next returns the next frame in the stack trace, // Next returns the next frame in the stack trace,
// and a boolean indicating whether there are more after it. // and a boolean indicating whether there are more after it.
func (st *stacktrace) Next() (_ runtime.Frame, more bool) { func (st *Stack) Next() (_ runtime.Frame, more bool) {
return st.frames.Next() return st.frames.Next()
} }
func takeStacktrace(skip int) string { // Take returns a string representation of the current stacktrace.
stack := captureStacktrace(skip+1, stacktraceFull) //
// skip is the number of frames to skip before recording the stack trace.
// skip=0 identifies the caller of Take.
func Take(skip int) string {
stack := Capture(skip+1, Full)
defer stack.Free() defer stack.Free()
buffer := bufferpool.Get() buffer := bufferpool.Get()
defer buffer.Free() defer buffer.Free()
stackfmt := newStackFormatter(buffer) stackfmt := NewFormatter(buffer)
stackfmt.FormatStack(stack) stackfmt.FormatStack(stack)
return buffer.String() return buffer.String()
} }
// stackFormatter formats a stack trace into a readable string representation. // Formatter formats a stack trace into a readable string representation.
type stackFormatter struct { type Formatter struct {
b *buffer.Buffer b *buffer.Buffer
nonEmpty bool // whehther we've written at least one frame already nonEmpty bool // whehther we've written at least one frame already
} }
// newStackFormatter builds a new stackFormatter. // NewFormatter builds a new Formatter.
func newStackFormatter(b *buffer.Buffer) stackFormatter { func NewFormatter(b *buffer.Buffer) Formatter {
return stackFormatter{b: b} return Formatter{b: b}
} }
// FormatStack formats all remaining frames in the provided stacktrace -- minus // FormatStack formats all remaining frames in the provided stacktrace -- minus
// the final runtime.main/runtime.goexit frame. // the final runtime.main/runtime.goexit frame.
func (sf *stackFormatter) FormatStack(stack *stacktrace) { func (sf *Formatter) FormatStack(stack *Stack) {
// Note: On the last iteration, frames.Next() returns false, with a valid // Note: On the last iteration, frames.Next() returns false, with a valid
// frame, but we ignore this frame. The last frame is a runtime frame which // frame, but we ignore this frame. The last frame is a runtime frame which
// adds noise, since it's only either runtime.main or runtime.goexit. // adds noise, since it's only either runtime.main or runtime.goexit.
@ -160,7 +167,7 @@ func (sf *stackFormatter) FormatStack(stack *stacktrace) {
} }
// FormatFrame formats the given frame. // FormatFrame formats the given frame.
func (sf *stackFormatter) FormatFrame(frame runtime.Frame) { func (sf *Formatter) FormatFrame(frame runtime.Frame) {
if sf.nonEmpty { if sf.nonEmpty {
sf.b.AppendByte('\n') sf.b.AppendByte('\n')
} }

42
vendor/go.uber.org/zap/logger.go generated vendored
View File

@ -27,6 +27,7 @@ import (
"strings" "strings"
"go.uber.org/zap/internal/bufferpool" "go.uber.org/zap/internal/bufferpool"
"go.uber.org/zap/internal/stacktrace"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
) )
@ -173,7 +174,8 @@ func (log *Logger) WithOptions(opts ...Option) *Logger {
} }
// With creates a child logger and adds structured context to it. Fields added // With creates a child logger and adds structured context to it. Fields added
// to the child don't affect the parent, and vice versa. // to the child don't affect the parent, and vice versa. Any fields that
// require evaluation (such as Objects) are evaluated upon invocation of With.
func (log *Logger) With(fields ...Field) *Logger { func (log *Logger) With(fields ...Field) *Logger {
if len(fields) == 0 { if len(fields) == 0 {
return log return log
@ -183,6 +185,28 @@ func (log *Logger) With(fields ...Field) *Logger {
return l return l
} }
// WithLazy creates a child logger and adds structured context to it lazily.
//
// The fields are evaluated only if the logger is further chained with [With]
// or is written to with any of the log level methods.
// Until that occurs, the logger may retain references to objects inside the fields,
// and logging will reflect the state of an object at the time of logging,
// not the time of WithLazy().
//
// WithLazy provides a worthwhile performance optimization for contextual loggers
// when the likelihood of using the child logger is low,
// such as error paths and rarely taken branches.
//
// Similar to [With], fields added to the child don't affect the parent, and vice versa.
func (log *Logger) WithLazy(fields ...Field) *Logger {
if len(fields) == 0 {
return log
}
return log.WithOptions(WrapCore(func(core zapcore.Core) zapcore.Core {
return zapcore.NewLazyWith(core, fields)
}))
}
// Level reports the minimum enabled level for this logger. // Level reports the minimum enabled level for this logger.
// //
// For NopLoggers, this is [zapcore.InvalidLevel]. // For NopLoggers, this is [zapcore.InvalidLevel].
@ -199,6 +223,8 @@ func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
// Log logs a message at the specified level. The message includes any fields // Log logs a message at the specified level. The message includes any fields
// passed at the log site, as well as any fields accumulated on the logger. // passed at the log site, as well as any fields accumulated on the logger.
// Any Fields that require evaluation (such as Objects) are evaluated upon
// invocation of Log.
func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) { func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) {
if ce := log.check(lvl, msg); ce != nil { if ce := log.check(lvl, msg); ce != nil {
ce.Write(fields...) ce.Write(fields...)
@ -288,8 +314,8 @@ func (log *Logger) Name() string {
} }
func (log *Logger) clone() *Logger { func (log *Logger) clone() *Logger {
copy := *log clone := *log
return &copy return &clone
} }
func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry { func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
@ -360,17 +386,17 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
// Adding the caller or stack trace requires capturing the callers of // Adding the caller or stack trace requires capturing the callers of
// this function. We'll share information between these two. // this function. We'll share information between these two.
stackDepth := stacktraceFirst stackDepth := stacktrace.First
if addStack { if addStack {
stackDepth = stacktraceFull stackDepth = stacktrace.Full
} }
stack := captureStacktrace(log.callerSkip+callerSkipOffset, stackDepth) stack := stacktrace.Capture(log.callerSkip+callerSkipOffset, stackDepth)
defer stack.Free() defer stack.Free()
if stack.Count() == 0 { if stack.Count() == 0 {
if log.addCaller { if log.addCaller {
fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", ent.Time.UTC()) fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", ent.Time.UTC())
log.errorOutput.Sync() _ = log.errorOutput.Sync()
} }
return ce return ce
} }
@ -391,7 +417,7 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
buffer := bufferpool.Get() buffer := bufferpool.Get()
defer buffer.Free() defer buffer.Free()
stackfmt := newStackFormatter(buffer) stackfmt := stacktrace.NewFormatter(buffer)
// We've already extracted the first frame, so format that // We've already extracted the first frame, so format that
// separately and defer to stackfmt for the rest. // separately and defer to stackfmt for the rest.

5
vendor/go.uber.org/zap/sink.go generated vendored
View File

@ -66,7 +66,8 @@ func newSinkRegistry() *sinkRegistry {
factories: make(map[string]func(*url.URL) (Sink, error)), factories: make(map[string]func(*url.URL) (Sink, error)),
openFile: os.OpenFile, openFile: os.OpenFile,
} }
sr.RegisterSink(schemeFile, sr.newFileSinkFromURL) // Infallible operation: the registry is empty, so we can't have a conflict.
_ = sr.RegisterSink(schemeFile, sr.newFileSinkFromURL)
return sr return sr
} }
@ -154,7 +155,7 @@ func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) {
case "stderr": case "stderr":
return nopCloserSink{os.Stderr}, nil return nopCloserSink{os.Stderr}, nil
} }
return sr.openFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666) return sr.openFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o666)
} }
func normalizeScheme(s string) (string, error) { func normalizeScheme(s string) (string, error) {

12
vendor/go.uber.org/zap/writer.go generated vendored
View File

@ -48,21 +48,21 @@ import (
// os.Stdout and os.Stderr. When specified without a scheme, relative file // os.Stdout and os.Stderr. When specified without a scheme, relative file
// paths also work. // paths also work.
func Open(paths ...string) (zapcore.WriteSyncer, func(), error) { func Open(paths ...string) (zapcore.WriteSyncer, func(), error) {
writers, close, err := open(paths) writers, closeAll, err := open(paths)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
writer := CombineWriteSyncers(writers...) writer := CombineWriteSyncers(writers...)
return writer, close, nil return writer, closeAll, nil
} }
func open(paths []string) ([]zapcore.WriteSyncer, func(), error) { func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
writers := make([]zapcore.WriteSyncer, 0, len(paths)) writers := make([]zapcore.WriteSyncer, 0, len(paths))
closers := make([]io.Closer, 0, len(paths)) closers := make([]io.Closer, 0, len(paths))
close := func() { closeAll := func() {
for _, c := range closers { for _, c := range closers {
c.Close() _ = c.Close()
} }
} }
@ -77,11 +77,11 @@ func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
closers = append(closers, sink) closers = append(closers, sink)
} }
if openErr != nil { if openErr != nil {
close() closeAll()
return nil, nil, openErr return nil, nil, openErr
} }
return writers, close, nil return writers, closeAll, nil
} }
// CombineWriteSyncers is a utility that combines multiple WriteSyncers into a // CombineWriteSyncers is a utility that combines multiple WriteSyncers into a

View File

@ -102,9 +102,9 @@ func (c *ioCore) Write(ent Entry, fields []Field) error {
return err return err
} }
if ent.Level > ErrorLevel { if ent.Level > ErrorLevel {
// Since we may be crashing the program, sync the output. Ignore Sync // Since we may be crashing the program, sync the output.
// errors, pending a clean solution to issue #370. // Ignore Sync errors, pending a clean solution to issue #370.
c.Sync() _ = c.Sync()
} }
return nil return nil
} }

View File

@ -242,7 +242,7 @@ func (ce *CheckedEntry) Write(fields ...Field) {
// CheckedEntry is being used after it was returned to the pool, // CheckedEntry is being used after it was returned to the pool,
// the message may be an amalgamation from multiple call sites. // the message may be an amalgamation from multiple call sites.
fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", ce.Time, ce.Entry) fmt.Fprintf(ce.ErrorOutput, "%v Unsafe CheckedEntry re-use near Entry %+v.\n", ce.Time, ce.Entry)
ce.ErrorOutput.Sync() _ = ce.ErrorOutput.Sync() // ignore error
} }
return return
} }
@ -254,7 +254,7 @@ func (ce *CheckedEntry) Write(fields ...Field) {
} }
if err != nil && ce.ErrorOutput != nil { if err != nil && ce.ErrorOutput != nil {
fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", ce.Time, err) fmt.Fprintf(ce.ErrorOutput, "%v write error: %v\n", ce.Time, err)
ce.ErrorOutput.Sync() _ = ce.ErrorOutput.Sync() // ignore error
} }
hook := ce.after hook := ce.after

View File

@ -98,8 +98,11 @@ func (errs errArray) MarshalLogArray(arr ArrayEncoder) error {
} }
el := newErrArrayElem(errs[i]) el := newErrArrayElem(errs[i])
arr.AppendObject(el) err := arr.AppendObject(el)
el.Free() el.Free()
if err != nil {
return err
}
} }
return nil return nil
} }

View File

@ -486,73 +486,98 @@ func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
// Unlike the standard library's encoder, it doesn't attempt to protect the // Unlike the standard library's encoder, it doesn't attempt to protect the
// user from browser vulnerabilities or JSONP-related problems. // user from browser vulnerabilities or JSONP-related problems.
func (enc *jsonEncoder) safeAddString(s string) { func (enc *jsonEncoder) safeAddString(s string) {
for i := 0; i < len(s); { safeAppendStringLike(
if enc.tryAddRuneSelf(s[i]) { (*buffer.Buffer).AppendString,
i++ utf8.DecodeRuneInString,
continue enc.buf,
} s,
r, size := utf8.DecodeRuneInString(s[i:]) )
if enc.tryAddRuneError(r, size) {
i++
continue
}
enc.buf.AppendString(s[i : i+size])
i += size
}
} }
// safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte. // safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte.
func (enc *jsonEncoder) safeAddByteString(s []byte) { func (enc *jsonEncoder) safeAddByteString(s []byte) {
for i := 0; i < len(s); { safeAppendStringLike(
if enc.tryAddRuneSelf(s[i]) { (*buffer.Buffer).AppendBytes,
i++ utf8.DecodeRune,
continue enc.buf,
} s,
r, size := utf8.DecodeRune(s[i:]) )
if enc.tryAddRuneError(r, size) {
i++
continue
}
enc.buf.Write(s[i : i+size])
i += size
}
} }
// tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte. // safeAppendStringLike is a generic implementation of safeAddString and safeAddByteString.
func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool { // It appends a string or byte slice to the buffer, escaping all special characters.
if b >= utf8.RuneSelf { func safeAppendStringLike[S []byte | string](
return false // appendTo appends this string-like object to the buffer.
appendTo func(*buffer.Buffer, S),
// decodeRune decodes the next rune from the string-like object
// and returns its value and width in bytes.
decodeRune func(S) (rune, int),
buf *buffer.Buffer,
s S,
) {
// The encoding logic below works by skipping over characters
// that can be safely copied as-is,
// until a character is found that needs special handling.
// At that point, we copy everything we've seen so far,
// and then handle that special character.
//
// last is the index of the last byte that was copied to the buffer.
last := 0
for i := 0; i < len(s); {
if s[i] >= utf8.RuneSelf {
// Character >= RuneSelf may be part of a multi-byte rune.
// They need to be decoded before we can decide how to handle them.
r, size := decodeRune(s[i:])
if r != utf8.RuneError || size != 1 {
// No special handling required.
// Skip over this rune and continue.
i += size
continue
} }
if b >= 0x20 && b != '\\' && b != '"' {
enc.buf.AppendByte(b) // Invalid UTF-8 sequence.
return true // Replace it with the Unicode replacement character.
appendTo(buf, s[last:i])
buf.AppendString(`\ufffd`)
i++
last = i
} else {
// Character < RuneSelf is a single-byte UTF-8 rune.
if s[i] >= 0x20 && s[i] != '\\' && s[i] != '"' {
// No escaping necessary.
// Skip over this character and continue.
i++
continue
} }
switch b {
// This character needs to be escaped.
appendTo(buf, s[last:i])
switch s[i] {
case '\\', '"': case '\\', '"':
enc.buf.AppendByte('\\') buf.AppendByte('\\')
enc.buf.AppendByte(b) buf.AppendByte(s[i])
case '\n': case '\n':
enc.buf.AppendByte('\\') buf.AppendByte('\\')
enc.buf.AppendByte('n') buf.AppendByte('n')
case '\r': case '\r':
enc.buf.AppendByte('\\') buf.AppendByte('\\')
enc.buf.AppendByte('r') buf.AppendByte('r')
case '\t': case '\t':
enc.buf.AppendByte('\\') buf.AppendByte('\\')
enc.buf.AppendByte('t') buf.AppendByte('t')
default: default:
// Encode bytes < 0x20, except for the escape sequences above. // Encode bytes < 0x20, except for the escape sequences above.
enc.buf.AppendString(`\u00`) buf.AppendString(`\u00`)
enc.buf.AppendByte(_hex[b>>4]) buf.AppendByte(_hex[s[i]>>4])
enc.buf.AppendByte(_hex[b&0xF]) buf.AppendByte(_hex[s[i]&0xF])
}
return true
} }
func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool { i++
if r == utf8.RuneError && size == 1 { last = i
enc.buf.AppendString(`\ufffd`)
return true
} }
return false }
// add remaining
appendTo(buf, s[last:])
} }

54
vendor/go.uber.org/zap/zapcore/lazy_with.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package zapcore
import "sync"
type lazyWithCore struct {
Core
sync.Once
fields []Field
}
// NewLazyWith wraps a Core with a "lazy" Core that will only encode fields if
// the logger is written to (or is further chained in a lon-lazy manner).
func NewLazyWith(core Core, fields []Field) Core {
return &lazyWithCore{
Core: core,
fields: fields,
}
}
func (d *lazyWithCore) initOnce() {
d.Once.Do(func() {
d.Core = d.Core.With(d.fields)
})
}
func (d *lazyWithCore) With(fields []Field) Core {
d.initOnce()
return d.Core.With(fields)
}
func (d *lazyWithCore) Check(e Entry, ce *CheckedEntry) *CheckedEntry {
d.initOnce()
return d.Core.Check(e, ce)
}

5
vendor/modules.txt vendored
View File

@ -2,7 +2,7 @@
## explicit; go 1.21 ## explicit; go 1.21
github.com/cyrilix/robocar-base/cli github.com/cyrilix/robocar-base/cli
github.com/cyrilix/robocar-base/service github.com/cyrilix/robocar-base/service
# github.com/cyrilix/robocar-protobuf/go v1.3.1 # github.com/cyrilix/robocar-protobuf/go v1.4.0
## explicit; go 1.21 ## explicit; go 1.21
github.com/cyrilix/robocar-protobuf/go/events github.com/cyrilix/robocar-protobuf/go/events
# github.com/eclipse/paho.mqtt.golang v1.4.3 # github.com/eclipse/paho.mqtt.golang v1.4.3
@ -18,7 +18,7 @@ github.com/tarm/serial
# go.uber.org/multierr v1.10.0 # go.uber.org/multierr v1.10.0
## explicit; go 1.19 ## explicit; go 1.19
go.uber.org/multierr go.uber.org/multierr
# go.uber.org/zap v1.25.0 # go.uber.org/zap v1.26.0
## explicit; go 1.19 ## explicit; go 1.19
go.uber.org/zap go.uber.org/zap
go.uber.org/zap/buffer go.uber.org/zap/buffer
@ -27,6 +27,7 @@ go.uber.org/zap/internal/bufferpool
go.uber.org/zap/internal/color go.uber.org/zap/internal/color
go.uber.org/zap/internal/exit go.uber.org/zap/internal/exit
go.uber.org/zap/internal/pool go.uber.org/zap/internal/pool
go.uber.org/zap/internal/stacktrace
go.uber.org/zap/zapcore go.uber.org/zap/zapcore
# golang.org/x/net v0.9.0 # golang.org/x/net v0.9.0
## explicit; go 1.17 ## explicit; go 1.17