优化开放接口日志分类
This commit is contained in:
@@ -23,6 +23,7 @@ func NewOpenHandler(fulfillmentSvc *service.FulfillmentService) *OpenHandler {
|
|||||||
// QueryOrder GET /api/open/v1/orders/:order_no
|
// QueryOrder GET /api/open/v1/orders/:order_no
|
||||||
// 上游输入店铺订单号,查询商品与是否可发货
|
// 上游输入店铺订单号,查询商品与是否可发货
|
||||||
func (h *OpenHandler) QueryOrder(c *gin.Context) {
|
func (h *OpenHandler) QueryOrder(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionQuery)
|
||||||
orderNo := c.Param("order_no")
|
orderNo := c.Param("order_no")
|
||||||
if orderNo == "" {
|
if orderNo == "" {
|
||||||
orderNo = c.Query("order_no")
|
orderNo = c.Query("order_no")
|
||||||
@@ -67,6 +68,7 @@ type shipNotifyReq struct {
|
|||||||
// ShipNotify POST /api/open/v1/orders/ship-notify
|
// ShipNotify POST /api/open/v1/orders/ship-notify
|
||||||
// 上游发货后推送结果,同步订单状态
|
// 上游发货后推送结果,同步订单状态
|
||||||
func (h *OpenHandler) ShipNotify(c *gin.Context) {
|
func (h *OpenHandler) ShipNotify(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionPush)
|
||||||
var req shipNotifyReq
|
var req shipNotifyReq
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
openlog.Warn(c, "ship_notify bind_fail err=%v", err)
|
openlog.Warn(c, "ship_notify bind_fail err=%v", err)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ func NewOpenV1Handler(merchantSvc *service.MerchantService, fulfillmentSvc *serv
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *OpenV1Handler) ListProducts(c *gin.Context) {
|
func (h *OpenV1Handler) ListProducts(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionList)
|
||||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "20"))
|
size, _ := strconv.Atoi(c.DefaultQuery("size", "20"))
|
||||||
openlog.Info(c, "list_products start page=%d size=%d", page, size)
|
openlog.Info(c, "list_products start page=%d size=%d", page, size)
|
||||||
@@ -47,6 +48,7 @@ type openCreateOrderReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *OpenV1Handler) CreateOrder(c *gin.Context) {
|
func (h *OpenV1Handler) CreateOrder(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionCreate)
|
||||||
var req openCreateOrderReq
|
var req openCreateOrderReq
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
openlog.Warn(c, "create_order bind_fail err=%v", err)
|
openlog.Warn(c, "create_order bind_fail err=%v", err)
|
||||||
@@ -103,6 +105,7 @@ func (h *OpenV1Handler) CreateOrder(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *OpenV1Handler) QueryOrder(c *gin.Context) {
|
func (h *OpenV1Handler) QueryOrder(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionQuery)
|
||||||
orderNo := c.Param("order_no")
|
orderNo := c.Param("order_no")
|
||||||
openlog.Info(c, "query_order start order_no=%s", orderNo)
|
openlog.Info(c, "query_order start order_no=%s", orderNo)
|
||||||
order, err := h.fulfillmentSvc.GetOrder(middleware.GetMerchantID(c), orderNo)
|
order, err := h.fulfillmentSvc.GetOrder(middleware.GetMerchantID(c), orderNo)
|
||||||
@@ -125,6 +128,7 @@ type openCancelOrderReq struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *OpenV1Handler) CancelOrder(c *gin.Context) {
|
func (h *OpenV1Handler) CancelOrder(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionCancel)
|
||||||
var req openCancelOrderReq
|
var req openCancelOrderReq
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
openlog.Warn(c, "cancel_order bind_fail err=%v", err)
|
openlog.Warn(c, "cancel_order bind_fail err=%v", err)
|
||||||
@@ -145,6 +149,7 @@ func (h *OpenV1Handler) CancelOrder(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *OpenV1Handler) GetWallet(c *gin.Context) {
|
func (h *OpenV1Handler) GetWallet(c *gin.Context) {
|
||||||
|
openlog.SetAction(c, openlog.ActionWallet)
|
||||||
openlog.Info(c, "get_wallet start")
|
openlog.Info(c, "get_wallet start")
|
||||||
wallet, err := h.fulfillmentSvc.GetWallet(middleware.GetMerchantID(c))
|
wallet, err := h.fulfillmentSvc.GetWallet(middleware.GetMerchantID(c))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ func OpenAuth(cfg OpenAuthConfig) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
reqID := openlog.EnsureReqID(c)
|
reqID := openlog.EnsureReqID(c)
|
||||||
|
side, action := openlog.ScopeFromPath(openlog.SideClient, c.Request.Method, c.Request.URL.Path)
|
||||||
|
openlog.SetScope(c, side, action)
|
||||||
c.Set(openlog.CtxDebug, cfg.Debug)
|
c.Set(openlog.CtxDebug, cfg.Debug)
|
||||||
c.Set(openlog.CtxStart, time.Now())
|
c.Set(openlog.CtxStart, time.Now())
|
||||||
c.Header("X-Request-Id", reqID)
|
c.Header("X-Request-Id", reqID)
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ func SourceOpenAuth(cfg SourceOpenAuthConfig) gin.HandlerFunc {
|
|||||||
store := newSourceNonceStore()
|
store := newSourceNonceStore()
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
reqID := openlog.EnsureReqID(c)
|
reqID := openlog.EnsureReqID(c)
|
||||||
|
side, action := openlog.ScopeFromPath(openlog.SideSource, c.Request.Method, c.Request.URL.Path)
|
||||||
|
openlog.SetScope(c, side, action)
|
||||||
c.Set(openlog.CtxDebug, cfg.Debug)
|
c.Set(openlog.CtxDebug, cfg.Debug)
|
||||||
c.Set(openlog.CtxStart, time.Now())
|
c.Set(openlog.CtxStart, time.Now())
|
||||||
c.Header("X-Request-Id", reqID)
|
c.Header("X-Request-Id", reqID)
|
||||||
|
|||||||
@@ -16,6 +16,27 @@ const (
|
|||||||
CtxBody = "open_body"
|
CtxBody = "open_body"
|
||||||
CtxStart = "open_start"
|
CtxStart = "open_start"
|
||||||
CtxAPIKey = "open_api_key"
|
CtxAPIKey = "open_api_key"
|
||||||
|
CtxSide = "open_side"
|
||||||
|
CtxAPIType = "open_api_type"
|
||||||
|
CtxAction = "open_action"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SideClient = "client"
|
||||||
|
SideSource = "source"
|
||||||
|
|
||||||
|
APITypeClientV1 = "client_v1"
|
||||||
|
APITypeSourceOpenV1 = "source_open_v1"
|
||||||
|
APITypeUnknown = "unknown"
|
||||||
|
|
||||||
|
ActionAuth = "auth"
|
||||||
|
ActionList = "list"
|
||||||
|
ActionCreate = "create"
|
||||||
|
ActionQuery = "query"
|
||||||
|
ActionCancel = "cancel"
|
||||||
|
ActionWallet = "wallet"
|
||||||
|
ActionPush = "push"
|
||||||
|
ActionUnknown = "unknown"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enabled 是否开启开放接口详细日志
|
// Enabled 是否开启开放接口详细日志
|
||||||
@@ -50,6 +71,38 @@ func EnsureReqID(c *gin.Context) string {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetScope(c *gin.Context, side, action string) {
|
||||||
|
c.Set(CtxSide, side)
|
||||||
|
c.Set(CtxAPIType, APITypeFromSide(side))
|
||||||
|
c.Set(CtxAction, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetAction(c *gin.Context, action string) {
|
||||||
|
c.Set(CtxAction, action)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeFromPath(side, method, path string) (string, string) {
|
||||||
|
action := ActionUnknown
|
||||||
|
switch side {
|
||||||
|
case SideClient:
|
||||||
|
action = clientAction(method, path)
|
||||||
|
case SideSource:
|
||||||
|
action = sourceAction(method, path)
|
||||||
|
}
|
||||||
|
return side, action
|
||||||
|
}
|
||||||
|
|
||||||
|
func APITypeFromSide(side string) string {
|
||||||
|
switch side {
|
||||||
|
case SideClient:
|
||||||
|
return APITypeClientV1
|
||||||
|
case SideSource:
|
||||||
|
return APITypeSourceOpenV1
|
||||||
|
default:
|
||||||
|
return APITypeUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func IsDebug(c *gin.Context) bool {
|
func IsDebug(c *gin.Context) bool {
|
||||||
if !Enabled {
|
if !Enabled {
|
||||||
return false
|
return false
|
||||||
@@ -92,12 +145,37 @@ func Truncate(s string, max int) string {
|
|||||||
return s[:max] + fmt.Sprintf("...(%d bytes)", len(s))
|
return s[:max] + fmt.Sprintf("...(%d bytes)", len(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Prefix(c *gin.Context) string {
|
||||||
|
side, _ := c.Get(CtxSide)
|
||||||
|
apiType, _ := c.Get(CtxAPIType)
|
||||||
|
action, _ := c.Get(CtxAction)
|
||||||
|
sideText, _ := side.(string)
|
||||||
|
apiTypeText, _ := apiType.(string)
|
||||||
|
actionText, _ := action.(string)
|
||||||
|
tag := "open"
|
||||||
|
if apiTypeText != "" && apiTypeText != APITypeUnknown {
|
||||||
|
tag += "." + apiTypeText
|
||||||
|
} else if sideText != "" {
|
||||||
|
tag += "." + sideText
|
||||||
|
}
|
||||||
|
if actionText != "" {
|
||||||
|
tag += "." + actionText
|
||||||
|
}
|
||||||
|
fields := ""
|
||||||
|
if apiTypeText != "" {
|
||||||
|
fields += fmt.Sprintf(" api_type=%s", apiTypeText)
|
||||||
|
}
|
||||||
|
if actionText != "" {
|
||||||
|
fields += fmt.Sprintf(" action=%s", actionText)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("[%s] req_id=%s%s ", tag, GetReqID(c), fields)
|
||||||
|
}
|
||||||
|
|
||||||
func Info(c *gin.Context, format string, args ...interface{}) {
|
func Info(c *gin.Context, format string, args ...interface{}) {
|
||||||
if !IsDebug(c) {
|
if !IsDebug(c) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
prefix := fmt.Sprintf("[open] req_id=%s ", GetReqID(c))
|
log.Printf(Prefix(c)+format, args...)
|
||||||
log.Printf(prefix+format, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warn(c *gin.Context, format string, args ...interface{}) {
|
func Warn(c *gin.Context, format string, args ...interface{}) {
|
||||||
@@ -105,8 +183,7 @@ func Warn(c *gin.Context, format string, args ...interface{}) {
|
|||||||
if !Enabled {
|
if !Enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
prefix := fmt.Sprintf("[open] req_id=%s ", GetReqID(c))
|
log.Printf(Prefix(c)+format, args...)
|
||||||
log.Printf(prefix+format, args...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Elapsed(c *gin.Context) time.Duration {
|
func Elapsed(c *gin.Context) time.Duration {
|
||||||
@@ -117,3 +194,33 @@ func Elapsed(c *gin.Context) time.Duration {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func clientAction(method, path string) string {
|
||||||
|
method = strings.ToUpper(method)
|
||||||
|
switch {
|
||||||
|
case method == "GET" && path == "/api/client/v1/products":
|
||||||
|
return ActionList
|
||||||
|
case method == "POST" && path == "/api/client/v1/orders":
|
||||||
|
return ActionCreate
|
||||||
|
case method == "GET" && strings.HasPrefix(path, "/api/client/v1/orders/"):
|
||||||
|
return ActionQuery
|
||||||
|
case method == "POST" && strings.HasPrefix(path, "/api/client/v1/orders/") && strings.HasSuffix(path, "/cancel"):
|
||||||
|
return ActionCancel
|
||||||
|
case method == "GET" && path == "/api/client/v1/wallet":
|
||||||
|
return ActionWallet
|
||||||
|
default:
|
||||||
|
return ActionUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sourceAction(method, path string) string {
|
||||||
|
method = strings.ToUpper(method)
|
||||||
|
switch {
|
||||||
|
case method == "GET" && strings.HasPrefix(path, "/api/open/v1/orders/"):
|
||||||
|
return ActionQuery
|
||||||
|
case method == "POST" && path == "/api/open/v1/orders/ship-notify":
|
||||||
|
return ActionPush
|
||||||
|
default:
|
||||||
|
return ActionUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package openlog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPrefixIncludesSideAndAction(t *testing.T) {
|
||||||
|
gin.SetMode(gin.TestMode)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := gin.CreateTestContext(w)
|
||||||
|
c.Set(CtxReqID, "req123")
|
||||||
|
SetScope(c, SideSource, ActionPush)
|
||||||
|
|
||||||
|
got := Prefix(c)
|
||||||
|
want := "[open.source_open_v1.push] req_id=req123 api_type=source_open_v1 action=push "
|
||||||
|
if got != want {
|
||||||
|
t.Fatalf("prefix mismatch: got %q want %q", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestScopeFromPath(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
side string
|
||||||
|
method string
|
||||||
|
path string
|
||||||
|
wantSide string
|
||||||
|
wantAction string
|
||||||
|
wantType string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "客户侧查询订单",
|
||||||
|
side: SideClient,
|
||||||
|
method: "GET",
|
||||||
|
path: "/api/client/v1/orders/FO123",
|
||||||
|
wantSide: SideClient,
|
||||||
|
wantAction: ActionQuery,
|
||||||
|
wantType: APITypeClientV1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "客户侧创建订单",
|
||||||
|
side: SideClient,
|
||||||
|
method: "POST",
|
||||||
|
path: "/api/client/v1/orders",
|
||||||
|
wantSide: SideClient,
|
||||||
|
wantAction: ActionCreate,
|
||||||
|
wantType: APITypeClientV1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "源头侧发货推送",
|
||||||
|
side: SideSource,
|
||||||
|
method: "POST",
|
||||||
|
path: "/api/open/v1/orders/ship-notify",
|
||||||
|
wantSide: SideSource,
|
||||||
|
wantAction: ActionPush,
|
||||||
|
wantType: APITypeSourceOpenV1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "源头侧查询订单",
|
||||||
|
side: SideSource,
|
||||||
|
method: "GET",
|
||||||
|
path: "/api/open/v1/orders/FO123",
|
||||||
|
wantSide: SideSource,
|
||||||
|
wantAction: ActionQuery,
|
||||||
|
wantType: APITypeSourceOpenV1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
gotSide, gotAction := ScopeFromPath(tc.side, tc.method, tc.path)
|
||||||
|
if gotSide != tc.wantSide || gotAction != tc.wantAction {
|
||||||
|
t.Fatalf("scope mismatch: got %s/%s want %s/%s", gotSide, gotAction, tc.wantSide, tc.wantAction)
|
||||||
|
}
|
||||||
|
if gotType := APITypeFromSide(gotSide); gotType != tc.wantType {
|
||||||
|
t.Fatalf("api type mismatch: got %s want %s", gotType, tc.wantType)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user