interceptor.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package interceptor
  2. import (
  3. "fmt"
  4. "net"
  5. "strconv"
  6. "strings"
  7. "time"
  8. "go-common/library/ecode"
  9. "go-common/library/log"
  10. "go-common/library/net/rpc/context"
  11. "go-common/library/stat"
  12. "golang.org/x/time/rate"
  13. )
  14. var stats = stat.RPCServer
  15. const (
  16. _innerService = "inner"
  17. )
  18. // Interceptor is rpc interceptor
  19. type Interceptor struct {
  20. // for limit rate
  21. rateLimits map[string]*rate.Limiter
  22. // for auth
  23. token string
  24. }
  25. // NewInterceptor new a interceptor
  26. func NewInterceptor(token string) *Interceptor {
  27. in := &Interceptor{token: token}
  28. in.rateLimits = make(map[string]*rate.Limiter)
  29. return in
  30. }
  31. // Rate check the call is limit or not
  32. func (i *Interceptor) Rate(c context.Context) error {
  33. limit, ok := i.rateLimits[c.ServiceMethod()]
  34. if ok && !limit.Allow() {
  35. return ecode.Degrade
  36. }
  37. return nil
  38. }
  39. // Stat add stat info to ops
  40. func (i *Interceptor) Stat(c context.Context, args interface{}, err error) {
  41. const noUser = "no_user"
  42. var (
  43. user = c.User()
  44. method = c.ServiceMethod()
  45. tmsub = time.Since(c.Now())
  46. )
  47. if user == "" {
  48. user = noUser
  49. }
  50. stats.Timing(user, int64(tmsub/time.Millisecond), method)
  51. stats.Incr(user, method, strconv.Itoa((ecode.Cause(err).Code())))
  52. if err != nil {
  53. log.Errorv(c,
  54. log.KV("args", fmt.Sprintf("%v", args)),
  55. log.KV("method", method),
  56. log.KV("duration", tmsub),
  57. log.KV("error", fmt.Sprintf("%+v", err)),
  58. )
  59. } else {
  60. if !strings.HasPrefix(method, _innerService) || bool(log.V(2)) {
  61. log.Infov(c,
  62. log.KV("args", fmt.Sprintf("%v", args)),
  63. log.KV("method", method),
  64. log.KV("duration", tmsub),
  65. log.KV("error", fmt.Sprintf("%+v", err)),
  66. )
  67. }
  68. }
  69. }
  70. // Auth check token has auth
  71. func (i *Interceptor) Auth(c context.Context, addr net.Addr, token string) error {
  72. if i.token != token {
  73. return ecode.RPCNoAuth
  74. }
  75. return nil
  76. }