mirror of
https://github.com/go-kratos/kratos.git
synced 2025-03-17 21:07:54 +02:00
fix(log): toString float32 precision loss and convert uint use FormatUint
(#2461)
* fix(log): toString float32 precision loss * convert uint to string
This commit is contained in:
parent
4bd1fde7ef
commit
a911f8f9ee
@ -16,6 +16,7 @@ import (
|
||||
// Logger see more detail https://github.com/aliyun/aliyun-log-go-sdk
|
||||
type Logger interface {
|
||||
log.Logger
|
||||
|
||||
GetProducer() *producer.Producer
|
||||
Close() error
|
||||
}
|
||||
@ -81,22 +82,16 @@ func (a *aliyunLog) Close() error {
|
||||
}
|
||||
|
||||
func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
|
||||
buf := level.String()
|
||||
levelTitle := "level"
|
||||
|
||||
contents := make([]*sls.LogContent, 0)
|
||||
contents := make([]*sls.LogContent, 0, len(keyvals)/2+1)
|
||||
|
||||
contents = append(contents, &sls.LogContent{
|
||||
Key: &levelTitle,
|
||||
Value: &buf,
|
||||
Key: newString(level.Key()),
|
||||
Value: newString(level.String()),
|
||||
})
|
||||
|
||||
for i := 0; i < len(keyvals); i += 2 {
|
||||
key := toString(keyvals[i])
|
||||
value := toString(keyvals[i+1])
|
||||
contents = append(contents, &sls.LogContent{
|
||||
Key: &key,
|
||||
Value: &value,
|
||||
Key: newString(toString(keyvals[i])),
|
||||
Value: newString(toString(keyvals[i+1])),
|
||||
})
|
||||
}
|
||||
|
||||
@ -104,9 +99,7 @@ func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
|
||||
Time: proto.Uint32(uint32(time.Now().Unix())),
|
||||
Contents: contents,
|
||||
}
|
||||
|
||||
err := a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
|
||||
return err
|
||||
return a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
|
||||
}
|
||||
|
||||
// NewAliyunLog new a aliyun logger with options.
|
||||
@ -128,6 +121,11 @@ func NewAliyunLog(options ...Option) Logger {
|
||||
}
|
||||
}
|
||||
|
||||
// newString string convert to *string
|
||||
func newString(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// toString convert any type to string
|
||||
func toString(v interface{}) string {
|
||||
var key string
|
||||
@ -138,23 +136,23 @@ func toString(v interface{}) string {
|
||||
case float64:
|
||||
key = strconv.FormatFloat(v, 'f', -1, 64)
|
||||
case float32:
|
||||
key = strconv.FormatFloat(float64(v), 'f', -1, 64)
|
||||
key = strconv.FormatFloat(float64(v), 'f', -1, 32)
|
||||
case int:
|
||||
key = strconv.Itoa(v)
|
||||
case uint:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int8:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint8:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int16:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint16:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int32:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint32:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int64:
|
||||
key = strconv.FormatInt(v, 10)
|
||||
case uint64:
|
||||
|
@ -2,6 +2,7 @@ package aliyun
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/log"
|
||||
@ -99,34 +100,44 @@ func TestLog(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
in interface{}
|
||||
out string
|
||||
}{
|
||||
{math.MaxFloat64, "17976931348623157000000000000000000000000000000000000" +
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
|
||||
"0000000000000000000000000000000"},
|
||||
{math.MaxFloat32, "340282346638528860000000000000000000000"},
|
||||
{1<<((32<<(^uint(0)>>63))-1) - 1, "9223372036854775807"},
|
||||
{uint(1<<(32<<(^uint(0)>>63)) - 1), "-1"},
|
||||
{math.MaxInt8, "127"},
|
||||
{math.MaxUint8, "255"},
|
||||
{math.MaxInt16, "32767"},
|
||||
{math.MaxUint16, "65535"},
|
||||
{math.MaxInt32, "2147483647"},
|
||||
{math.MaxUint32, "4294967295"},
|
||||
{math.MaxInt64, "9223372036854775807"},
|
||||
{uint64(math.MaxUint64), "18446744073709551615"},
|
||||
{"abc", "abc"},
|
||||
{false, "false"},
|
||||
{[]byte("abc"), "abc"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
if toString(test.in) != test.out {
|
||||
t.Fatalf("want: %s, got: %s", test.out, toString(test.in))
|
||||
}
|
||||
func TestNewString(t *testing.T) {
|
||||
ptr := newString("")
|
||||
if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
|
||||
t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in interface{}
|
||||
out string
|
||||
}{
|
||||
{"float64", 6.66, "6.66"},
|
||||
{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
|
||||
{"float32", float32(6.66), "6.66"},
|
||||
{"max float32", math.MaxFloat32, "340282346638528860000000000000000000000"},
|
||||
{"int", int(math.MaxInt64), "9223372036854775807"},
|
||||
{"uint", uint(math.MaxUint64), "18446744073709551615"},
|
||||
{"int8", math.MaxInt8, "127"},
|
||||
{"uint8", math.MaxUint8, "255"},
|
||||
{"int16", math.MaxInt16, "32767"},
|
||||
{"uint16", math.MaxUint16, "65535"},
|
||||
{"int32", math.MaxInt32, "2147483647"},
|
||||
{"uint32", math.MaxUint32, "4294967295"},
|
||||
{"int64", math.MaxInt64, "9223372036854775807"},
|
||||
{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
|
||||
{"string", "abc", "abc"},
|
||||
{"bool", false, "false"},
|
||||
{"[]byte", []byte("abc"), "abc"},
|
||||
{"struct", struct{ Name string }{}, `{"Name":""}`},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
out := toString(test.in)
|
||||
if test.out != out {
|
||||
t.Fatalf("want: %s, got: %s", test.out, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
|
||||
type Logger interface {
|
||||
log.Logger
|
||||
GetProducer() *cls.AsyncProducerClient
|
||||
|
||||
GetProducer() *cls.AsyncProducerClient
|
||||
Close() error
|
||||
}
|
||||
|
||||
@ -66,25 +66,20 @@ func WithAccessSecret(as string) Option {
|
||||
type Option func(cls *options)
|
||||
|
||||
func (log *tencentLog) Close() error {
|
||||
err := log.producer.Close(5000)
|
||||
return err
|
||||
return log.producer.Close(5000)
|
||||
}
|
||||
|
||||
func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
|
||||
buf := level.String()
|
||||
levelTitle := "level"
|
||||
contents := make([]*cls.Log_Content, 0)
|
||||
contents := make([]*cls.Log_Content, 0, len(keyvals)/2+1)
|
||||
|
||||
contents = append(contents, &cls.Log_Content{
|
||||
Key: &levelTitle,
|
||||
Value: &buf,
|
||||
Key: newString(level.Key()),
|
||||
Value: newString(level.String()),
|
||||
})
|
||||
for i := 0; i < len(keyvals); i += 2 {
|
||||
key := toString(keyvals[i])
|
||||
value := toString(keyvals[i+1])
|
||||
contents = append(contents, &cls.Log_Content{
|
||||
Key: &key,
|
||||
Value: &value,
|
||||
Key: newString(toString(keyvals[i])),
|
||||
Value: newString(toString(keyvals[i+1])),
|
||||
})
|
||||
}
|
||||
|
||||
@ -92,8 +87,7 @@ func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
|
||||
Time: proto.Int64(time.Now().Unix()),
|
||||
Contents: contents,
|
||||
}
|
||||
err := log.producer.SendLog(log.opts.topicID, logInst, nil)
|
||||
return err
|
||||
return log.producer.SendLog(log.opts.topicID, logInst, nil)
|
||||
}
|
||||
|
||||
func NewLogger(options ...Option) (Logger, error) {
|
||||
@ -115,6 +109,10 @@ func NewLogger(options ...Option) (Logger, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newString(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
// toString convert any type to string
|
||||
func toString(v interface{}) string {
|
||||
var key string
|
||||
@ -125,23 +123,23 @@ func toString(v interface{}) string {
|
||||
case float64:
|
||||
key = strconv.FormatFloat(v, 'f', -1, 64)
|
||||
case float32:
|
||||
key = strconv.FormatFloat(float64(v), 'f', -1, 64)
|
||||
key = strconv.FormatFloat(float64(v), 'f', -1, 32)
|
||||
case int:
|
||||
key = strconv.Itoa(v)
|
||||
case uint:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int8:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint8:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int16:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint16:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int32:
|
||||
key = strconv.Itoa(int(v))
|
||||
case uint32:
|
||||
key = strconv.Itoa(int(v))
|
||||
key = strconv.FormatUint(uint64(v), 10)
|
||||
case int64:
|
||||
key = strconv.FormatInt(v, 10)
|
||||
case uint64:
|
||||
|
@ -1,6 +1,8 @@
|
||||
package tencent
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kratos/kratos/v2/log"
|
||||
@ -101,3 +103,45 @@ func TestLog(t *testing.T) {
|
||||
t.Errorf("Log() returns error:%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewString(t *testing.T) {
|
||||
ptr := newString("")
|
||||
if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
|
||||
t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in interface{}
|
||||
out string
|
||||
}{
|
||||
{"float64", 6.66, "6.66"},
|
||||
{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
|
||||
{"float32", float32(6.66), "6.66"},
|
||||
{"max float32", math.MaxFloat32, "340282346638528860000000000000000000000"},
|
||||
{"int", int(math.MaxInt64), "9223372036854775807"},
|
||||
{"uint", uint(math.MaxUint64), "18446744073709551615"},
|
||||
{"int8", math.MaxInt8, "127"},
|
||||
{"uint8", math.MaxUint8, "255"},
|
||||
{"int16", math.MaxInt16, "32767"},
|
||||
{"uint16", math.MaxUint16, "65535"},
|
||||
{"int32", math.MaxInt32, "2147483647"},
|
||||
{"uint32", math.MaxUint32, "4294967295"},
|
||||
{"int64", math.MaxInt64, "9223372036854775807"},
|
||||
{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
|
||||
{"string", "abc", "abc"},
|
||||
{"bool", false, "false"},
|
||||
{"[]byte", []byte("abc"), "abc"},
|
||||
{"struct", struct{ Name string }{}, `{"Name":""}`},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
out := toString(test.in)
|
||||
if test.out != out {
|
||||
t.Fatalf("want: %s, got: %s", test.out, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ const (
|
||||
LevelFatal
|
||||
)
|
||||
|
||||
func (l Level) Key() string {
|
||||
return LevelKey
|
||||
}
|
||||
|
||||
func (l Level) String() string {
|
||||
switch l {
|
||||
case LevelDebug:
|
||||
|
@ -2,6 +2,12 @@ package log
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestLevel_Key(t *testing.T) {
|
||||
if LevelInfo.Key() != LevelKey {
|
||||
t.Errorf("want: %s, got: %s", LevelKey, LevelInfo.Key())
|
||||
}
|
||||
}
|
||||
|
||||
func TestLevel_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
Loading…
x
Reference in New Issue
Block a user