You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kratos/contrib/log/tencent/tencent.go

163 lines
3.1 KiB

package tencent
import (
"encoding/json"
"fmt"
"strconv"
"time"
cls "github.com/tencentcloud/tencentcloud-cls-sdk-go"
"google.golang.org/protobuf/proto"
log "github.com/go-kratos/kratos/v2/log"
)
type Logger interface {
log.Logger
GetProducer() *cls.AsyncProducerClient
Close() error
}
type tencentLog struct {
producer *cls.AsyncProducerClient
opts *options
}
func (log *tencentLog) GetProducer() *cls.AsyncProducerClient {
return log.producer
}
type options struct {
topicID string
accessKey string
accessSecret string
endpoint string
}
func defaultOptions() *options {
return &options{}
}
func WithEndpoint(endpoint string) Option {
return func(cls *options) {
cls.endpoint = endpoint
}
}
func WithTopicID(topicID string) Option {
return func(cls *options) {
cls.topicID = topicID
}
}
func WithAccessKey(ak string) Option {
return func(cls *options) {
cls.accessKey = ak
}
}
func WithAccessSecret(as string) Option {
return func(cls *options) {
cls.accessSecret = as
}
}
type Option func(cls *options)
func (log *tencentLog) Close() error {
err := log.producer.Close(5000)
return err
}
func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
buf := level.String()
levelTitle := "level"
contents := make([]*cls.Log_Content, 0)
contents = append(contents, &cls.Log_Content{
Key: &levelTitle,
Value: &buf,
})
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,
})
}
logInst := &cls.Log{
Time: proto.Int64(time.Now().Unix()),
Contents: contents,
}
err := log.producer.SendLog(log.opts.topicID, logInst, nil)
return err
}
func NewLogger(options ...Option) (Logger, error) {
opts := defaultOptions()
for _, o := range options {
o(opts)
}
producerConfig := cls.GetDefaultAsyncProducerClientConfig()
producerConfig.AccessKeyID = opts.accessKey
producerConfig.AccessKeySecret = opts.accessSecret
producerConfig.Endpoint = opts.endpoint
producerInst, err := cls.NewAsyncProducerClient(producerConfig)
if err != nil {
return nil, err
}
return &tencentLog{
producer: producerInst,
opts: opts,
}, nil
}
// toString convert any type to string
func toString(v interface{}) string {
var key string
if v == nil {
return key
}
switch v := v.(type) {
case float64:
key = strconv.FormatFloat(v, 'f', -1, 64)
case float32:
key = strconv.FormatFloat(float64(v), 'f', -1, 64)
case int:
key = strconv.Itoa(v)
case uint:
key = strconv.Itoa(int(v))
case int8:
key = strconv.Itoa(int(v))
case uint8:
key = strconv.Itoa(int(v))
case int16:
key = strconv.Itoa(int(v))
case uint16:
key = strconv.Itoa(int(v))
case int32:
key = strconv.Itoa(int(v))
case uint32:
key = strconv.Itoa(int(v))
case int64:
key = strconv.FormatInt(v, 10)
case uint64:
key = strconv.FormatUint(v, 10)
case string:
key = v
case bool:
key = strconv.FormatBool(v)
case []byte:
key = string(v)
case fmt.Stringer:
key = v.String()
default:
newValue, _ := json.Marshal(v)
key = string(newValue)
}
return key
}