From a89783bbf839be78ce085c7a46dd89953eebdd95 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sat, 29 Jun 2024 18:57:13 -0700 Subject: [PATCH 01/27] no_http/no_net and no_json buildtags (wip) --- .gitignore | 3 +++ Makefile | 13 ++++++++++++- README.md | 4 ++++ http_logging.go | 3 +++ http_logging_test.go | 3 +++ logger.go | 42 +----------------------------------------- logger_test.go | 11 ----------- 7 files changed, 26 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index 6c3cdf3..9b5da77 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ +.DS_Store .golangci.yml +fullsize +smallsize diff --git a/Makefile b/Makefile index 7affc5c..227ddc3 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,9 @@ all: test example test: - go test . -race ./... + go test -race ./... + go test -tags no_json ./... + go test -tags no_http ./... example: @echo "### Colorized (default) ###" @@ -17,6 +19,15 @@ line: screenshot: line example @echo +size-check: + @echo "### Size of the binary:" + CGO_ENABLED=0 go build -ldflags="-w -s" -trimpath -o ./fullsize ./levelsDemo + ls -lh ./fullsize + CGO_ENABLED=0 go build -tags no_net -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + ls -lh ./smallsize + CGO_ENABLED=0 go build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + ls -lh ./smallsize + lint: .golangci.yml golangci-lint run diff --git a/README.md b/README.md index e78028f..3ddc8bb 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,7 @@ LOGGER_GOROUTINE_ID=false LOGGER_COMBINE_REQUEST_AND_RESPONSE=true LOGGER_LEVEL='Info' ``` + +# Small binaries + +If you're never logging http requests/responses, use `-tags no_http` (or `-tags no_net`) to exclude the http/https logging utilities. diff --git a/http_logging.go b/http_logging.go index 0782c10..503b6fc 100644 --- a/http_logging.go +++ b/http_logging.go @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !no_http && !no_net +// +build !no_http,!no_net + package log import ( diff --git a/http_logging_test.go b/http_logging_test.go index 750d5e1..a9697ee 100644 --- a/http_logging_test.go +++ b/http_logging_test.go @@ -1,3 +1,6 @@ +//go:build !no_http && !no_net +// +build !no_http,!no_net + package log // import "fortio.org/fortio/log" import ( diff --git a/logger.go b/logger.go index 2fcb8f5..2e56606 100644 --- a/logger.go +++ b/logger.go @@ -25,7 +25,6 @@ package log // import "fortio.org/log" import ( "bytes" - "encoding/json" "flag" "fmt" "io" @@ -349,7 +348,7 @@ func Logf(lvl Level, format string, rest ...interface{}) { logPrintf(lvl, format, rest...) } -// Used when doing our own logging writing, in JSON/structured mode. +// Used when doing our own logging writing, in JSON/structured mode (and some color variants as well, misnomer). var ( jWriter = jsonWriter{w: os.Stderr, tsBuf: make([]byte, 0, 32)} ) @@ -631,45 +630,6 @@ type ValueType[T ValueTypes] struct { Val T } -func toJSON(v any) string { - bytes, err := json.Marshal(v) - if err != nil { - return strconv.Quote(fmt.Sprintf("ERR marshaling %v: %v", v, err)) - } - str := string(bytes) - // We now handle errors before calling toJSON: if there is a marshaller we use it - // otherwise we use the string from .Error() - return str -} - -func (v ValueType[T]) String() string { - // if the type is numeric, use Sprint(v.val) otherwise use Sprintf("%q", v.Val) to quote it. - switch s := any(v.Val).(type) { - case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, - float32, float64: - return fmt.Sprint(s) - case string: - return fmt.Sprintf("%q", s) - case error: - // Sadly structured errors like nettwork error don't have the reason in - // the exposed struct/JSON - ie on gets - // {"Op":"read","Net":"tcp","Source":{"IP":"127.0.0.1","Port":60067,"Zone":""}, - // "Addr":{"IP":"127.0.0.1","Port":3000,"Zone":""},"Err":{}} - // instead of - // read tcp 127.0.0.1:60067->127.0.0.1:3000: i/o timeout - // Noticed in https://github.com/fortio/fortio/issues/913 - _, hasMarshaller := s.(json.Marshaler) - if hasMarshaller { - return toJSON(v.Val) - } else { - return fmt.Sprintf("%q", s.Error()) - } - /* It's all handled by json fallback now even though slightly more expensive at runtime, it's a lot simpler */ - default: - return toJSON(v.Val) // was fmt.Sprintf("%q", fmt.Sprint(v.Val)) - } -} - // Our original name, now switched to slog style Any. func Attr[T ValueTypes](key string, value T) KeyVal { return Any(key, value) diff --git a/logger_test.go b/logger_test.go index d7c175e..4dceea4 100644 --- a/logger_test.go +++ b/logger_test.go @@ -793,17 +793,6 @@ func TestSerializationOfError(t *testing.T) { } } -func TestToJSON_MarshalError(t *testing.T) { - badValue := make(chan int) - - expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "json: unsupported type: chan int") - actual := toJSON(badValue) - - if actual != expected { - t.Errorf("Expected %q, got %q", expected, actual) - } -} - func TestEnvHelp(t *testing.T) { SetDefaultsForClientTools() Config.NoTimestamp = false From a761e9410bd62c3d3376548247691c653728e54a Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sat, 29 Jun 2024 18:57:37 -0700 Subject: [PATCH 02/27] better with git add --- json_logging.go | 65 ++++++++++++++++++++++++++++++++++ json_logging_tests.go | 20 +++++++++++ no_json_logging.go | 82 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 json_logging.go create mode 100644 json_logging_tests.go create mode 100644 no_json_logging.go diff --git a/json_logging.go b/json_logging.go new file mode 100644 index 0000000..4f06be8 --- /dev/null +++ b/json_logging.go @@ -0,0 +1,65 @@ +// Copyright 2017-2024 Fortio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Moved json logging out so it can be skipped for smallest binaries based on build tags. +// only difference is with nested struct/array logging or logging of types with json Marchaller interface. + +//go:build !no_json + +package log // import "fortio.org/log" + +import ( + "encoding/json" + "fmt" + "strconv" +) + +func toJSON(v any) string { + bytes, err := json.Marshal(v) + if err != nil { + return strconv.Quote(fmt.Sprintf("ERR marshaling %v: %v", v, err)) + } + str := string(bytes) + // We now handle errors before calling toJSON: if there is a marshaller we use it + // otherwise we use the string from .Error() + return str +} + +func (v ValueType[T]) String() string { + // if the type is numeric, use Sprint(v.val) otherwise use Sprintf("%q", v.Val) to quote it. + switch s := any(v.Val).(type) { + case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, + float32, float64: + return fmt.Sprint(s) + case string: + return fmt.Sprintf("%q", s) + case error: + // Sadly structured errors like nettwork error don't have the reason in + // the exposed struct/JSON - ie on gets + // {"Op":"read","Net":"tcp","Source":{"IP":"127.0.0.1","Port":60067,"Zone":""}, + // "Addr":{"IP":"127.0.0.1","Port":3000,"Zone":""},"Err":{}} + // instead of + // read tcp 127.0.0.1:60067->127.0.0.1:3000: i/o timeout + // Noticed in https://github.com/fortio/fortio/issues/913 + _, hasMarshaller := s.(json.Marshaler) + if hasMarshaller { + return toJSON(v.Val) + } else { + return fmt.Sprintf("%q", s.Error()) + } + /* It's all handled by json fallback now even though slightly more expensive at runtime, it's a lot simpler */ + default: + return toJSON(v.Val) // was fmt.Sprintf("%q", fmt.Sprint(v.Val)) + } +} diff --git a/json_logging_tests.go b/json_logging_tests.go new file mode 100644 index 0000000..659aed9 --- /dev/null +++ b/json_logging_tests.go @@ -0,0 +1,20 @@ +//go:build !no_json +// +build !no_json + +package log // import "fortio.org/fortio/log" + +import ( + "fmt" + "testing" +) + +func TestToJSON_MarshalError(t *testing.T) { + badValue := make(chan int) + + expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "json: unsupported type: chan int") + actual := toJSON(badValue) + + if actual != expected { + t.Errorf("Expected %q, got %q", expected, actual) + } +} diff --git a/no_json_logging.go b/no_json_logging.go new file mode 100644 index 0000000..3766f83 --- /dev/null +++ b/no_json_logging.go @@ -0,0 +1,82 @@ +// Copyright 2017-2024 Fortio Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Moved json logging out so it can be skipped for smallest binaries based on build tags. + +//go:build no_json + +package log // import "fortio.org/log" + +import ( + "fmt" + "sort" + "strings" +) + +// restore version "manual json serialization" from +// https://github.com/fortio/log/pull/46/files#diff-ff87b7c4777a35588053a509583d66c9f404ccbea9e1c71d2a5f224d7ad1323e +func arrayToString(s []interface{}) string { + var buf strings.Builder + buf.WriteString("[") + for i, e := range s { + if i != 0 { + buf.WriteString(",") + } + vv := ValueType[interface{}]{Val: e} + buf.WriteString(vv.String()) + } + buf.WriteString("]") + return buf.String() +} + +func mapToString(s map[string]interface{}) string { + var buf strings.Builder + buf.WriteString("{") + keys := make([]string, 0, len(s)) + for k := range s { + keys = append(keys, k) + } + sort.Strings(keys) + for i, k := range keys { + if i != 0 { + buf.WriteString(",") + } + buf.WriteString(fmt.Sprintf("%q", k)) + buf.WriteString(":") + vv := ValueType[interface{}]{Val: s[k]} + buf.WriteString(vv.String()) + } + buf.WriteString("}") + return buf.String() +} + +func (v ValueType[T]) String() string { + // if the type is numeric, use Sprint(v.val) otherwise use Sprintf("%q", v.Val) to quote it. + switch s := any(v.Val).(type) { + case bool, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, + float32, float64: + return fmt.Sprint(s) + case string: + return fmt.Sprintf("%q", s) + case []interface{}: + return arrayToString(s) + case map[string]interface{}: + return mapToString(s) + case error: + return fmt.Sprintf("%q", s.Error()) + + default: + return fmt.Sprintf("%q", fmt.Sprint(v.Val)) + } +} From 78309933357dbee978123420c34adba5d1d1fae7 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 13:11:03 -0700 Subject: [PATCH 03/27] passing tests but not happy about the nil error Invalid case --- json_logging.go | 2 ++ logger_test.go | 21 +++++++++++++++++++++ no_json_logging.go | 25 +++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/json_logging.go b/json_logging.go index 4f06be8..dad0e56 100644 --- a/json_logging.go +++ b/json_logging.go @@ -25,6 +25,8 @@ import ( "strconv" ) +var fullJSON = true + func toJSON(v any) string { bytes, err := json.Marshal(v) if err != nil { diff --git a/logger_test.go b/logger_test.go index 4dceea4..1b67575 100644 --- a/logger_test.go +++ b/logger_test.go @@ -767,6 +767,24 @@ func (e customError) MarshalJSON() ([]byte, error) { return json.Marshal(customErrorAlias(e)) } +func TestPointers(t *testing.T) { + var iPtr *int + kv := Any("err", iPtr) + kvStr := kv.StringValue() + expected := `null` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } + i := 42 + iPtr = &i + kv = Any("err", iPtr) + kvStr = kv.StringValue() + expected = `42` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } +} + func TestSerializationOfError(t *testing.T) { var err error kv := Any("err", err) @@ -788,6 +806,9 @@ func TestSerializationOfError(t *testing.T) { kv = Any("err", err) kvStr = kv.StringValue() expected = `{"Msg":"custom error","Code":42}` + if !fullJSON { + expected = `"custom error custom error (code 42)"` + } if kvStr != expected { t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) } diff --git a/no_json_logging.go b/no_json_logging.go index 3766f83..312fe5a 100644 --- a/no_json_logging.go +++ b/no_json_logging.go @@ -20,10 +20,13 @@ package log // import "fortio.org/log" import ( "fmt" + "reflect" "sort" "strings" ) +var fullJSON = false + // restore version "manual json serialization" from // https://github.com/fortio/log/pull/46/files#diff-ff87b7c4777a35588053a509583d66c9f404ccbea9e1c71d2a5f224d7ad1323e func arrayToString(s []interface{}) string { @@ -61,6 +64,8 @@ func mapToString(s map[string]interface{}) string { return buf.String() } +const nullString = "null" + func (v ValueType[T]) String() string { // if the type is numeric, use Sprint(v.val) otherwise use Sprintf("%q", v.Val) to quote it. switch s := any(v.Val).(type) { @@ -69,14 +74,30 @@ func (v ValueType[T]) String() string { return fmt.Sprint(s) case string: return fmt.Sprintf("%q", s) + case *string: + if s == nil { + return nullString + } + return fmt.Sprintf("%q", *s) case []interface{}: return arrayToString(s) case map[string]interface{}: return mapToString(s) case error: - return fmt.Sprintf("%q", s.Error()) - + return fmt.Sprintf("%q", s.Error()) // no nil check needed/working for errors (interface) default: + val := reflect.ValueOf(s) + k := val.Kind() + if k == reflect.Invalid { // any way to avoid this and still get `var err error` to return null? + return nullString + } + if k == reflect.Ptr || k == reflect.Interface { + if val.IsNil() { + return nullString + } + vv := ValueType[interface{}]{Val: val.Elem().Interface()} + return vv.String() + } return fmt.Sprintf("%q", fmt.Sprint(v.Val)) } } From 3a022cf689cce207db3694015d3961143b3fd6b5 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 13:52:44 -0700 Subject: [PATCH 04/27] adding info about no_json and github.com/Zxilly/go-size-analyzer/cmd/gsa --- Makefile | 1 + README.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 227ddc3..38295ab 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ size-check: ls -lh ./smallsize CGO_ENABLED=0 go build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize + gsa ./smallsize # go install github.com/Zxilly/go-size-analyzer/cmd/gsa@master lint: .golangci.yml diff --git a/README.md b/README.md index 3ddc8bb..43741d7 100644 --- a/README.md +++ b/README.md @@ -104,3 +104,7 @@ LOGGER_LEVEL='Info' # Small binaries If you're never logging http requests/responses, use `-tags no_http` (or `-tags no_net`) to exclude the http/https logging utilities. + +If you never need to JSON log complex structures/types that have a special `json.Marshaler` then you can use `-tags no_net,no_json` for the smallest executables + +(see `make size-check`) From 64bc184fd2f11cd9c7f24fef7b1f1156de1f714d Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 13:59:16 -0700 Subject: [PATCH 05/27] linter alerted indirectly about wrongly named test file --- json_logging_tests.go => json_logging_test.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename json_logging_tests.go => json_logging_test.go (100%) diff --git a/json_logging_tests.go b/json_logging_test.go similarity index 100% rename from json_logging_tests.go rename to json_logging_test.go From 4dd0c3206bbe03582ca54b66ace2790568a8a641 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 14:15:36 -0700 Subject: [PATCH 06/27] so much cleaner, thanks polyscone (gophers discord) --- no_json_logging.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/no_json_logging.go b/no_json_logging.go index 312fe5a..37c373a 100644 --- a/no_json_logging.go +++ b/no_json_logging.go @@ -85,12 +85,11 @@ func (v ValueType[T]) String() string { return mapToString(s) case error: return fmt.Sprintf("%q", s.Error()) // no nil check needed/working for errors (interface) + case nil: + return nullString default: val := reflect.ValueOf(s) k := val.Kind() - if k == reflect.Invalid { // any way to avoid this and still get `var err error` to return null? - return nullString - } if k == reflect.Ptr || k == reflect.Interface { if val.IsNil() { return nullString From a3ee5188a38d8ecad3fd745a044e8cc750f70469 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 14:27:11 -0700 Subject: [PATCH 07/27] update comments and add test for nil *string --- logger_test.go | 9 ++++++++- no_json_logging.go | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/logger_test.go b/logger_test.go index 1b67575..47599b8 100644 --- a/logger_test.go +++ b/logger_test.go @@ -777,12 +777,19 @@ func TestPointers(t *testing.T) { } i := 42 iPtr = &i - kv = Any("err", iPtr) + kv = Any("int", iPtr) kvStr = kv.StringValue() expected = `42` if kvStr != expected { t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) } + var sPtr *string + kv = Any("msg", sPtr) + kvStr = kv.StringValue() + expected = `null` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } } func TestSerializationOfError(t *testing.T) { diff --git a/no_json_logging.go b/no_json_logging.go index 37c373a..ead776d 100644 --- a/no_json_logging.go +++ b/no_json_logging.go @@ -13,6 +13,7 @@ // limitations under the License. // Moved json logging out so it can be skipped for smallest binaries based on build tags. +// This file is the variant that does serialization manually instead of using json.Marshal. //go:build no_json @@ -84,9 +85,9 @@ func (v ValueType[T]) String() string { case map[string]interface{}: return mapToString(s) case error: - return fmt.Sprintf("%q", s.Error()) // no nil check needed/working for errors (interface) + return fmt.Sprintf("%q", s.Error()) // nil errors handled in case nil below case nil: - return nullString + return nullString // nil interface{} like `var err error` (but not nil *string etc.) default: val := reflect.ValueOf(s) k := val.Kind() From 34330f1e341834f0e327d17b1cf83ba23dc63e56 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 14:45:54 -0700 Subject: [PATCH 08/27] adding make coverage now that https://github.com/fortio/workflows/pull/51 is done --- .gitignore | 2 ++ .vscode/launch.json | 14 ++++++++++++++ Makefile | 8 ++++++++ 3 files changed, 24 insertions(+) create mode 100644 .vscode/launch.json diff --git a/.gitignore b/.gitignore index 9b5da77..fdd9bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .golangci.yml fullsize smallsize +coverage.out +coverage?.out diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a75431d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch test function with tags", + "type": "go", + "request": "launch", + "mode": "test", + "program": "${workspaceFolder}", + "buildFlags": "-tags=no_json" + } + + ] +} diff --git a/Makefile b/Makefile index 38295ab..8e202f9 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,14 @@ test: go test -tags no_json ./... go test -tags no_http ./... +coverage: + go test -coverprofile=coverage1.out ./... + go test -tags no_net -coverprofile=coverage2.out ./... + go test -tags no_json -coverprofile=coverage3.out ./... + go test -tags no_http,no_json -coverprofile=coverage4.out ./... + gocovmerge coverage?.out > coverage.out + # go tool cover -html=coverage.out + example: @echo "### Colorized (default) ###" go run ./levelsDemo From d8deb7565d54587f401a756fa9b97808414d6d74 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 14:55:34 -0700 Subject: [PATCH 09/27] lets see if it work with just cat and codecov --- Makefile | 3 ++- codecov.yml | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 codecov.yml diff --git a/Makefile b/Makefile index 8e202f9..c037103 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,8 @@ coverage: go test -tags no_net -coverprofile=coverage2.out ./... go test -tags no_json -coverprofile=coverage3.out ./... go test -tags no_http,no_json -coverprofile=coverage4.out ./... - gocovmerge coverage?.out > coverage.out + cat coverage*.out > coverage.out + # gocovmerge coverage?.out > coverage.out # go tool cover -html=coverage.out example: diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..8ed636b --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +coverage: + ignore: + - "levelsDemo" From c4f7b5ee41aaf52d76229f5c22111c03a2b453d9 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 15:04:07 -0700 Subject: [PATCH 10/27] codecov already looks for *coverage* --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c037103..043f937 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ coverage: go test -tags no_net -coverprofile=coverage2.out ./... go test -tags no_json -coverprofile=coverage3.out ./... go test -tags no_http,no_json -coverprofile=coverage4.out ./... - cat coverage*.out > coverage.out + # cat coverage*.out > coverage.out # gocovmerge coverage?.out > coverage.out # go tool cover -html=coverage.out From 507d00e680a470fc00245febe7970f30b57241ae Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 15:07:57 -0700 Subject: [PATCH 11/27] actually not... trying to specify files --- codecov.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/codecov.yml b/codecov.yml index 8ed636b..24ca19f 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,5 @@ coverage: ignore: - "levelsDemo" + files: + - "coverage*.out" From fe0dc98e26ad3a051714a069894df95f6d398a1a Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 15:22:24 -0700 Subject: [PATCH 12/27] using gocovmerge --- Makefile | 3 ++- codecov.yml | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 043f937..8240c9b 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,8 @@ coverage: go test -tags no_json -coverprofile=coverage3.out ./... go test -tags no_http,no_json -coverprofile=coverage4.out ./... # cat coverage*.out > coverage.out - # gocovmerge coverage?.out > coverage.out + go install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c + gocovmerge coverage?.out > coverage.out # go tool cover -html=coverage.out example: diff --git a/codecov.yml b/codecov.yml index 24ca19f..c1f00ca 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,5 +1,6 @@ coverage: ignore: - "levelsDemo" - files: - - "coverage*.out" +# not used (is nothing at all used?) +# files: +# - "coverage*.out" From d0d83d191dc38f84d872f843764ad4901aa1d1aa Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 15:53:00 -0700 Subject: [PATCH 13/27] added tests for struct etc --- Makefile | 5 ++++- logger_test.go | 27 +++++++++++++++++++++++++++ no_json_logging.go | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8240c9b..739e439 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ test: go test -tags no_json ./... go test -tags no_http ./... +local-coverage: coverage + go test -coverprofile=coverage.out ./... + go tool cover -html=coverage.out + coverage: go test -coverprofile=coverage1.out ./... go test -tags no_net -coverprofile=coverage2.out ./... @@ -14,7 +18,6 @@ coverage: # cat coverage*.out > coverage.out go install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c gocovmerge coverage?.out > coverage.out - # go tool cover -html=coverage.out example: @echo "### Colorized (default) ###" diff --git a/logger_test.go b/logger_test.go index 47599b8..45e4eef 100644 --- a/logger_test.go +++ b/logger_test.go @@ -790,6 +790,33 @@ func TestPointers(t *testing.T) { if kvStr != expected { t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) } + s := "test\nline2" + sPtr = &s + kv = Any("msg", sPtr) + kvStr = kv.StringValue() + expected = `"test\nline2"` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } +} + +func TestStruct(t *testing.T) { + type testStruct struct { + Msg1 string + Msg2 *string + } + ptrStr := "test2" + ts := testStruct{Msg1: "test\nline2", Msg2: &ptrStr} + kv := Any("ts", ts) + kvStr := kv.StringValue() + expected := `{"Msg1":"test\nline2","Msg2":"test2"}` + if !fullJSON { + expected = `"{Msg1:test\nline2 Msg2:` + expected += fmt.Sprintf("%p}\"", &ptrStr) + } + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } } func TestSerializationOfError(t *testing.T) { diff --git a/no_json_logging.go b/no_json_logging.go index ead776d..52f8541 100644 --- a/no_json_logging.go +++ b/no_json_logging.go @@ -98,6 +98,6 @@ func (v ValueType[T]) String() string { vv := ValueType[interface{}]{Val: val.Elem().Interface()} return vv.String() } - return fmt.Sprintf("%q", fmt.Sprint(v.Val)) + return fmt.Sprintf("%q", fmt.Sprintf("%+v", v.Val)) } } From 8c8c16665f186c44516a13a99fb5b88ad1925512 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 15:59:24 -0700 Subject: [PATCH 14/27] retrigger codecov From 647912d793e8ebd2a1bb642799bfd50574aca245 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 16:31:16 -0700 Subject: [PATCH 15/27] minor improvement to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 43741d7..1653c19 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ LOGGER_LEVEL='Info' # Small binaries -If you're never logging http requests/responses, use `-tags no_http` (or `-tags no_net`) to exclude the http/https logging utilities. +If you're never logging http requests/responses, use `-tags no_http` (or `-tags no_net`) to exclude the http/https logging utilities (which pulls in a lot of dependencies because of `net/http` init). If you never need to JSON log complex structures/types that have a special `json.Marshaler` then you can use `-tags no_net,no_json` for the smallest executables From 5efce327b4944d640fcbc44b91b468ce92011180 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 17:10:26 -0700 Subject: [PATCH 16/27] lint the no_json path too --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 739e439..626a306 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,7 @@ size-check: lint: .golangci.yml golangci-lint run + golangci-lint run --build-tags no_json .golangci.yml: Makefile curl -fsS -o .golangci.yml https://raw.githubusercontent.com/fortio/workflows/main/golangci.yml From 6e2d299025efac7ed5ab9f9e94f40da9fcd06636 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 17:12:28 -0700 Subject: [PATCH 17/27] json->JSON Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com> --- no_json_logging.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/no_json_logging.go b/no_json_logging.go index 52f8541..7128875 100644 --- a/no_json_logging.go +++ b/no_json_logging.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Moved json logging out so it can be skipped for smallest binaries based on build tags. +// Moved JSON logging out so it can be skipped for smallest binaries based on build tags. // This file is the variant that does serialization manually instead of using json.Marshal. //go:build no_json From 410f4363d4ecae5c85c5a17e10071fd6499c7019 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 30 Jun 2024 17:15:09 -0700 Subject: [PATCH 18/27] more json->JSON --- README.md | 6 +++--- levelsDemo/levels.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1653c19..c1d0b20 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ log.S(log.Info, "msg", log.Attr("key1", value1)...) See the `Config` object for options like whether to include line number and file name of caller or not etc -New since 1.4 server logging (as used in [fortio.org/scli](https://pkg.go.dev/fortio.org/scli#ServerMain) for instance) is now structured (json), client logging (as setup by [fortio.org/cli](https://pkg.go.dev/fortio.org/scli#ServerMain) remains as before. +New since 1.4 server logging (as used in [fortio.org/scli](https://pkg.go.dev/fortio.org/scli#ServerMain) for instance) is now structured (JSON), client logging (as setup by [fortio.org/cli](https://pkg.go.dev/fortio.org/scli#ServerMain) remains as before. One can also revert server to not be JSON through config. @@ -46,7 +46,7 @@ Which can be converted to JSONEntry but is also a fixed, optimized format (ie ts The timestamp `ts` is in seconds.microseconds since epoch (golang UnixMicro() split into seconds part before decimal and microseconds after) -Since 1.8 the Go Routine ID is present in json (`r` field) or colorized log output (for multi threaded server types). +Since 1.8 the Go Routine ID is present in JSON (`r` field) or colorized log output (for multi threaded server types). Optional additional `KeyValue` pairs can be added to the base structure using the new `log.S` or passed to `log.LogRequest` using `log.Any` and `log.Str`. Note that numbers, as well as arrays of any type and maps of string keys to any type are supported (but more expensive to serialize recursively). @@ -63,7 +63,7 @@ When output is redirected, JSON output: {"ts":1689986143.4634,"level":"err","r":1,"file":"levels.go","line":23,"msg":"This is an error message"} {"ts":1689986143.463403,"level":"crit","r":1,"file":"levels.go","line":24,"msg":"This is a critical message"} {"ts":1689986143.463406,"level":"fatal","r":1,"file":"levels.go","line":25,"msg":"This is a fatal message"} -This is a non json output, will get prefixed with a exclamation point with logc +This is a non JSON output, will get prefixed with a exclamation point with logc ``` When on console: diff --git a/levelsDemo/levels.go b/levelsDemo/levels.go index 7ec8737..7c47f73 100644 --- a/levelsDemo/levels.go +++ b/levelsDemo/levels.go @@ -14,10 +14,10 @@ func main() { log.Config.GoroutineID = false log.Debugf("This is a debug message without goroutine id, file:line nor prefix (cli style)") log.Config = log.DefaultConfig() - // So log fatal doesn't panic nor exit (so we can print the non json last line). + // So log fatal doesn't panic nor exit (so we can print the non JSON last line). log.Config.FatalPanics = false log.Config.FatalExit = func(int) {} - // Meat of the example: (some of these are reproducing fixed issues in `logc` json->console attributes detection) + // Meat of the example: (some of these are reproducing fixed issues in `logc` JSON->console attributes detection) log.Debugf("Back to default (server) logging style with a debug message ending with backslash \\") log.LogVf("This is a verbose message") log.Printf("This an always printed, file:line omitted message (and no level in console)") @@ -28,5 +28,5 @@ func main() { log.Errf("This is an error message") log.Critf("This is a critical message") log.Fatalf("This is a fatal message") //nolint:revive // we disabled exit for this demo - fmt.Println("This is a non json output, will get prefixed with a exclamation point with logc") + fmt.Println("This is a non JSON output, will get prefixed with a exclamation point with logc") } From 3a4c6bc432ac92b5af5be5f3d6555f2d191352e3 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 12:50:59 -0700 Subject: [PATCH 19/27] verify through test that byte = uint8 works and added log.Rune(k,v) to print 1 character as one would most likely expect --- logger.go | 5 +++++ logger_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/logger.go b/logger.go index 2e56606..50a906b 100644 --- a/logger.go +++ b/logger.go @@ -616,6 +616,11 @@ func Bool(key string, value bool) KeyVal { return Any(key, value) } +func Rune(key string, value rune) KeyVal { + // Special case otherwise rune is printed as int32 number + return Any(key, fmt.Sprintf("%c", value)) +} + func (v *KeyVal) StringValue() string { if !v.Cached { v.StrValue = v.Value.String() diff --git a/logger_test.go b/logger_test.go index 45e4eef..9401cd2 100644 --- a/logger_test.go +++ b/logger_test.go @@ -800,6 +800,38 @@ func TestPointers(t *testing.T) { } } +func TestMoreTypes(t *testing.T) { + var b byte = 42 + kv := Any("byte", b) + kvStr := kv.StringValue() + expected := `42` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } + runes := []rune("A\"Φ") // test plain ascii, quote, and multibyte + r := runes[0] + kv = Rune("rune", r) + kvStr = kv.StringValue() + expected = `"A"` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } + r = runes[1] + kv = Rune("rune", r) + kvStr = kv.StringValue() + expected = `"\""` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } + r = runes[2] + kv = Rune("rune", r) + kvStr = kv.StringValue() + expected = `"Φ"` + if kvStr != expected { + t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) + } +} + func TestStruct(t *testing.T) { type testStruct struct { Msg1 string From bab50906fd27b03c617e1303165fe728f4b0d6f1 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 12:54:39 -0700 Subject: [PATCH 20/27] make the rune test slightly more readable --- logger_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logger_test.go b/logger_test.go index 9401cd2..ef966c4 100644 --- a/logger_test.go +++ b/logger_test.go @@ -808,7 +808,7 @@ func TestMoreTypes(t *testing.T) { if kvStr != expected { t.Errorf("unexpected:\n%s\nvs:\n%s\n", kvStr, expected) } - runes := []rune("A\"Φ") // test plain ascii, quote, and multibyte + runes := []rune(`A"Φ`) // test plain ascii, a double quote, and multibyte r := runes[0] kv = Rune("rune", r) kvStr = kv.StringValue() From 4b32ab67de41dc9538e399238c3f8331f3d5f71b Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 12:59:01 -0700 Subject: [PATCH 21/27] more efficient conversion rune to string --- logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logger.go b/logger.go index 50a906b..6db46df 100644 --- a/logger.go +++ b/logger.go @@ -618,7 +618,7 @@ func Bool(key string, value bool) KeyVal { func Rune(key string, value rune) KeyVal { // Special case otherwise rune is printed as int32 number - return Any(key, fmt.Sprintf("%c", value)) + return Any(key, string(value)) // similar to "%c". } func (v *KeyVal) StringValue() string { From 9c02bb38da16d89cf10cb6c5252860489019f66f Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 13:30:38 -0700 Subject: [PATCH 22/27] Apply suggestions from code review Co-authored-by: ccoVeille <3875889+ccoVeille@users.noreply.github.com> --- README.md | 2 +- json_logging_test.go | 2 +- levelsDemo/levels.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c1d0b20..51ef7aa 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ When output is redirected, JSON output: {"ts":1689986143.4634,"level":"err","r":1,"file":"levels.go","line":23,"msg":"This is an error message"} {"ts":1689986143.463403,"level":"crit","r":1,"file":"levels.go","line":24,"msg":"This is a critical message"} {"ts":1689986143.463406,"level":"fatal","r":1,"file":"levels.go","line":25,"msg":"This is a fatal message"} -This is a non JSON output, will get prefixed with a exclamation point with logc +This is a non-JSON output, will get prefixed with a exclamation point with logc ``` When on console: diff --git a/json_logging_test.go b/json_logging_test.go index 659aed9..af55efe 100644 --- a/json_logging_test.go +++ b/json_logging_test.go @@ -11,7 +11,7 @@ import ( func TestToJSON_MarshalError(t *testing.T) { badValue := make(chan int) - expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "json: unsupported type: chan int") + expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "JSON: unsupported type: chan int") actual := toJSON(badValue) if actual != expected { diff --git a/levelsDemo/levels.go b/levelsDemo/levels.go index 7c47f73..5ef98d0 100644 --- a/levelsDemo/levels.go +++ b/levelsDemo/levels.go @@ -14,7 +14,7 @@ func main() { log.Config.GoroutineID = false log.Debugf("This is a debug message without goroutine id, file:line nor prefix (cli style)") log.Config = log.DefaultConfig() - // So log fatal doesn't panic nor exit (so we can print the non JSON last line). + // So log fatal doesn't panic nor exit (so we can print the non-JSON last line). log.Config.FatalPanics = false log.Config.FatalExit = func(int) {} // Meat of the example: (some of these are reproducing fixed issues in `logc` JSON->console attributes detection) @@ -28,5 +28,5 @@ func main() { log.Errf("This is an error message") log.Critf("This is a critical message") log.Fatalf("This is a fatal message") //nolint:revive // we disabled exit for this demo - fmt.Println("This is a non JSON output, will get prefixed with a exclamation point with logc") + fmt.Println("This is a non-JSON output, will get prefixed with a exclamation point with logc") } From 8f090f791f768285ba8ed24d2c6bed8c151563f1 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 13:34:18 -0700 Subject: [PATCH 23/27] don't break standard lib message checks --- json_logging_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/json_logging_test.go b/json_logging_test.go index af55efe..659aed9 100644 --- a/json_logging_test.go +++ b/json_logging_test.go @@ -11,7 +11,7 @@ import ( func TestToJSON_MarshalError(t *testing.T) { badValue := make(chan int) - expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "JSON: unsupported type: chan int") + expected := fmt.Sprintf("\"ERR marshaling %v: %v\"", badValue, "json: unsupported type: chan int") actual := toJSON(badValue) if actual != expected { From 8c8094b86ef7f92484bc3818f4f62c7119b9bf82 Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 13:57:38 -0700 Subject: [PATCH 24/27] put variable in makefile for go so I can run 'make GOBIN=go1.23rc1' --- Makefile | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 626a306..7f5ec29 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,31 @@ +GOBIN:=$(GOBIN) + all: test example test: - go test -race ./... - go test -tags no_json ./... - go test -tags no_http ./... + $(GOBIN) test -race ./... + $(GOBIN) test -tags no_json ./... + $(GOBIN) test -tags no_http ./... local-coverage: coverage - go test -coverprofile=coverage.out ./... - go tool cover -html=coverage.out + $(GOBIN) test -coverprofile=coverage.out ./... + $(GOBIN) tool cover -html=coverage.out coverage: - go test -coverprofile=coverage1.out ./... - go test -tags no_net -coverprofile=coverage2.out ./... - go test -tags no_json -coverprofile=coverage3.out ./... - go test -tags no_http,no_json -coverprofile=coverage4.out ./... + $(GOBIN) test -coverprofile=coverage1.out ./... + $(GOBIN) test -tags no_net -coverprofile=coverage2.out ./... + $(GOBIN) test -tags no_json -coverprofile=coverage3.out ./... + $(GOBIN) test -tags no_http,no_json -coverprofile=coverage4.out ./... # cat coverage*.out > coverage.out - go install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c + $(GOBIN) install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c gocovmerge coverage?.out > coverage.out example: @echo "### Colorized (default) ###" - go run ./levelsDemo + $(GOBIN) run ./levelsDemo @echo "### JSON: (redirected stderr) ###" - go run ./levelsDemo 3>&1 1>&2 2>&3 | jq -c + $(GOBIN) run ./levelsDemo 3>&1 1>&2 2>&3 | jq -c line: @echo @@ -34,13 +36,13 @@ screenshot: line example size-check: @echo "### Size of the binary:" - CGO_ENABLED=0 go build -ldflags="-w -s" -trimpath -o ./fullsize ./levelsDemo + CGO_ENABLED=0 $(GOBIN) build -ldflags="-w -s" -trimpath -o ./fullsize ./levelsDemo ls -lh ./fullsize - CGO_ENABLED=0 go build -tags no_net -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + CGO_ENABLED=0 $(GOBIN) build -tags no_net -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize - CGO_ENABLED=0 go build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + CGO_ENABLED=0 $(GOBIN) build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize - gsa ./smallsize # go install github.com/Zxilly/go-size-analyzer/cmd/gsa@master + gsa ./smallsize # $(GOBIN) install github.com/Zxilly/$(GOBIN)-size-analyzer/cmd/gsa@master lint: .golangci.yml From a085108b8ee497ba24a0b00afae8b312bdef523c Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 14:07:57 -0700 Subject: [PATCH 25/27] better to not search and replace ALL without testing --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7f5ec29..ddbe74b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -GOBIN:=$(GOBIN) +GOBIN:=go all: test example From e46248980e9dedce26c02a23953426d841adec5e Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 14:16:39 -0700 Subject: [PATCH 26/27] thanks @ccoVeille - was using a defined go env var (GOBIN) instead of makefile specific/local (GO_BIN) - tweaked the make all target --- Makefile | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index ddbe74b..5853a70 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,35 @@ -GOBIN:=go +GO_BIN?=GOTOOLCHAIN=local go -all: test example +all: info test lint size-check coverage example + +info: + @echo "### Go (using GO_BIN=\"$(GO_BIN)\") version:" + $(GO_BIN) version test: - $(GOBIN) test -race ./... - $(GOBIN) test -tags no_json ./... - $(GOBIN) test -tags no_http ./... + $(GO_BIN) test -race ./... + $(GO_BIN) test -tags no_json ./... + $(GO_BIN) test -tags no_http ./... local-coverage: coverage - $(GOBIN) test -coverprofile=coverage.out ./... - $(GOBIN) tool cover -html=coverage.out + $(GO_BIN) test -coverprofile=coverage.out ./... + $(GO_BIN) tool cover -html=coverage.out coverage: - $(GOBIN) test -coverprofile=coverage1.out ./... - $(GOBIN) test -tags no_net -coverprofile=coverage2.out ./... - $(GOBIN) test -tags no_json -coverprofile=coverage3.out ./... - $(GOBIN) test -tags no_http,no_json -coverprofile=coverage4.out ./... + $(GO_BIN) test -coverprofile=coverage1.out ./... + $(GO_BIN) test -tags no_net -coverprofile=coverage2.out ./... + $(GO_BIN) test -tags no_json -coverprofile=coverage3.out ./... + $(GO_BIN) test -tags no_http,no_json -coverprofile=coverage4.out ./... # cat coverage*.out > coverage.out - $(GOBIN) install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c + $(GO_BIN) install github.com/wadey/gocovmerge@b5bfa59ec0adc420475f97f89b58045c721d761c gocovmerge coverage?.out > coverage.out example: @echo "### Colorized (default) ###" - $(GOBIN) run ./levelsDemo + $(GO_BIN) run ./levelsDemo @echo "### JSON: (redirected stderr) ###" - $(GOBIN) run ./levelsDemo 3>&1 1>&2 2>&3 | jq -c + $(GO_BIN) run ./levelsDemo 3>&1 1>&2 2>&3 | jq -c line: @echo @@ -36,13 +40,13 @@ screenshot: line example size-check: @echo "### Size of the binary:" - CGO_ENABLED=0 $(GOBIN) build -ldflags="-w -s" -trimpath -o ./fullsize ./levelsDemo + CGO_ENABLED=0 $(GO_BIN) build -ldflags="-w -s" -trimpath -o ./fullsize ./levelsDemo ls -lh ./fullsize - CGO_ENABLED=0 $(GOBIN) build -tags no_net -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + CGO_ENABLED=0 $(GO_BIN) build -tags no_net -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize - CGO_ENABLED=0 $(GOBIN) build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo + CGO_ENABLED=0 $(GO_BIN) build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize - gsa ./smallsize # $(GOBIN) install github.com/Zxilly/$(GOBIN)-size-analyzer/cmd/gsa@master + gsa ./smallsize # $(GO_BIN) install github.com/Zxilly/$(GO_BIN)-size-analyzer/cmd/gsa@master lint: .golangci.yml @@ -53,4 +57,4 @@ lint: .golangci.yml curl -fsS -o .golangci.yml https://raw.githubusercontent.com/fortio/workflows/main/golangci.yml -.PHONY: all test example screenshot line lint +.PHONY: all info test lint size-check local-coverage example screenshot line coverage From 7ec8cc2eb34913f925e236bde9f758e6b1004d3e Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Mon, 1 Jul 2024 14:20:25 -0700 Subject: [PATCH 27/27] fix comment / another bad search and replace --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5853a70..517602e 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ size-check: ls -lh ./smallsize CGO_ENABLED=0 $(GO_BIN) build -tags no_http,no_json -ldflags="-w -s" -trimpath -o ./smallsize ./levelsDemo ls -lh ./smallsize - gsa ./smallsize # $(GO_BIN) install github.com/Zxilly/$(GO_BIN)-size-analyzer/cmd/gsa@master + gsa ./smallsize # go install github.com/Zxilly/go-size-analyzer/cmd/gsa@master lint: .golangci.yml