github.com/keakon/golog@v0.0.0-20230330091222-cac71197c18d/README.md (about)

     1  # golog
     2  [![GoDoc](https://pkg.go.dev/badge/github.com/keakon/golog)](https://pkg.go.dev/github.com/keakon/golog)
     3  [![Build Status](https://github.com/keakon/golog/actions/workflows/go.yml/badge.svg)](https://github.com/keakon/golog/actions)
     4  [![Go Report Card](https://goreportcard.com/badge/github.com/keakon/golog)](https://goreportcard.com/report/github.com/keakon/golog)
     5  [![codecov](https://codecov.io/gh/keakon/golog/branch/master/graph/badge.svg?token=dmE2GC9in2)](https://codecov.io/gh/keakon/golog)
     6  
     7  ## Features
     8  
     9  1. Unstructured
    10  2. Leveled
    11  3. With caller (file path / name and line number)
    12  4. Customizable output format
    13  5. Rotating by size, date or hour
    14  6. Cross platform, tested on Linux, macOS and Windows
    15  7. No 3rd party dependance
    16  8. Fast
    17  9. Thread safe
    18  
    19  ## Installation
    20  
    21  ```
    22  go get -u github.com/keakon/golog
    23  ```
    24  
    25  ## Examples
    26  
    27  ### Logging to console
    28  
    29  ```go
    30  package main
    31  
    32  import (
    33      "github.com/keakon/golog"
    34      "github.com/keakon/golog/log"
    35  )
    36  
    37  func main() {
    38      l := golog.NewStdoutLogger()
    39      defer l.Close()
    40  
    41      l.Infof("hello %d", 1)
    42  
    43      log.SetDefaultLogger(l)
    44      test()
    45  }
    46  
    47  func test() {
    48      log.Infof("hello %d", 2)
    49  }
    50  ```
    51  
    52  ### Logging to file
    53  
    54  ```go
    55  func main() {
    56      w, _ := golog.NewBufferedFileWriter("test.log")
    57      l := golog.NewLoggerWithWriter(w)
    58      defer l.Close()
    59  
    60      l.Infof("hello world")
    61  }
    62  ```
    63  
    64  ### Rotating
    65  
    66  ```go
    67  func main() {
    68      w, _ := golog.NewTimedRotatingFileWriter("test", golog.RotateByDate, 30)
    69      l := golog.NewLoggerWithWriter(w)
    70      defer l.Close()
    71  
    72      l.Infof("hello world")
    73  }
    74  ```
    75  
    76  ### Formatting
    77  
    78  ```go
    79  func main() {
    80      w := golog.NewStdoutWriter()
    81  
    82      f := golog.ParseFormat("[%l %D %T %S] %m")
    83      h := golog.NewHandler(golog.InfoLevel, f)
    84      h.AddWriter(w)
    85  
    86      l := golog.NewLogger(golog.InfoLevel)
    87      l.AddHandler(h)
    88      defer l.Close()
    89  
    90      l.Infof("hello world")
    91  }
    92  ```
    93  
    94  Check [document](https://pkg.go.dev/github.com/keakon/golog#Formatter.Format) for more format directives.
    95  
    96  ### Fast timer
    97  
    98  ```go
    99  func main() {
   100      golog.StartFastTimer()
   101      defer golog.StopFastTimer()
   102  
   103      l := golog.NewStdoutLogger()
   104      defer l.Close()
   105  
   106      l.Infof("hello world")
   107  }
   108  ```
   109  
   110  The fast timer is about 30% faster than calling time.Time() for each logging record. But it's not thread-safe which may cause some problems (I think those are negligible in most cases):
   111  1. The timer updates every 1 second, so the logging time can be at most 1 second behind the real time.
   112  2. Each thread will notice the changes of timer in a few milliseconds, so the concurrent logging messages may get different logging time (less than 2% probability). eg:
   113  ```
   114  [I 2021-09-13 14:31:25 log_test:206] test
   115  [I 2021-09-13 14:31:24 log_test:206] test
   116  [I 2021-09-13 14:31:25 log_test:206] test
   117  ```
   118  3. When the day changing, the logging date and time might belong to different day. eg:
   119  ```
   120  [I 2021-09-12 23:59:59 log_test:206] test
   121  [I 2021-09-13 23:59:59 log_test:206] test
   122  [I 2021-09-12 00:00:00 log_test:206] test
   123  ```
   124  
   125  ### ConcurrentFileWriter *(experimental)*
   126  
   127  
   128  ```go
   129  func main() {
   130      w, _ := golog.NewConcurrentFileWriter("test.log")
   131      l := golog.NewLoggerWithWriter(w)
   132      defer l.Close()
   133  
   134      l.Infof("hello world")
   135  }
   136  ```
   137  
   138  The `ConcurrentFileWriter` is designed for high concurrency applications.
   139  It is about 140% faster than `BufferedFileWriter` at 6C12H by reducing the lock overhead, but a little slower at single thread.  
   140  **Note**: The order of logging records from different cpu cores within each 0.1 second is random.
   141  
   142  ## Benchmarks
   143  
   144  ### Platform
   145  
   146  go1.19.2 darwin/amd64
   147  cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
   148  
   149  ### Result
   150  
   151  | Name | Time/op | Time (x) | Alloc/op | allocs/op |
   152  | :--- | :---: | :---: | :---: | :---: |
   153  | DiscardLogger | 483ns ± 1% | 1.00 | 0B | 0 |
   154  | DiscardLoggerParallel | 89.0ns ± 6% | 1.00 | 0B | 0 |
   155  | DiscardLoggerWithoutTimer | 691ns ± 7% | 1.43 | 0B | 0 |
   156  | DiscardLoggerWithoutTimerParallel | 129ns ± 5% | 1.45 | 0B | 0 |
   157  | NopLog | 1.5ns ± 1% | 0.003 | 0B | 0 |
   158  | NopLogParallel | 0.22ns ± 3% | 0.002 | 0B | 0 |
   159  | MultiLevels | 2.77µs ± 7% | 5.73 | 0B | 0 |
   160  | MultiLevelsParallel | 532ns ± 15% | 5.98 | 0B | 0 |
   161  | BufferedFileLogger | 588ns ± 2% | 1.22 | 0B | 0 |
   162  | BufferedFileLoggerParallel | 241ns ± 1% | 2.71 | 0B | 0 |
   163  | ConcurrentFileLogger | 593ns ± 1% | 1.23 | 0B | 0 |
   164  | ConcurrentFileLoggerParallel | 101ns ± 2% | 1.13 | 0B | 0 |
   165  | | | | | |
   166  | DiscardZerolog | 2.24µs ± 1% | 4.64 | 280B | 3 |
   167  | DiscardZerologParallel | 408ns ± 10% | 4.58 | 280B | 3 |
   168  | DiscardZap | 2.13µs ± 0% | 4.41 | 272B | 5 |
   169  | DiscardZapParallel | 465ns ± 5% | 5.22 | 274B | 5 |
   170  
   171  * DiscardLogger: writes logs to `ioutil.Discard`
   172  * DiscardLoggerWithoutTimer: the same as above but without fast timer
   173  * NopLog: skips logs with lower level than the logger or handler
   174  * MultiLevels: writes 5 levels of logs to 5 levels handlers of a warning level logger
   175  * BufferedFileLogger: writes logs to a disk file
   176  * ConcurrentFileLogger: writes logs to a disk file with `ConcurrentFileWriter`
   177  * DiscardZerolog: writes logs to `ioutil.Discard` with [zerolog](https://github.com/rs/zerolog)
   178  * DiscardZap: writes logs to `ioutil.Discard` with [zap](https://github.com/uber-go/zap) using `zap.NewProductionEncoderConfig()`
   179  
   180  All the logs include 4 parts: level, time, caller and message. This is an example output of the benchmarks:
   181  
   182  ```
   183  [I 2018-11-20 17:05:37 log_test:118] test
   184  ```