io.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. package log
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "io"
  7. "log"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "sync"
  12. "time"
  13. )
  14. func NewLogger(level Level, prefix string, depth int, w ...io.Writer) Logger {
  15. return NewLog(level, w, prefix, depth, 0)
  16. }
  17. func NewFileWriter(prefix, path string) io.WriteCloser {
  18. return &file{
  19. Prefix: prefix,
  20. Path: path,
  21. }
  22. }
  23. func ConsoleWith(level Level, dept int) *Log {
  24. return NewLog(level, []io.Writer{os.Stdout}, "", dept, 0)
  25. }
  26. func Discard() *Log {
  27. return NewLog(LevelNone, []io.Writer{io.Discard}, "", 0, 0)
  28. }
  29. func Fork(l Logger, subPath, prefix string) Logger {
  30. return rebuild(l, subPath, prefix, true)
  31. }
  32. func Part(l Logger, subPath, prefix string) Logger {
  33. return rebuild(l, subPath, prefix, false)
  34. }
  35. func rebuild(l Logger, subPath, prefix string, withMain bool) Logger {
  36. switch old := l.(type) {
  37. case *Log:
  38. pool := make([]io.Writer, 0, len(old.wPool))
  39. for _, w := range old.wPool {
  40. if f, o := w.(*file); o {
  41. if prefix == "" {
  42. prefix = "log"
  43. }
  44. pool = append(pool,
  45. NewFileWriter(filepath.Base(prefix), filepath.Join(f.Path, subPath)),
  46. )
  47. if withMain {
  48. pool = append(pool, f)
  49. }
  50. } else {
  51. if w == os.Stdout {
  52. pool = append(pool, Console())
  53. } else {
  54. pool = append(pool, w)
  55. }
  56. }
  57. }
  58. return NewLog(old.level, pool, prefix, old.depth, old.buf)
  59. case MultiLogger:
  60. part := make(MultiLogger, len(old))
  61. for i, ol := range old {
  62. if lg, ok := ol.(*Log); ok {
  63. part[i] = rebuild(lg, subPath, prefix, withMain)
  64. } else {
  65. part[i] = ol
  66. }
  67. }
  68. return part
  69. default:
  70. return l
  71. }
  72. }
  73. func NewSession(l Logger, sessionId string) Logger {
  74. switch old := l.(type) {
  75. case *Log:
  76. return NewLog(old.level, old.wPool, strings.TrimSuffix(old.prefix, " ")+sessionId, old.depth, old.buf)
  77. case MultiLogger:
  78. logs := make(MultiLogger, len(old))
  79. for i, ol := range old {
  80. logs[i] = NewSession(ol, sessionId)
  81. }
  82. return logs
  83. default:
  84. return l
  85. }
  86. }
  87. var consoleLog = ConsoleWith(LevelDebug, 2)
  88. func Console() *Log {
  89. return consoleLog
  90. }
  91. type Level int
  92. const (
  93. LevelNone Level = 0
  94. )
  95. const (
  96. LevelError Level = iota + 1
  97. LevelWarn
  98. LevelInfo
  99. LevelDebug
  100. )
  101. const (
  102. LevelsError = "[E]"
  103. LevelsWarn = "[W]"
  104. LevelsInfo = "[I]"
  105. LevelsDebug = "[D]"
  106. )
  107. const (
  108. PrintFlags = log.LstdFlags | log.Llongfile
  109. )
  110. const (
  111. Ext = ".log"
  112. )
  113. const (
  114. Layout = "2006_01_02"
  115. )
  116. type FileName string
  117. func (f FileName) Prefix() string {
  118. return string(f)[:strings.Index(string(f), "_")]
  119. }
  120. func (f FileName) Date() string {
  121. last := strings.LastIndex(string(f), ".")
  122. idx := len(f) - len(Layout) - len(Ext)
  123. return string(f)[idx:last]
  124. }
  125. func (f FileName) Ext() string {
  126. return filepath.Ext(string(f))
  127. }
  128. func (f FileName) String() string { return string(f) }
  129. func buildPrefix(s string) string {
  130. return "[" + s + "]"
  131. }
  132. func spitPrefix(s string) string {
  133. idx := strings.Index(s, " ")
  134. if idx == -1 {
  135. return s
  136. }
  137. s = strings.ToLower(s[:idx])
  138. s = strings.TrimPrefix(s, "[")
  139. s = strings.TrimSuffix(s, "]")
  140. return s
  141. }
  142. type file struct {
  143. Prefix string // svc
  144. Path string // /var/log
  145. date time.Time // 2006_01_02
  146. fi *os.File
  147. }
  148. func (f *file) Write(b []byte) (n int, err error) {
  149. if err = f.check(); err != nil {
  150. return 0, err
  151. }
  152. return f.fi.Write(b)
  153. }
  154. func (f *file) Close() error {
  155. if f.fi != nil {
  156. return f.fi.Close()
  157. }
  158. return nil
  159. }
  160. func (f *file) createDir() error {
  161. if _, err := os.Stat(f.Path); err != nil {
  162. if os.IsNotExist(err) {
  163. // 这里文件夹权限即使设置为 ModePerm, Linux 系统权限也是 755
  164. if err = os.MkdirAll(f.Path, os.ModePerm); err != nil {
  165. return err
  166. }
  167. }
  168. return err
  169. }
  170. return nil
  171. }
  172. func (f *file) openFile(date string) (*os.File, error) {
  173. return os.OpenFile(f.name(date), os.O_WRONLY|os.O_CREATE|os.O_APPEND, os.ModePerm) // 创建文件
  174. }
  175. func (f *file) name(date string) string {
  176. path := fmt.Sprintf("%s_%s%s", f.Prefix, date, Ext)
  177. if f.Prefix == "" {
  178. path = date + Ext
  179. }
  180. // /var/log/svc_2006_01_02.log
  181. return filepath.Join(f.Path, path)
  182. }
  183. func (f *file) checkDate(cur time.Time) bool {
  184. curY, curM, curD := cur.Date()
  185. oldY, oldM, oldD := f.date.Date()
  186. if curY == oldY && curM == oldM && curD == oldD {
  187. return true
  188. }
  189. return false
  190. }
  191. func (f *file) check() error {
  192. if f.fi == nil {
  193. if err := f.createDir(); err != nil {
  194. return err
  195. }
  196. }
  197. cur := time.Now()
  198. if f.checkDate(cur) {
  199. return nil
  200. }
  201. if f.fi != nil {
  202. _ = f.fi.Close()
  203. }
  204. fi, err := f.openFile(cur.Format(Layout))
  205. if err != nil {
  206. return err
  207. }
  208. f.fi = fi
  209. f.date = cur
  210. return nil
  211. }
  212. type Log struct {
  213. level Level
  214. depth int // 2
  215. prefix string
  216. buf int
  217. wPool []io.Writer
  218. logs []*log.Logger
  219. mu sync.Mutex
  220. }
  221. func NewLog(level Level, writers []io.Writer, prefix string, depth int, buf int) *Log {
  222. if depth < 0 {
  223. depth = 0
  224. }
  225. if prefix != "" {
  226. prefix = prefix + " "
  227. }
  228. l := new(Log)
  229. l.level = level
  230. l.prefix = prefix
  231. l.depth = depth
  232. l.wPool = writers
  233. l.buf = buf
  234. l.logs = make([]*log.Logger, len(l.wPool))
  235. for i := 0; i < len(l.wPool); i++ {
  236. w := l.wPool[i]
  237. if buf > 0 {
  238. w = bufio.NewWriterSize(w, buf)
  239. }
  240. l.logs[i] = log.New(w, prefix, func() int {
  241. if depth <= 0 {
  242. return log.LstdFlags
  243. }
  244. return PrintFlags
  245. }())
  246. }
  247. return l
  248. }
  249. func (l *Log) CallDepthPlus() {
  250. l.depth++
  251. }
  252. func (l *Log) CallDepthMinus() {
  253. l.depth--
  254. }
  255. func (l *Log) Write(b []byte) (int, error) {
  256. if l.level == LevelNone {
  257. return len(b), nil
  258. }
  259. l.mu.Lock()
  260. n, err := bytes.NewReader(b).WriteTo(io.MultiWriter(l.wPool...))
  261. l.mu.Unlock()
  262. return int(n), err
  263. }
  264. func (l *Log) Prefix(prefix string, f string, v ...any) {
  265. if l.level == LevelNone {
  266. return
  267. }
  268. l.mu.Lock()
  269. for _, lg := range l.logs {
  270. l.setPrefixFmt(lg, prefix)
  271. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  272. }
  273. l.mu.Unlock()
  274. }
  275. func (l *Log) Println(f string, v ...any) {
  276. if l.level == LevelNone {
  277. return
  278. }
  279. l.mu.Lock()
  280. for _, lg := range l.logs {
  281. l.setPrefixFmt(lg, "")
  282. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  283. }
  284. l.mu.Unlock()
  285. }
  286. // Logger start
  287. func (l *Log) Error(f string, v ...any) {
  288. if l.level < LevelError {
  289. return
  290. }
  291. l.mu.Lock()
  292. for _, lg := range l.logs {
  293. l.setPrefixFmt(lg, LevelsError)
  294. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  295. }
  296. l.mu.Unlock()
  297. }
  298. func (l *Log) Warn(f string, v ...any) {
  299. if l.level < LevelWarn {
  300. return
  301. }
  302. l.mu.Lock()
  303. for _, lg := range l.logs {
  304. l.setPrefixFmt(lg, LevelsWarn)
  305. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  306. }
  307. l.mu.Unlock()
  308. }
  309. func (l *Log) Info(f string, v ...any) {
  310. if l.level < LevelInfo {
  311. return
  312. }
  313. l.mu.Lock()
  314. for _, lg := range l.logs {
  315. l.setPrefixFmt(lg, LevelsInfo)
  316. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  317. }
  318. l.mu.Unlock()
  319. }
  320. func (l *Log) Debug(f string, v ...any) {
  321. if l.level < LevelDebug {
  322. return
  323. }
  324. l.mu.Lock()
  325. for _, lg := range l.logs {
  326. l.setPrefixFmt(lg, LevelsDebug)
  327. _ = lg.Output(l.depth, fmt.Sprintf(l.prefix+f, v...))
  328. }
  329. l.mu.Unlock()
  330. }
  331. // Logger end
  332. func (l *Log) setPrefixFmt(logger *log.Logger, s string) {
  333. prefix := s + " "
  334. if logger.Prefix() == prefix {
  335. return
  336. }
  337. logger.SetPrefix(prefix)
  338. }