logger.go 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package Logger
  2. import (
  3. "fmt"
  4. "go.uber.org/zap"
  5. "go.uber.org/zap/zapcore"
  6. "gopkg.in/natefinch/lumberjack.v2"
  7. "log"
  8. "os"
  9. "runtime"
  10. "strconv"
  11. "sync"
  12. "time"
  13. )
  14. var Logger *zap.Logger
  15. func InitLogger(logpath string, loglevel string) {
  16. // 日志分割
  17. hook := lumberjack.Logger{
  18. Filename: logpath, // 日志文件路径,默认 os.TempDir()
  19. MaxSize: 200, // 每个日志文件保存10M,默认 100M
  20. MaxBackups: 20, // 保留30个备份,默认不限
  21. MaxAge: 15, // 保留7天,默认不限
  22. Compress: false, // 是否压缩,默认不压缩
  23. }
  24. write := zapcore.AddSync(&hook)
  25. // 设置日志级别
  26. // debug 可以打印出 info debug warn
  27. // info 级别可以打印 warn info
  28. // warn 只能打印 warn
  29. // debug->info->warn->error
  30. var level zapcore.Level
  31. switch loglevel {
  32. case "debug":
  33. level = zap.DebugLevel
  34. case "info":
  35. level = zap.InfoLevel
  36. case "error":
  37. level = zap.ErrorLevel
  38. default:
  39. level = zap.InfoLevel
  40. }
  41. encoderConfig := zapcore.EncoderConfig{
  42. TimeKey: "time",
  43. LevelKey: "level",
  44. NameKey: "logger",
  45. CallerKey: "caller",
  46. MessageKey: "msg",
  47. StacktraceKey: "stacktrace",
  48. LineEnding: zapcore.DefaultLineEnding,
  49. EncodeLevel: zapcore.LowercaseLevelEncoder, // 小写编码器
  50. EncodeTime: formatEncodeTime,
  51. EncodeDuration: zapcore.SecondsDurationEncoder, //
  52. EncodeCaller: zapcore.ShortCallerEncoder, // 全路径编码器
  53. //EncodeName: zapcore.FullNameEncoder,
  54. }
  55. // 设置日志级别
  56. atomicLevel := zap.NewAtomicLevel()
  57. atomicLevel.SetLevel(level)
  58. core := zapcore.NewCore(
  59. // zapcore.NewConsoleEncoder(encoderConfig),
  60. zapcore.NewJSONEncoder(encoderConfig),
  61. //zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)),
  62. zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(write)), // 打印到控制台和文件
  63. //write, //文件
  64. level,
  65. )
  66. // 开启开发模式,堆栈跟踪
  67. caller := zap.AddCaller()
  68. // 开启文件及行号
  69. development := zap.Development()
  70. // 设置初始化字段,如:添加一个服务器名称
  71. //filed := zap.Fields(zap.String("serviceName", "serviceName"))
  72. // 构造日志
  73. Logger = zap.New(core, caller, development)
  74. Logger.Info("DefaultLogger init success")
  75. }
  76. func formatEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  77. enc.AppendString(fmt.Sprintf("%d-%02d-%02d %02d:%02d:%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()))
  78. }
  79. func Field(key string, val interface{}) zap.Field {
  80. return zap.Any(key, val)
  81. }
  82. const (
  83. _VER string = "1.0.2"
  84. )
  85. type LEVEL int32
  86. var logLevel LEVEL = 1
  87. var maxFileSize int64
  88. var maxFileCount int32
  89. var dailyRolling bool = true
  90. var consoleAppender bool = true
  91. var RollingFile bool = false
  92. var logObj *_FILE
  93. const DATEFORMAT = "2006-01-02"
  94. type UNIT int64
  95. const (
  96. _ = iota
  97. KB UNIT = 1 << (iota * 10)
  98. MB
  99. GB
  100. TB
  101. )
  102. const (
  103. ALL LEVEL = iota
  104. DEBUG
  105. INFO
  106. WARN
  107. ERROR
  108. FATAL
  109. OFF
  110. )
  111. type _FILE struct {
  112. dir string
  113. filename string
  114. _suffix int
  115. isCover bool
  116. _date *time.Time
  117. mu *sync.RWMutex
  118. logfile *os.File
  119. lg *log.Logger
  120. }
  121. func SetConsole(isConsole bool) {
  122. consoleAppender = isConsole
  123. }
  124. func SetLevel(_level LEVEL) {
  125. logLevel = _level
  126. }
  127. func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
  128. maxFileCount = maxNumber
  129. maxFileSize = maxSize * int64(_unit)
  130. RollingFile = true
  131. dailyRolling = false
  132. mkdirlog(fileDir)
  133. logObj = &_FILE{dir: fileDir, filename: fileName, isCover: false, mu: new(sync.RWMutex)}
  134. logObj.mu.Lock()
  135. defer logObj.mu.Unlock()
  136. for i := 1; i <= int(maxNumber); i++ {
  137. if isExist(fileDir + "/" + fileName + "." + strconv.Itoa(i)) {
  138. logObj._suffix = i
  139. } else {
  140. break
  141. }
  142. }
  143. if !logObj.isMustRename() {
  144. logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
  145. logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
  146. } else {
  147. logObj.rename()
  148. }
  149. go fileMonitor()
  150. }
  151. func SetRollingDaily(fileDir, fileName string) {
  152. RollingFile = false
  153. dailyRolling = true
  154. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  155. mkdirlog(fileDir)
  156. logObj = &_FILE{dir: fileDir, filename: fileName, _date: &t, isCover: false, mu: new(sync.RWMutex)}
  157. logObj.mu.Lock()
  158. defer logObj.mu.Unlock()
  159. if !logObj.isMustRename() {
  160. logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
  161. logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
  162. } else {
  163. logObj.rename()
  164. }
  165. }
  166. func mkdirlog(dir string) (e error) {
  167. _, er := os.Stat(dir)
  168. b := er == nil || os.IsExist(er)
  169. if !b {
  170. if err := os.MkdirAll(dir, 0666); err != nil {
  171. if os.IsPermission(err) {
  172. fmt.Println("create dir error:", err.Error())
  173. e = err
  174. }
  175. }
  176. }
  177. return
  178. }
  179. func console(s ...interface{}) {
  180. if consoleAppender {
  181. _, file, line, _ := runtime.Caller(2)
  182. short := file
  183. for i := len(file) - 1; i > 0; i-- {
  184. if file[i] == '/' {
  185. short = file[i+1:]
  186. break
  187. }
  188. }
  189. file = short
  190. log.Println(file, strconv.Itoa(line), s)
  191. }
  192. }
  193. func catchError() {
  194. if err := recover(); err != nil {
  195. log.Println("err", err)
  196. }
  197. }
  198. func Debug(v ...interface{}) {
  199. if dailyRolling {
  200. fileCheck()
  201. }
  202. defer catchError()
  203. if logObj != nil {
  204. logObj.mu.RLock()
  205. defer logObj.mu.RUnlock()
  206. }
  207. if logLevel <= DEBUG {
  208. if logObj != nil {
  209. logObj.lg.Output(2, fmt.Sprintln("debug", v))
  210. }
  211. console("debug", v)
  212. }
  213. }
  214. func Info(v ...interface{}) {
  215. if dailyRolling {
  216. fileCheck()
  217. }
  218. defer catchError()
  219. if logObj != nil {
  220. logObj.mu.RLock()
  221. defer logObj.mu.RUnlock()
  222. }
  223. if logLevel <= INFO {
  224. if logObj != nil {
  225. logObj.lg.Output(2, fmt.Sprintln("info", v))
  226. }
  227. console("info", v)
  228. }
  229. }
  230. func Warn(v ...interface{}) {
  231. if dailyRolling {
  232. fileCheck()
  233. }
  234. defer catchError()
  235. if logObj != nil {
  236. logObj.mu.RLock()
  237. defer logObj.mu.RUnlock()
  238. }
  239. if logLevel <= WARN {
  240. if logObj != nil {
  241. logObj.lg.Output(2, fmt.Sprintln("warn", v))
  242. }
  243. console("warn", v)
  244. }
  245. }
  246. func Error(v ...interface{}) {
  247. if dailyRolling {
  248. fileCheck()
  249. }
  250. defer catchError()
  251. if logObj != nil {
  252. logObj.mu.RLock()
  253. defer logObj.mu.RUnlock()
  254. }
  255. if logLevel <= ERROR {
  256. if logObj != nil {
  257. logObj.lg.Output(2, fmt.Sprintln("error", v))
  258. }
  259. console("error", v)
  260. }
  261. }
  262. func Fatal(v ...interface{}) {
  263. if dailyRolling {
  264. fileCheck()
  265. }
  266. defer catchError()
  267. if logObj != nil {
  268. logObj.mu.RLock()
  269. defer logObj.mu.RUnlock()
  270. }
  271. if logLevel <= FATAL {
  272. if logObj != nil {
  273. logObj.lg.Output(2, fmt.Sprintln("fatal", v))
  274. }
  275. console("fatal", v)
  276. }
  277. }
  278. func (f *_FILE) isMustRename() bool {
  279. if dailyRolling {
  280. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  281. if t.After(*f._date) {
  282. return true
  283. }
  284. } else {
  285. if maxFileCount > 1 {
  286. if fileSize(f.dir+"/"+f.filename) >= maxFileSize {
  287. return true
  288. }
  289. }
  290. }
  291. return false
  292. }
  293. func (f *_FILE) rename() {
  294. if dailyRolling {
  295. fn := f.dir + "/" + f.filename + "." + f._date.Format(DATEFORMAT)
  296. if !isExist(fn) && f.isMustRename() {
  297. if f.logfile != nil {
  298. f.logfile.Close()
  299. }
  300. err := os.Rename(f.dir+"/"+f.filename, fn)
  301. if err != nil {
  302. f.lg.Println("rename err", err.Error())
  303. }
  304. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  305. f._date = &t
  306. f.logfile, _ = os.Create(f.dir + "/" + f.filename)
  307. f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
  308. }
  309. } else {
  310. f.coverNextOne()
  311. }
  312. }
  313. func (f *_FILE) nextSuffix() int {
  314. return int(f._suffix%int(maxFileCount) + 1)
  315. }
  316. func (f *_FILE) coverNextOne() {
  317. f._suffix = f.nextSuffix()
  318. if f.logfile != nil {
  319. f.logfile.Close()
  320. }
  321. if isExist(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix))) {
  322. os.Remove(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix)))
  323. }
  324. os.Rename(f.dir+"/"+f.filename, f.dir+"/"+f.filename+"."+strconv.Itoa(int(f._suffix)))
  325. f.logfile, _ = os.Create(f.dir + "/" + f.filename)
  326. f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
  327. }
  328. func fileSize(file string) int64 {
  329. fmt.Println("fileSize", file)
  330. f, e := os.Stat(file)
  331. if e != nil {
  332. fmt.Println(e.Error())
  333. return 0
  334. }
  335. return f.Size()
  336. }
  337. func isExist(path string) bool {
  338. _, err := os.Stat(path)
  339. return err == nil || os.IsExist(err)
  340. }
  341. func fileMonitor() {
  342. timer := time.NewTicker(1 * time.Second)
  343. for {
  344. select {
  345. case <-timer.C:
  346. fileCheck()
  347. }
  348. }
  349. }
  350. func fileCheck() {
  351. defer func() {
  352. if err := recover(); err != nil {
  353. log.Println(err)
  354. }
  355. }()
  356. if logObj != nil && logObj.isMustRename() {
  357. logObj.mu.Lock()
  358. defer logObj.mu.Unlock()
  359. logObj.rename()
  360. }
  361. }