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.
129 lines
3.2 KiB
129 lines
3.2 KiB
package logger
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
|
|
logboxclient "git.lowcodeplatform.net/fabric/logbox-client"
|
|
)
|
|
|
|
// LogLine структура строк лог-файла. нужна для анмаршалинга
|
|
type LogLine struct {
|
|
Uid string `json:"uid"`
|
|
Level string `json:"level"`
|
|
Name string `json:"logger"`
|
|
Type string `json:"service-type"`
|
|
Time string `json:"ts"`
|
|
Timing string `json:"timing"`
|
|
ConfigID string `json:"config-id"`
|
|
RequestID string `json:"request-id"`
|
|
UserID string `json:"user-id"`
|
|
ServiceID string `json:"service-id"`
|
|
Msg interface{} `json:"msg"`
|
|
}
|
|
|
|
type LogboxConfig struct {
|
|
Endpoint, AccessKeyID, SecretKey string
|
|
RequestTimeout time.Duration
|
|
CbMaxRequests uint32
|
|
CbTimeout, CbInterval time.Duration
|
|
ProjectKey string
|
|
}
|
|
|
|
func (l *LogboxConfig) client(ctx context.Context) (client logboxclient.Client, err error) {
|
|
client, err = logboxclient.New(ctx, l.Endpoint, l.RequestTimeout, l.CbMaxRequests, l.CbTimeout, l.CbInterval, l.ProjectKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return client, nil
|
|
}
|
|
|
|
type logboxSender struct {
|
|
requestTimeout time.Duration
|
|
logboxClient logboxclient.Client
|
|
}
|
|
|
|
func (v *logboxSender) Write(p []byte) (n int, err error) {
|
|
reqTimeout, cancel := context.WithTimeout(context.Background(), v.requestTimeout)
|
|
defer cancel()
|
|
|
|
newReq := v.logboxClient.NewUpsertReq()
|
|
recordsBytes := bytes.Split(p, []byte("\n"))
|
|
for _, value := range recordsBytes {
|
|
if string(value) == "" {
|
|
continue
|
|
}
|
|
|
|
l := LogLine{}
|
|
err = json.Unmarshal(value, &l)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("error unmarshal to logline. err: %s, value: %s", err, string(value))
|
|
}
|
|
newReq.AddEvent(v.logboxClient.NewEvent(
|
|
l.Uid,
|
|
l.Level,
|
|
l.Type,
|
|
l.Name,
|
|
l.ConfigID,
|
|
l.RequestID,
|
|
l.UserID,
|
|
l.ServiceID,
|
|
l.Msg.(string),
|
|
l.Time,
|
|
l.Timing,
|
|
string(value),
|
|
))
|
|
}
|
|
|
|
_, err = v.logboxClient.Upsert(reqTimeout, newReq)
|
|
|
|
return len(p), err
|
|
}
|
|
|
|
func (v *logboxSender) Sync() error {
|
|
return v.logboxClient.Close()
|
|
}
|
|
|
|
// SetupDefaultLogboxLogger инициируем логирование в сервис Logbox
|
|
func SetupDefaultLogboxLogger(namespace string, cfg LogboxConfig, options map[string]string) (err error) {
|
|
if len(cfg.Endpoint) == 0 {
|
|
return errors.New("logbox address must be specified")
|
|
}
|
|
|
|
cl, err := cfg.client(context.Background())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// инициализировать лог и его ротацию
|
|
ws := &logboxSender{
|
|
requestTimeout: cfg.RequestTimeout,
|
|
logboxClient: cl,
|
|
}
|
|
|
|
enc := newStringCastingEncoder(zap.NewProductionEncoderConfig())
|
|
core := zapcore.NewCore(enc, ws, zap.NewAtomicLevelAt(zap.InfoLevel))
|
|
|
|
errOut, _, err := zap.Open("stderr")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
opts := []zap.Option{zap.ErrorOutput(errOut), zap.AddCaller()}
|
|
for k, v := range options {
|
|
opts = append(opts, zap.Fields(zap.String(k, v)))
|
|
}
|
|
|
|
logger := zap.New(core, opts...)
|
|
defaultLogger = New(logger.Named(namespace))
|
|
|
|
return nil
|
|
}
|
|
|