追加统一sls接入和请求日志写入sls方法

master
wujianhua 1 year ago
parent 80d23bb340
commit 0b2a2a4d44
  1. 104
      sls/log.go
  2. 123
      sls/producer.go
  3. 60
      sls/producer_test.go
  4. 46
      sls/types.go

@ -0,0 +1,104 @@
package sls
import (
"encoding/json"
"time"
sls "github.com/aliyun/aliyun-log-go-sdk"
"google.golang.org/protobuf/proto"
)
// GenerateLog 传入固定请求日志,生成sls对应格式日志
func GenerateLog(request *Request) *sls.Log {
var log sls.Log
// 获取当前时间
log.Time = proto.Uint32(uint32(time.Now().Unix()))
contents := make([]*sls.LogContent, 0)
// time
contents = append(contents, &sls.LogContent{
Key: proto.String("time"),
Value: proto.String(request.Time.Format("2006-01-02 15:04:05")),
})
// remote_addr
contents = append(contents, &sls.LogContent{
Key: proto.String("remote_addr"),
Value: proto.String(request.RemoteAddr),
})
// query_string
contents = append(contents, &sls.LogContent{
Key: proto.String("query_string"),
Value: proto.String(request.QueryString),
})
// request_method
contents = append(contents, &sls.LogContent{
Key: proto.String("request_method"),
Value: proto.String(request.RequestMethod),
})
// request_uri
contents = append(contents, &sls.LogContent{
Key: proto.String("request_uri"),
Value: proto.String(request.RequestUri),
})
// host
contents = append(contents, &sls.LogContent{
Key: proto.String("host"),
Value: proto.String(request.Host),
})
// request_body
contents = append(contents, &sls.LogContent{
Key: proto.String("request_body"),
Value: proto.String(request.RequestBody),
})
// http_user_agent
contents = append(contents, &sls.LogContent{
Key: proto.String("http_user_agent"),
Value: proto.String(request.HttpUserAgent),
})
// http_finger
contents = append(contents, &sls.LogContent{
Key: proto.String("http_finger"),
Value: proto.String(request.HttpFinger),
})
// http_referrer
contents = append(contents, &sls.LogContent{
Key: proto.String("http_referrer"),
Value: proto.String(request.HttpReferrer),
})
// http_trace_id
contents = append(contents, &sls.LogContent{
Key: proto.String("http_trace_id"),
Value: proto.String(request.HttpTraceId),
})
// x_app_id
contents = append(contents, &sls.LogContent{
Key: proto.String("x_app_id"),
Value: proto.String(request.XAppId),
})
// x_user_data
userData, _ := json.Marshal(request.XUserData)
contents = append(contents, &sls.LogContent{
Key: proto.String("x_user_data"),
Value: proto.String(string(userData)),
})
// x_dsm_data
dsmData, _ := json.Marshal(request.XDsmData)
contents = append(contents, &sls.LogContent{
Key: proto.String("x_dsm_data"),
Value: proto.String(string(dsmData)),
})
// http_trace_id
customData, _ := json.Marshal(request.XCustomData)
contents = append(contents, &sls.LogContent{
Key: proto.String("x_custom_data"),
Value: proto.String(string(customData)),
})
// response_data
respData, _ := json.Marshal(request.ResponseData)
contents = append(contents, &sls.LogContent{
Key: proto.String("response_data"),
Value: proto.String(string(respData)),
})
log.Contents = contents
return &log
}

@ -0,0 +1,123 @@
package sls
import (
"gitea.drugeyes.vip/pharnexbase/utils/enum"
sls "github.com/aliyun/aliyun-log-go-sdk"
"github.com/aliyun/aliyun-log-go-sdk/producer"
)
type options struct {
accessKey string
accessSecret string
endpoint string
project string
logstore string
}
func defaultOptions() *options {
return &options{
project: "bcpm-log",
logstore: "request-develop",
}
}
// WithEndpoint 指定端口
func WithEndpoint(endpoint string) Option {
return func(alc *options) {
alc.endpoint = endpoint
}
}
// WithProject 指定发送普通日志的project
func WithProject(project string) Option {
return func(alc *options) {
alc.project = project
}
}
// WithLogstore 指定发送普通日志的logstore
func WithLogstore(logstore string) Option {
return func(alc *options) {
alc.logstore = logstore
}
}
// WithAccessKey 设置访问access id
func WithAccessKey(ak string) Option {
return func(alc *options) {
alc.accessKey = ak
}
}
// WithAccessSecret 设置访问access secret
func WithAccessSecret(as string) Option {
return func(alc *options) {
alc.accessSecret = as
}
}
type Option func(alc *options)
type slsProducer struct {
pr *producer.Producer
opts *options
}
// NewSLSProducer 创建一个高性能的sls制造者
func NewSLSProducer(opts ...Option) *slsProducer {
opt := defaultOptions()
for _, o := range opts {
o(opt)
}
producerConfig := producer.GetDefaultProducerConfig()
producerConfig.Endpoint = opt.endpoint
producerConfig.AccessKeyID = opt.accessKey
producerConfig.AccessKeySecret = opt.accessSecret
producerInstance := producer.InitProducer(producerConfig)
producerInstance.Start()
return &slsProducer{
pr: producerInstance,
opts: opt,
}
}
// Close 程序结束时,必须调用该方法,不然可能导致部分日志丢失
func (s *slsProducer) Close() error {
return s.pr.Close(5000)
}
// SendLog 发送普通日志
func (s *slsProducer) SendLog(log *sls.Log) error {
err := s.pr.SendLog(s.opts.project, s.opts.logstore, "", "", log)
if err != nil {
return err
}
return nil
}
// SendRequestLog 发送特定的请求日志,使用该方法时,不需要指定project和logstore
func (s *slsProducer) SendRequestLog(env enum.Env, req *Request) error {
log := GenerateLog(req)
err := s.pr.SendLog("bcpm-log", getLogStore(env), "", "", log)
if err != nil {
return err
}
return nil
}
func getLogStore(env enum.Env) string {
switch env {
case enum.Env_local, enum.Env_develop:
return "request-develop"
case enum.Env_preview:
return "request-preview"
case enum.Env_production:
return "request"
default:
return "request-develop"
}
}

@ -0,0 +1,60 @@
package sls
import (
"testing"
"time"
"gitea.drugeyes.vip/pharnexbase/utils/enum"
)
var pd *slsProducer
func init() {
pd = NewSLSProducer(
WithEndpoint("cn-hangzhou.log.aliyuncs.com"),
WithAccessKey("-"), // 传入阿里云sls的key
WithAccessSecret("-"), // 传入阿里云sls的Secret
)
}
func TestProducer(t *testing.T) {
err := pd.SendRequestLog(enum.Env_develop, &Request{
Time: time.Now(),
RemoteAddr: "118.112.98.208",
QueryString: "test001",
RequestMethod: "POST",
RequestUri: "/dc/analyse/senior_aggregation",
Host: "intsynth-server.drugeyes.vip",
RequestBody: "{}",
HttpUserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 OPR/99.0.0.0",
HttpFinger: "59246b1e1639f4753bcd010bac2ddb01",
HttpReferrer: "http://intsynth-web.drugeyes.vip:7031/",
HttpTraceId: "0121",
XAppId: "LtEolTiV",
XUserData: &UserData{
ID: "1075",
Username: "用户名_IDdXdk4xSU",
OrganizeID: "223",
OrganizeName: "新数据-机构06-权限",
Email: "",
Phone: "17800000051",
},
XDsmData: &DSMData{
AppKey: "ce2f8bcc2f64466d",
PageType: "LIST",
DataCount: 1,
DBData: make([]*DBCount, 0),
},
XCustomData: nil,
ResponseData: nil,
})
if err != nil {
t.Fail()
}
err = pd.Close()
if err != nil {
t.Fail()
}
}

@ -0,0 +1,46 @@
package sls
import "time"
// Request HTTP请求
type Request struct {
Time time.Time `json:"time"` // 请求时间
RemoteAddr string `json:"remote_addr"` // 客户IP
QueryString string `json:"query_string"` // Query参数
RequestMethod string `json:"request_method"` // 请求方法
RequestUri string `json:"request_uri"` // 请求地址
Host string `json:"host"` // host地址
RequestBody string `json:"request_body"` // 请求body
HttpUserAgent string `json:"http_user_agent"` // 浏览器标识
HttpFinger string `json:"http_finger"` // 浏览器指纹
HttpReferrer string `json:"http_referrer"` // referer信息
HttpTraceId string `json:"http_trace_id"` // trance信息
XAppId string `json:"x_app_id"` // 用户中心的应用ID
XUserData *UserData `json:"x_user_data"` // 用户信息
XDsmData *DSMData `json:"x_dsm_data"` // 风控信息,不接人风控可不传入
XCustomData any `json:"x_custom_data"` // 自定义信息,需要能够转为json字符串
ResponseData any `json:"response_data"` // 返回信息
}
// UserData 用户数据
type UserData struct {
ID string `json:"id"` // 用户ID
Username string `json:"username"` // 用户名称
OrganizeID string `json:"organize_id"` // 组织ID
OrganizeName string `json:"organize_name"` // 组织名称
Phone string `json:"phone"` // 手机号
Email string `json:"email"` // 邮箱
}
type DBCount struct {
DB string `json:"db"` // 数据库标识
UniqueKey string `json:"unique_key"` // 该条记录唯一标识
}
// DSMData 风控需要数据
type DSMData struct {
AppKey string `json:"app_key"` // 项目在风控平台的appid
PageType string `json:"page_type"` // 访问类型
DataCount int32 `json:"data_count"` // 请求数量,list的时为列表数据量
DBData []*DBCount `json:"db_data"` // 数据库监控时,对应数据相关内容
}
Loading…
Cancel
Save