Skip to content

Commit

Permalink
支持SDK请求监控
Browse files Browse the repository at this point in the history
  • Loading branch information
NICEXAI committed Aug 4, 2021
1 parent b0ea053 commit 477de7d
Show file tree
Hide file tree
Showing 14 changed files with 185 additions and 21 deletions.
25 changes: 20 additions & 5 deletions account.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ type AccountAddSchema struct {

// AccountAdd 添加客服账号
func (r *Client) AccountAdd(options AccountAddOptions) (info AccountAddSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(accountAddAddr, r.accessToken), options)
target := fmt.Sprintf(accountAddAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -51,7 +54,10 @@ type AccountDelOptions struct {

// AccountDel 删除客服账号
func (r *Client) AccountDel(options AccountDelOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(accountDelAddr, r.accessToken), options)
target := fmt.Sprintf(accountDelAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -71,7 +77,10 @@ type AccountUpdateOptions struct {

// AccountUpdate 修复客服账号
func (r *Client) AccountUpdate(options AccountUpdateOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(accountUpdateAddr, r.accessToken), options)
target := fmt.Sprintf(accountUpdateAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -97,7 +106,10 @@ type AccountListSchema struct {

// AccountList 获取客服账号列表
func (r *Client) AccountList() (info AccountListSchema, err error) {
data, err := util.HttpGet(fmt.Sprintf(accountListAddr, r.accessToken))
target := fmt.Sprintf(accountListAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpGet(target)
if err != nil {
return info, err
}
Expand All @@ -122,7 +134,10 @@ type AddContactWaySchema struct {

// AddContactWay 获取客服账号链接
func (r *Client) AddContactWay(options AddContactWayOptions) (info AddContactWaySchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(addContactWayAddr, r.accessToken), options)
target := fmt.Sprintf(addContactWayAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
1 change: 1 addition & 0 deletions cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import "time"
type Cache interface {
Set(k, v string, expires time.Duration) error
Get(k string) (string, error)
Scan(cursor uint64, match string, count int64) (keys []string, newCursor uint64, err error)
}
4 changes: 4 additions & 0 deletions cache/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,8 @@ func (r *Redis) Get(k string) (string, error) {
return "", err
}
return con, nil
}

func (r *Redis) Scan(cursor uint64, match string, count int64) (keys []string, newCursor uint64, err error) {
return r.Point.Scan(context.TODO(), cursor, match, count).Result()
}
12 changes: 11 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ type Options struct {
Cache cache.Cache // 数据缓存
ExpireTime time.Duration // 令牌过期时间
IsCloseCache bool // 是否关闭自动缓存AccessToken, 默认缓存
MonitorOpen bool // 是否开启监控
MonitorLogExpireTime time.Duration // 监控日志过期时间,默认三天
}

// Client 微信客服实例
Expand All @@ -35,6 +37,8 @@ type Client struct {
mutex sync.Mutex
accessToken string // 用户访问凭证
isCloseCache bool // 是否自动缓存AccessToken, 默认缓存
monitorOpen bool // 是否开启监控
monitorLogExpireTime time.Duration // 监控日志过期时间,默认三天
}

// New 初始化微信客服实例
Expand All @@ -44,7 +48,11 @@ func New(options Options) (client *Client, err error) {
}

if options.ExpireTime == 0 {
options.ExpireTime = 6000
options.ExpireTime = 6000 * time.Second
}

if options.MonitorOpen && options.MonitorLogExpireTime == 0 {
options.MonitorLogExpireTime = 3 * 24 * 3600
}

client = &Client{
Expand All @@ -57,6 +65,8 @@ func New(options Options) (client *Client, err error) {
eventQueue: sync.Map{},
mutex: sync.Mutex{},
isCloseCache: options.IsCloseCache,
monitorOpen: options.MonitorOpen,
monitorLogExpireTime: options.MonitorLogExpireTime,
}

if err = client.initAccessToken(); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion customer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ type CustomerBatchGetSchema struct {

// CustomerBatchGet 客户基本信息获取
func (r *Client) CustomerBatchGet(options CustomerBatchGetOptions) (info CustomerBatchGetSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(customerBatchGetAddr, r.accessToken), options)
target := fmt.Sprintf(customerBatchGetAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
10 changes: 8 additions & 2 deletions media.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ func (r *Client) MediaUpload(options MediaUploadOptions) (info MediaUploadSchema
FileSize: options.FileSize,
File: options.File,
}
data, err := util.HttpPostFile(fmt.Sprintf(mediaUploadAddr, r.accessToken, options.Type), fileOptions)
target := fmt.Sprintf(mediaUploadAddr, r.accessToken, options.Type)
r.recordUpdate(target)

data, err := util.HttpPostFile(target, fileOptions)
if err != nil {
return info, err
}
Expand All @@ -67,7 +70,10 @@ func (r *Client) MediaUpload(options MediaUploadOptions) (info MediaUploadSchema
//视频(video) :10MB,支持MP4格式
//普通文件(file):20MB
func (r *Client) MediaOriginUpload(fileName, fileType string, size int, body []byte) (info MediaUploadSchema, err error) {
data, err := util.HttpPostOriginFile(fmt.Sprintf(mediaUploadAddr, r.accessToken, fileType), fileName, size, body)
target := fmt.Sprintf(mediaUploadAddr, r.accessToken, fileType)
r.recordUpdate(target)

data, err := util.HttpPostOriginFile(target, fileName, size, body)
if err != nil {
return info, err
}
Expand Down
79 changes: 79 additions & 0 deletions monitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package WeChatCustomerServiceSDK

import (
"github.com/NICEXAI/WeChatCustomerServiceSDK/util"
"strconv"
"strings"
"time"
)

// MonitorSchema SDK监控数据
type MonitorSchema map[string]map[string]int

// Monitor 获取当前服务SDK调用统计数据
func (r *Client) Monitor() MonitorSchema {
keyList := make([]string, 0)
cursor := uint64(0)
hasMore := true

for hasMore {
keys, newCursor, err := r.cache.Scan(cursor, "wechat:log:" + r.corpID + "*", 1000)
if err != nil {
break
}
if newCursor == 0 || len(keys) == 0 {
hasMore = false
}
cursor = newCursor
keyList = append(keyList, keys...)
}

monitorInfo := MonitorSchema{}
for _, key := range keyList {
options := strings.Split(key, ":")
if len(options) != 5 {
continue
}
con, err := r.cache.Get(key)
if err != nil {
continue
}
timeDic := monitorInfo[options[3]]
if timeDic == nil {
monitorInfo[options[3]] = map[string]int{}
}
count, err := strconv.Atoi(con)
if err != nil {
continue
}
monitorInfo[options[3]][options[4]] = count
}
return monitorInfo
}

//记录SDK调用信息
func (r *Client) recordUpdate(path string) {
if !r.monitorOpen {
return
}
path = util.ParseRoute(path)
if path == "" {
return
}
recordKey := "wechat:log:" + r.corpID + ":" + time.Now().Format("2006010215") + ":" + path[1:]
con, err := r.cache.Get(recordKey)
if err != nil {
return
}
if con == "" {
if err = r.cache.Set(recordKey, strconv.Itoa(1), r.monitorLogExpireTime); err != nil {
return
}
return
}
count, err := strconv.Atoi(con)
if err != nil {
return
}
_ = r.cache.Set(recordKey, strconv.Itoa(count + 1), r.monitorLogExpireTime)
}
5 changes: 4 additions & 1 deletion sendmsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ type SendMsgSchema struct {

// SendMsg 获取消息
func (r *Client) SendMsg(options interface{}) (info SendMsgSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(sendMsgAddr, r.accessToken), options)
target := fmt.Sprintf(sendMsgAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
15 changes: 12 additions & 3 deletions servicer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ type ReceptionistSchema struct {

// ReceptionistAdd 添加接待人员
func (r *Client) ReceptionistAdd(options ReceptionistOptions) (info ReceptionistSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(receptionistAddAddr, r.accessToken), options)
target := fmt.Sprintf(receptionistAddAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -45,7 +48,10 @@ func (r *Client) ReceptionistAdd(options ReceptionistOptions) (info Receptionist

// ReceptionistDel 删除接待人员
func (r *Client) ReceptionistDel(options ReceptionistOptions) (info ReceptionistSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(receptionistDelAddr, r.accessToken), options)
target := fmt.Sprintf(receptionistDelAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -67,7 +73,10 @@ type ReceptionistListSchema struct {

// ReceptionistList 获取接待人员列表
func (r *Client) ReceptionistList(kfID string) (info ReceptionistListSchema, err error) {
data, err := util.HttpGet(fmt.Sprintf(receptionistListAddr, r.accessToken, kfID))
target := fmt.Sprintf(receptionistListAddr, r.accessToken, kfID)
r.recordUpdate(target)

data, err := util.HttpGet(target)
if err != nil {
return info, err
}
Expand Down
10 changes: 8 additions & 2 deletions servicestate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ type ServiceStateGetSchema struct {
//3 由人工接待 人工接待中。可选择结束会话
//4 已结束 会话已经结束。不允许变更会话状态,等待用户重新发起咨询
func (r *Client) ServiceStateGet(options ServiceStateGetOptions) (info ServiceStateGetSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(serviceStateGetAddr, r.accessToken), options)
target := fmt.Sprintf(serviceStateGetAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -54,7 +57,10 @@ type ServiceStateTransOptions struct {

// ServiceStateTrans 变更会话状态
func (r *Client) ServiceStateTrans(options ServiceStateTransOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(serviceStateTransAddr, r.accessToken), options)
target := fmt.Sprintf(serviceStateTransAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
5 changes: 4 additions & 1 deletion syncmsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ type SyncMsgSchema struct {

// SyncMsg 获取消息
func (r *Client) SyncMsg(options SyncMsgOptions) (info SyncMsgSchema, err error) {
data, err := util.HttpPost(fmt.Sprintf(syncMsgAddr, r.accessToken), options)
target := fmt.Sprintf(syncMsgAddr, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
5 changes: 4 additions & 1 deletion token.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ type AccessTokenSchema struct {

// GetAccessToken 获取调用凭证access_token
func (r *Client) GetAccessToken() (info AccessTokenSchema, err error) {
data, err := util.HttpGet(fmt.Sprintf(getTokenAddr, r.corpID, r.secret))
target := fmt.Sprintf(getTokenAddr, r.corpID, r.secret)
r.recordUpdate(target)

data, err := util.HttpGet(target)
if err != nil {
return info, err
}
Expand Down
20 changes: 16 additions & 4 deletions upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ type UpgradeServiceOptions struct {

// UpgradeService 为客户升级为专员或客户群服务
func (r *Client) UpgradeService(options UpgradeServiceOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(upgradeService, r.accessToken), options)
target := fmt.Sprintf(upgradeService, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -81,7 +84,10 @@ type UpgradeMemberServiceOptions struct {

// UpgradeMemberService 为客户升级为专员服务
func (r *Client) UpgradeMemberService(options UpgradeMemberServiceOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(upgradeService, r.accessToken), options)
target := fmt.Sprintf(upgradeService, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -105,7 +111,10 @@ type UpgradeServiceGroupChatOptions struct {

// UpgradeGroupChatService 为客户升级为客户群服务
func (r *Client) UpgradeGroupChatService(options UpgradeServiceGroupChatOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(upgradeService, r.accessToken), options)
target := fmt.Sprintf(upgradeService, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand All @@ -124,7 +133,10 @@ type UpgradeServiceCancelOptions struct {

// UpgradeServiceCancel 为客户取消推荐
func (r *Client) UpgradeServiceCancel(options UpgradeServiceCancelOptions) (info BaseModel, err error) {
data, err := util.HttpPost(fmt.Sprintf(upgradeServiceCancel, r.accessToken), options)
target := fmt.Sprintf(upgradeServiceCancel, r.accessToken)
r.recordUpdate(target)

data, err := util.HttpPost(target, options)
if err != nil {
return info, err
}
Expand Down
10 changes: 10 additions & 0 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
"strconv"
)

Expand Down Expand Up @@ -112,3 +113,12 @@ func HttpPostOriginFile(path, fileName string, size int, body []byte) ([]byte, e
}
return ioutil.ReadAll(resp.Body)
}

// ParseRoute 解析路由
func ParseRoute(path string) string {
route, err := url.ParseRequestURI(path)
if err != nil {
return ""
}
return route.Path
}

0 comments on commit 477de7d

Please sign in to comment.