myLog.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package lxLog
  2. import (
  3. "fmt"
  4. "os"
  5. "runtime"
  6. "strconv"
  7. "time"
  8. )
  9. // 异步写日志
  10. var LxLog *FileLog
  11. const (
  12. LogSplitTypeHour = iota
  13. LogSplitTypeSize
  14. logPath = "myLog"
  15. logName = "myLog"
  16. chanSize = 5000
  17. )
  18. type FileLog struct {
  19. logPath string
  20. logName string
  21. file *os.File //普通日志
  22. warnFile *os.File //错误日志 级别低
  23. logDataChan chan *LogData
  24. logSplitType int //分割类型
  25. logSplitSize int64 //分割体积
  26. lastSplitHour int //分割时间
  27. }
  28. type LogData struct {
  29. Message string
  30. TimeStr string
  31. LevelStr string
  32. IsWarn bool
  33. File string
  34. }
  35. func InitLog() (log *FileLog) {
  36. config := make(map[string]string, 8)
  37. config["log_path"] = "."
  38. config["log_name"] = "server"
  39. config["log_chan_size"] = "50000" //chan size 可以不用
  40. config["log_split_type"] = "size"
  41. config["log_split_size"] = strconv.Itoa(100 * 1024 * 1024) // 100MB
  42. log, err := NewFileLog(config)
  43. if err != nil {
  44. panic("init lxLog err")
  45. }
  46. LxLog = log
  47. return log
  48. }
  49. func NewFileLog(config map[string]string) (logFile *FileLog, err error) {
  50. var logSplitType = LogSplitTypeSize
  51. var logSplitSize int64
  52. splitType, ok := config["log_split_type"]
  53. if !ok {
  54. splitType = "hour"
  55. } else {
  56. if splitType == "size" {
  57. splitSize, ok := config["log_split_size"]
  58. if !ok {
  59. splitSize = "104857600" //100M 以文字来讲很多了
  60. }
  61. logSplitSize, err = strconv.ParseInt(splitSize, 10, 64)
  62. if err != nil {
  63. logSplitSize = 104857600
  64. }
  65. logSplitType = LogSplitTypeSize
  66. } else {
  67. logSplitType = LogSplitTypeHour
  68. }
  69. }
  70. //打开日志文件
  71. exist, err := PathIsExists(logPath)
  72. if err != nil {
  73. fmt.Printf("get dir error![%v]\n", err)
  74. return
  75. }
  76. if !exist {
  77. err = os.Mkdir(logPath, os.ModePerm)
  78. if err != nil {
  79. fmt.Printf("mkdir failed![%v]\n", err)
  80. return
  81. } else {
  82. fmt.Printf("mkdir success!\n")
  83. }
  84. }
  85. //正常日志
  86. fileName := fmt.Sprintf("%s/%s.lxLog", logPath, logName)
  87. file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
  88. //错误日志
  89. fileNameWarn := fmt.Sprintf("%s/%s.lxLog.err", logPath, logName)
  90. fileWarn, err := os.OpenFile(fileNameWarn, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
  91. if err != nil {
  92. return
  93. }
  94. logFile = &FileLog{
  95. logPath: logPath,
  96. logName: logName,
  97. logDataChan: make(chan *LogData, chanSize),
  98. file: file,
  99. warnFile: fileWarn,
  100. logSplitType: logSplitType,
  101. logSplitSize: logSplitSize,
  102. lastSplitHour: time.Now().Hour(),
  103. }
  104. go logFile.writeLogBackGround()
  105. return
  106. }
  107. // 判断文件夹是否存在
  108. func PathIsExists(path string) (bool, error) {
  109. _, err := os.Stat(path)
  110. if err == nil {
  111. return true, nil
  112. }
  113. if os.IsNotExist(err) {
  114. return false, nil
  115. }
  116. return false, err
  117. }
  118. func (f *FileLog) Info(message string) {
  119. _, file, line, _ := runtime.Caller(1)
  120. fi := file + ":" + strconv.Itoa(line)
  121. f.print(message, "info", fi)
  122. }
  123. func (f *FileLog) Debug(message string) {
  124. _, file, line, _ := runtime.Caller(1)
  125. fi := file + ":" + strconv.Itoa(line)
  126. f.print(message, "debug", fi)
  127. }
  128. func (f *FileLog) Warn(message string) {
  129. _, file, line, _ := runtime.Caller(1)
  130. fi := file + ":" + strconv.Itoa(line)
  131. f.print(message, "warn", fi)
  132. }
  133. func (f *FileLog) Error(message string) {
  134. _, file, line, _ := runtime.Caller(1)
  135. fi := file + ":" + strconv.Itoa(line)
  136. f.print(message, "error", fi)
  137. }
  138. func (f *FileLog) print(message, Type string, file string) {
  139. isWarn := false
  140. if Type == "error" {
  141. isWarn = true
  142. }
  143. msg := &LogData{
  144. Message: message,
  145. TimeStr: time.Now().Format("2006-01-02 15:04:05"),
  146. LevelStr: Type,
  147. IsWarn: isWarn,
  148. File: file,
  149. }
  150. // 怕chan满了插不进去
  151. select {
  152. case f.logDataChan <- msg:
  153. default:
  154. }
  155. }
  156. func (f *FileLog) writeLogBackGround() {
  157. for logData := range f.logDataChan {
  158. var file = f.file
  159. if logData.IsWarn {
  160. file = f.warnFile
  161. }
  162. f.checkSplitFile(logData.IsWarn) // 检查文件分割类型
  163. fmt.Fprintf(file, "%s %s %s %s\n", logData.TimeStr, logData.LevelStr, logData.Message, logData.File)
  164. }
  165. }
  166. func (f *FileLog) checkSplitFile(isWarn bool) {
  167. if f.logSplitType == LogSplitTypeHour {
  168. f.splitHour(isWarn)
  169. return
  170. }
  171. f.splitSize(isWarn)
  172. }
  173. // 根据时间切割
  174. func (f *FileLog) splitHour(isWarn bool) {
  175. now := time.Now()
  176. hour := now.Hour()
  177. if hour == f.lastSplitHour {
  178. return
  179. }
  180. f.lastSplitHour = hour
  181. var backupFileName string
  182. var fileName string
  183. if isWarn {
  184. backupFileName = fmt.Sprintf("%s/%s.lxLog.err_%s", f.logPath, f.logName, now.Format("20060102150405"))
  185. fileName = fmt.Sprintf("%s/%s.lxLog.err", f.logPath, f.logName)
  186. } else {
  187. backupFileName = fmt.Sprintf("%s/%s.log_%s", f.logPath, f.logName, now.Format("20060102150405"))
  188. fileName = fmt.Sprintf("%s/%s.lxLog", f.logPath, f.logName)
  189. }
  190. file := f.file
  191. if isWarn {
  192. file = f.warnFile
  193. }
  194. file.Close()
  195. os.Rename(fileName, backupFileName)
  196. file, err := os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
  197. if err != nil {
  198. return
  199. }
  200. if isWarn {
  201. f.warnFile = file
  202. } else {
  203. f.file = file
  204. }
  205. }
  206. // 根据文件大小来分割
  207. func (f *FileLog) splitSize(isWarn bool) {
  208. file := f.file
  209. if isWarn {
  210. file = f.warnFile
  211. }
  212. fileInfo, err := file.Stat() // 可以得到文件的参数
  213. if err != nil {
  214. return
  215. }
  216. fileSize := fileInfo.Size()
  217. if fileSize <= f.logSplitSize {
  218. return
  219. }
  220. var backupFileName string
  221. var fileName string
  222. now := time.Now()
  223. if isWarn {
  224. backupFileName = fmt.Sprintf("%s/%s.log_%s", f.logPath, f.logName, now.Format("20060102150405"))
  225. fileName = fmt.Sprintf("%s/%s.lxLog", f.logPath, f.logName)
  226. } else {
  227. backupFileName = fmt.Sprintf("%s/%s.lxLog.err_%s", f.logPath, f.logName, now.Format("20060102150405"))
  228. fileName = fmt.Sprintf("%s/%s.lxLog.err", f.logPath, f.logName)
  229. }
  230. file.Close()
  231. os.Rename(fileName, backupFileName)
  232. file, err = os.OpenFile(fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
  233. if err != nil {
  234. return
  235. }
  236. if isWarn {
  237. f.warnFile = file
  238. } else {
  239. f.file = file
  240. }
  241. }