logger.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package util
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "runtime"
  7. "strconv"
  8. "sync"
  9. "time"
  10. )
  11. const (
  12. _VER string = "1.0.2"
  13. )
  14. type LEVEL int32
  15. var logLevel LEVEL = 1
  16. var maxFileSize int64
  17. var maxFileCount int32
  18. var dailyRolling bool = true
  19. var consoleAppender bool = true
  20. var RollingFile bool = false
  21. var logObj *_FILE
  22. const DATEFORMAT = "2006-01-02"
  23. type UNIT int64
  24. const (
  25. _ = iota
  26. KB UNIT = 1 << (iota * 10)
  27. MB
  28. GB
  29. TB
  30. )
  31. const (
  32. ALL LEVEL = iota
  33. DEBUG
  34. INFO
  35. WARN
  36. ERROR
  37. FATAL
  38. OFF
  39. )
  40. type _FILE struct {
  41. dir string
  42. filename string
  43. _suffix int
  44. isCover bool
  45. _date *time.Time
  46. mu *sync.RWMutex
  47. logfile *os.File
  48. lg *log.Logger
  49. }
  50. func SetConsole(isConsole bool) {
  51. consoleAppender = isConsole
  52. }
  53. func SetLevel(_level LEVEL) {
  54. logLevel = _level
  55. }
  56. func SetRollingFile(fileDir, fileName string, maxNumber int32, maxSize int64, _unit UNIT) {
  57. maxFileCount = maxNumber
  58. maxFileSize = maxSize * int64(_unit)
  59. RollingFile = true
  60. dailyRolling = false
  61. mkdirlog(fileDir)
  62. logObj = &_FILE{dir: fileDir, filename: fileName, isCover: false, mu: new(sync.RWMutex)}
  63. logObj.mu.Lock()
  64. defer logObj.mu.Unlock()
  65. for i := 1; i <= int(maxNumber); i++ {
  66. if isExist(fileDir + "/" + fileName + "." + strconv.Itoa(i)) {
  67. logObj._suffix = i
  68. } else {
  69. break
  70. }
  71. }
  72. if !logObj.isMustRename() {
  73. logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
  74. logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
  75. } else {
  76. logObj.rename()
  77. }
  78. go fileMonitor()
  79. }
  80. func SetRollingDaily(fileDir, fileName string) {
  81. RollingFile = false
  82. dailyRolling = true
  83. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  84. mkdirlog(fileDir)
  85. logObj = &_FILE{dir: fileDir, filename: fileName, _date: &t, isCover: false, mu: new(sync.RWMutex)}
  86. logObj.mu.Lock()
  87. defer logObj.mu.Unlock()
  88. if !logObj.isMustRename() {
  89. logObj.logfile, _ = os.OpenFile(fileDir+"/"+fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
  90. logObj.lg = log.New(logObj.logfile, "", log.Ldate|log.Ltime|log.Lshortfile)
  91. } else {
  92. logObj.rename()
  93. }
  94. }
  95. func mkdirlog(dir string) (e error) {
  96. _, er := os.Stat(dir)
  97. b := er == nil || os.IsExist(er)
  98. if !b {
  99. if err := os.MkdirAll(dir, 0666); err != nil {
  100. if os.IsPermission(err) {
  101. fmt.Println("create dir error:", err.Error())
  102. e = err
  103. }
  104. }
  105. }
  106. return
  107. }
  108. func console(s ...interface{}) {
  109. if consoleAppender {
  110. _, file, line, _ := runtime.Caller(2)
  111. short := file
  112. for i := len(file) - 1; i > 0; i-- {
  113. if file[i] == '/' {
  114. short = file[i+1:]
  115. break
  116. }
  117. }
  118. file = short
  119. log.Println(file, strconv.Itoa(line), s)
  120. }
  121. }
  122. func catchError() {
  123. if err := recover(); err != nil {
  124. log.Println("err", err)
  125. }
  126. }
  127. func Debug(v ...interface{}) {
  128. if dailyRolling {
  129. fileCheck()
  130. }
  131. defer catchError()
  132. if logObj != nil {
  133. logObj.mu.RLock()
  134. defer logObj.mu.RUnlock()
  135. }
  136. if logLevel <= DEBUG {
  137. if logObj != nil {
  138. logObj.lg.Output(2, fmt.Sprintln("debug", v))
  139. }
  140. console("debug", v)
  141. }
  142. }
  143. func Info(v ...interface{}) {
  144. if dailyRolling {
  145. fileCheck()
  146. }
  147. defer catchError()
  148. if logObj != nil {
  149. logObj.mu.RLock()
  150. defer logObj.mu.RUnlock()
  151. }
  152. if logLevel <= INFO {
  153. if logObj != nil {
  154. logObj.lg.Output(2, fmt.Sprintln("info", v))
  155. }
  156. console("info", v)
  157. }
  158. }
  159. func Warn(v ...interface{}) {
  160. if dailyRolling {
  161. fileCheck()
  162. }
  163. defer catchError()
  164. if logObj != nil {
  165. logObj.mu.RLock()
  166. defer logObj.mu.RUnlock()
  167. }
  168. if logLevel <= WARN {
  169. if logObj != nil {
  170. logObj.lg.Output(2, fmt.Sprintln("warn", v))
  171. }
  172. console("warn", v)
  173. }
  174. }
  175. func Error(v ...interface{}) {
  176. if dailyRolling {
  177. fileCheck()
  178. }
  179. defer catchError()
  180. if logObj != nil {
  181. logObj.mu.RLock()
  182. defer logObj.mu.RUnlock()
  183. }
  184. if logLevel <= ERROR {
  185. if logObj != nil {
  186. logObj.lg.Output(2, fmt.Sprintln("error", v))
  187. }
  188. console("error", v)
  189. }
  190. }
  191. func Fatal(v ...interface{}) {
  192. if dailyRolling {
  193. fileCheck()
  194. }
  195. defer catchError()
  196. if logObj != nil {
  197. logObj.mu.RLock()
  198. defer logObj.mu.RUnlock()
  199. }
  200. if logLevel <= FATAL {
  201. if logObj != nil {
  202. logObj.lg.Output(2, fmt.Sprintln("fatal", v))
  203. }
  204. console("fatal", v)
  205. }
  206. }
  207. func (f *_FILE) isMustRename() bool {
  208. if dailyRolling {
  209. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  210. if t.After(*f._date) {
  211. return true
  212. }
  213. } else {
  214. if maxFileCount > 1 {
  215. if fileSize(f.dir+"/"+f.filename) >= maxFileSize {
  216. return true
  217. }
  218. }
  219. }
  220. return false
  221. }
  222. func (f *_FILE) rename() {
  223. if dailyRolling {
  224. fn := f.dir + "/" + f.filename + "." + f._date.Format(DATEFORMAT)
  225. if !isExist(fn) && f.isMustRename() {
  226. if f.logfile != nil {
  227. f.logfile.Close()
  228. }
  229. err := os.Rename(f.dir+"/"+f.filename, fn)
  230. if err != nil {
  231. f.lg.Println("rename err", err.Error())
  232. }
  233. t, _ := time.Parse(DATEFORMAT, time.Now().Format(DATEFORMAT))
  234. f._date = &t
  235. f.logfile, _ = os.Create(f.dir + "/" + f.filename)
  236. f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
  237. }
  238. } else {
  239. f.coverNextOne()
  240. }
  241. }
  242. func (f *_FILE) nextSuffix() int {
  243. return int(f._suffix%int(maxFileCount) + 1)
  244. }
  245. func (f *_FILE) coverNextOne() {
  246. f._suffix = f.nextSuffix()
  247. if f.logfile != nil {
  248. f.logfile.Close()
  249. }
  250. if isExist(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix))) {
  251. os.Remove(f.dir + "/" + f.filename + "." + strconv.Itoa(int(f._suffix)))
  252. }
  253. os.Rename(f.dir+"/"+f.filename, f.dir+"/"+f.filename+"."+strconv.Itoa(int(f._suffix)))
  254. f.logfile, _ = os.Create(f.dir + "/" + f.filename)
  255. f.lg = log.New(logObj.logfile, "\n", log.Ldate|log.Ltime|log.Lshortfile)
  256. }
  257. func fileSize(file string) int64 {
  258. fmt.Println("fileSize", file)
  259. f, e := os.Stat(file)
  260. if e != nil {
  261. fmt.Println(e.Error())
  262. return 0
  263. }
  264. return f.Size()
  265. }
  266. func isExist(path string) bool {
  267. _, err := os.Stat(path)
  268. return err == nil || os.IsExist(err)
  269. }
  270. func fileMonitor() {
  271. timer := time.NewTicker(1 * time.Second)
  272. for {
  273. select {
  274. case <-timer.C:
  275. fileCheck()
  276. }
  277. }
  278. }
  279. func fileCheck() {
  280. defer func() {
  281. if err := recover(); err != nil {
  282. log.Println(err)
  283. }
  284. }()
  285. if logObj != nil && logObj.isMustRename() {
  286. logObj.mu.Lock()
  287. defer logObj.mu.Unlock()
  288. logObj.rename()
  289. }
  290. }