io.go 7.2 KB

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