monitor.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package monitor
  2. import (
  3. "leafstalk/log"
  4. "leafstalk/otherutils"
  5. "reflect"
  6. "runtime"
  7. "time"
  8. )
  9. type Alarm struct {
  10. Type int64 `json:"type"`
  11. Name string `json:"name"`
  12. Args string `json:"args"`
  13. CostTime int64 `json:"costTime"`
  14. CreatedAt int64 `json:"createdAt"`
  15. }
  16. var (
  17. reportFunc func(alarm *Alarm)
  18. )
  19. func SetReportFunc(f func(alarm *Alarm)) {
  20. reportFunc = f
  21. }
  22. func reportMonitorAlarm(alarm *Alarm) {
  23. if reportFunc != nil {
  24. reportFunc(alarm)
  25. } else {
  26. log.Warnf("monitor.reportMonitorAlarm:%v", otherutils.DumpToJSON(alarm))
  27. }
  28. }
  29. // TimeoutWarn 超时报警
  30. // 这个函数的几个参数说明如下:
  31. // funName、args 表示超时发生位置的两个字符串参数
  32. // start 程序开始执行的时间
  33. // timeLimit 函数执行超时阀值,单位是毫秒
  34. func TimeoutWarn(funName string, args any, typ int64, start time.Time, tl ...int64) {
  35. timeLimit := DefaultAlarmThreshold
  36. if len(tl) > 0 {
  37. timeLimit = tl[0]
  38. }
  39. ct := time.Since(start).Milliseconds()
  40. if ct > timeLimit {
  41. // 上报报警数据
  42. alarm := new(Alarm)
  43. alarm.Type = typ
  44. alarm.Name = funName
  45. alarm.Args = otherutils.DumpToJSON(args)
  46. alarm.CostTime = ct
  47. alarm.CreatedAt = start.Unix()
  48. reportMonitorAlarm(alarm)
  49. }
  50. }
  51. func GoExecTimeoutWarn(fn any, args any, start time.Time, tl ...int64) {
  52. funName := functionName(fn)
  53. if funName == "" {
  54. return
  55. }
  56. TimeoutWarn(funName, args, AlarmTypeGoExec, start, tl...)
  57. }
  58. func GoLoadTimeoutWarn(funName string, playerId int64, start time.Time, tl ...int64) {
  59. TimeoutWarn(funName, playerId, AlarmTypeGoLoad, start, tl...)
  60. }
  61. func GoLoadTimeoutWarn2(funName string, playerId string, start time.Time, tl ...int64) {
  62. TimeoutWarn(funName, playerId, AlarmTypeGoLoad, start, tl...)
  63. }
  64. func MySqlExecTimeoutWarn(funName string, args any, start time.Time, tl ...int64) {
  65. TimeoutWarn(funName, args, AlarmTypeMySqlExec, start, tl...)
  66. }
  67. func RedisDoTimeoutWarn(funName string, args any, start time.Time, tl ...int64) {
  68. TimeoutWarn(funName, args, AlarmTypeRedisDo, start, tl...)
  69. }
  70. func TimeoutWarnCall(f func(), funName string, args any, typ int64, start time.Time, tl ...int64) {
  71. defer TimeoutWarn(funName, args, typ, start, tl...)
  72. f()
  73. }
  74. func functionName(fn interface{}) string {
  75. fullName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
  76. // 在完整名称内查找函数名
  77. lastDotIndex := 0
  78. for i := len(fullName) - 1; i >= 0; i-- {
  79. if fullName[i] == '.' {
  80. lastDotIndex = i
  81. break
  82. }
  83. }
  84. funcName := fullName[lastDotIndex+1:]
  85. return funcName
  86. }