logger.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. package logger
  2. import (
  3. "database/sql/driver"
  4. "fmt"
  5. "github.com/sirupsen/logrus"
  6. "github.com/spf13/viper"
  7. "os"
  8. "reflect"
  9. "regexp"
  10. "runtime"
  11. "strings"
  12. "time"
  13. "unicode"
  14. )
  15. var MaxInt64 = ^int64(0)
  16. type Logger struct {
  17. logrus.Entry
  18. Level logrus.Level
  19. }
  20. func New() *Logger {
  21. timeFormat := "2006/01/02 15:04:05.000 -0700"
  22. if tmFormat, ok := viper.Get("logger.time_format").(string); ok && len(tmFormat) > 0 {
  23. timeFormat = strings.TrimSpace(tmFormat)
  24. }
  25. level := logrus.InfoLevel
  26. if lvStr, ok := viper.Get("logger.level").(string); ok {
  27. lvStr = strings.TrimSpace(strings.ToLower(lvStr))
  28. if lvStr == "warn" {
  29. level = logrus.WarnLevel
  30. } else if lvStr == "debug" {
  31. level = logrus.DebugLevel
  32. } else if lvStr == "error" {
  33. level = logrus.ErrorLevel
  34. } else if lvStr == "fatal" {
  35. level = logrus.FatalLevel
  36. } else if lvStr == "panic" {
  37. level = logrus.PanicLevel
  38. }
  39. }
  40. log := &logrus.Logger{
  41. Out: os.Stderr,
  42. Formatter: &logrus.TextFormatter{TimestampFormat: timeFormat},
  43. Hooks: make(logrus.LevelHooks),
  44. Level: level,
  45. }
  46. //if grayAddr, ok := viper.Get("logger.graylog.addr").(string); ok && len(grayAddr) > 0 {
  47. // grayHook := graylog.NewGraylogHook(grayAddr, nil)
  48. // log.AddHook(grayHook)
  49. //}
  50. entry := logrus.NewEntry(log)
  51. extra := viper.GetStringMap("logger.extra")
  52. if nil != extra && len(extra) > 0 {
  53. entry = entry.WithFields(extra)
  54. }
  55. return &Logger{Entry: *entry, Level: level}
  56. }
  57. func (logger *Logger) Print(args ...interface{}) {
  58. if args == nil || len(args) == 0 {
  59. return
  60. }
  61. if tp, ok := args[0].(string); ok {
  62. tp = strings.ToLower(strings.TrimSpace(tp))
  63. if "sql" == tp && len(args) == 6 {
  64. logger.printSql(args...)
  65. } else {
  66. logger.WithCaller(2).Entry.Print(args...)
  67. }
  68. } else {
  69. logger.WithCaller(2).Entry.Print(args...)
  70. }
  71. }
  72. func (logger *Logger) WithField(key string, value interface{}) *Logger {
  73. return &Logger{Entry: *logger.Entry.WithField(key, value)}
  74. }
  75. func (logger *Logger) WithFields(fields map[string]interface{}) *Logger {
  76. return &Logger{Entry: *logger.Entry.WithFields(fields)}
  77. }
  78. func (logger *Logger) WithError(err error) *Logger {
  79. return &Logger{Entry: *logger.Entry.WithError(err)}
  80. }
  81. func (logger *Logger) WithCaller(skip int) *Logger {
  82. if _, ok := logger.Data["codeline"]; ok {
  83. return logger
  84. }
  85. for i := 0; i < 100; i++ {
  86. if _, file, line, ok := runtime.Caller(i); ok {
  87. if strings.Contains(file, "git.haoqitour.com") &&
  88. !strings.Contains(file, "git.haoqitour.com/haoqi/go-common/utils/logger") {
  89. return logger.
  90. WithField("codeline", fmt.Sprintf("%s:%d", file, line))
  91. //WithField("func", runtime.FuncForPC(pc).Name())
  92. }
  93. }
  94. }
  95. if _, file, line, ok := runtime.Caller(skip); ok {
  96. return logger.
  97. WithField("codeline", fmt.Sprintf("%s:%d", file, line))
  98. //WithField("func", runtime.FuncForPC(pc).Name())
  99. }
  100. return logger
  101. }
  102. func (logger *Logger) Debugf(format string, args ...interface{}) {
  103. logger.WithCaller(2).Entry.Debugf(format, args...)
  104. }
  105. func (logger *Logger) Infof(format string, args ...interface{}) {
  106. logger.WithCaller(2).Entry.Infof(format, args...)
  107. }
  108. func (logger *Logger) Printf(format string, args ...interface{}) {
  109. logger.WithCaller(2).Entry.Printf(format, args...)
  110. }
  111. func (logger *Logger) Warnf(format string, args ...interface{}) {
  112. logger.WithCaller(2).Entry.Warnf(format, args...)
  113. }
  114. func (logger *Logger) Warningf(format string, args ...interface{}) {
  115. logger.WithCaller(2).Entry.Warningf(format, args...)
  116. }
  117. func (logger *Logger) Errorf(format string, args ...interface{}) {
  118. logger.WithCaller(2).Entry.Errorf(format, args...)
  119. }
  120. func (logger *Logger) Fatalf(format string, args ...interface{}) {
  121. logger.WithCaller(2).Entry.Fatalf(format, args...)
  122. }
  123. func (logger *Logger) Panicf(format string, args ...interface{}) {
  124. logger.WithCaller(2).Entry.Panicf(format, args...)
  125. }
  126. func (logger *Logger) Debug(args ...interface{}) {
  127. logger.WithCaller(2).Entry.Debug(args...)
  128. }
  129. func (logger *Logger) Info(args ...interface{}) {
  130. logger.WithCaller(2).Entry.Info(args...)
  131. }
  132. func (logger *Logger) Warn(args ...interface{}) {
  133. logger.WithCaller(2).Entry.Warn(args...)
  134. }
  135. func (logger *Logger) Warning(args ...interface{}) {
  136. logger.WithCaller(2).Entry.Warning(args...)
  137. }
  138. func (logger *Logger) Error(args ...interface{}) {
  139. logger.WithCaller(2).Entry.Error(args...)
  140. }
  141. func (logger *Logger) Fatal(args ...interface{}) {
  142. logger.WithCaller(2).Entry.Fatal(args...)
  143. }
  144. func (logger *Logger) Panic(args ...interface{}) {
  145. logger.WithCaller(2).Entry.Panic(args...)
  146. }
  147. func (logger *Logger) Debugln(args ...interface{}) {
  148. logger.WithCaller(2).Entry.Debugln(args...)
  149. }
  150. func (logger *Logger) Infoln(args ...interface{}) {
  151. logger.WithCaller(2).Entry.Infoln(args...)
  152. }
  153. func (logger *Logger) Println(args ...interface{}) {
  154. logger.WithCaller(2).Entry.Println(args...)
  155. }
  156. func (logger *Logger) Warnln(args ...interface{}) {
  157. logger.WithCaller(2).Entry.Warnln(args...)
  158. }
  159. func (logger *Logger) Warningln(args ...interface{}) {
  160. logger.WithCaller(2).Entry.Warningln(args...)
  161. }
  162. func (logger *Logger) Errorln(args ...interface{}) {
  163. logger.WithCaller(2).Entry.Errorln(args...)
  164. }
  165. func (logger *Logger) Fatalln(args ...interface{}) {
  166. logger.WithCaller(2).Entry.Fatalln(args...)
  167. }
  168. func (logger *Logger) Panicln(args ...interface{}) {
  169. logger.WithCaller(2).Entry.Panicln(args...)
  170. }
  171. var (
  172. sqlRegexp = regexp.MustCompile(`\?`)
  173. numericPlaceHolderRegexp = regexp.MustCompile(`\$\d+`)
  174. )
  175. func (logger *Logger) printSql(args ...interface{}) {
  176. length := len(args)
  177. var (
  178. codeLine, sql string
  179. params []interface{}
  180. latency time.Duration
  181. rows int64
  182. ok bool
  183. )
  184. if length > 1 {
  185. codeLine, _ = args[1].(string)
  186. }
  187. if length > 2 {
  188. latency, _ = args[2].(time.Duration)
  189. }
  190. if length > 3 {
  191. sql, ok = args[3].(string)
  192. if ok {
  193. sql = strings.TrimSpace(strings.Replace(strings.Replace(strings.Replace(sql, "\r\n", " ", -1), "\n", " ", -1), "\t", " ", -1))
  194. }
  195. }
  196. if length > 4 {
  197. params, _ = args[4].([]interface{})
  198. }
  199. if length > 5 {
  200. rows, _ = args[5].(int64)
  201. }
  202. lg := logger.
  203. WithField("tag", "SQL").
  204. WithField("sql", logger.getSql(sql, params))
  205. if len(codeLine) > 0 {
  206. lg = lg.WithField("codeline", strings.TrimSpace(codeLine))
  207. } else {
  208. lg = lg.WithCaller(9)
  209. }
  210. if latency > 0 {
  211. lg = lg.WithField("latency", fmt.Sprintf("%v", latency))
  212. }
  213. if rows != MaxInt64 {
  214. lg = lg.WithField("rows", fmt.Sprintf("%d rows affected or returned", rows))
  215. }
  216. lg.Info(fmt.Sprintf("%s %v", sql, params))
  217. }
  218. func (logger *Logger) getSql(originSql string, params []interface{}) string {
  219. var formattedValues []string
  220. for _, value := range params {
  221. indirectValue := reflect.Indirect(reflect.ValueOf(value))
  222. if indirectValue.IsValid() {
  223. value = indirectValue.Interface()
  224. if t, ok := value.(time.Time); ok {
  225. formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05")))
  226. } else if b, ok := value.([]byte); ok {
  227. if str := string(b); logger.isPrintable(str) {
  228. formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str))
  229. } else {
  230. formattedValues = append(formattedValues, "'<binary>'")
  231. }
  232. } else if r, ok := value.(driver.Valuer); ok {
  233. if value, err := r.Value(); err == nil && value != nil {
  234. formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
  235. } else {
  236. formattedValues = append(formattedValues, "NULL")
  237. }
  238. } else {
  239. formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value))
  240. }
  241. } else {
  242. formattedValues = append(formattedValues, "NULL")
  243. }
  244. }
  245. if nil == formattedValues {
  246. return ""
  247. }
  248. var sql string
  249. // differentiate between $n placeholders or else treat like ?
  250. if numericPlaceHolderRegexp.MatchString(originSql) {
  251. for index, value := range formattedValues {
  252. placeholder := fmt.Sprintf(`\$%d([^\d]|$)`, index+1)
  253. sql = regexp.MustCompile(placeholder).ReplaceAllString(originSql, value+"$1")
  254. }
  255. } else {
  256. formattedValuesLength := len(formattedValues)
  257. for index, value := range sqlRegexp.Split(originSql, -1) {
  258. sql += value
  259. if index < formattedValuesLength {
  260. sql += formattedValues[index]
  261. }
  262. }
  263. }
  264. return sql
  265. }
  266. func (logger *Logger) isPrintable(s string) bool {
  267. for _, r := range s {
  268. if !unicode.IsPrint(r) {
  269. return false
  270. }
  271. }
  272. return true
  273. }