logger.go 8.4 KB

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