github.com/nikandfor/tlog@v0.21.5-0.20231108111739-3ef89426a96d/README.md (about) 1 [![Documentation](https://pkg.go.dev/badge/github.com/nikandfor/tlog)](https://pkg.go.dev/github.com/nikandfor/tlog?tab=doc) 2 [![Go workflow](https://github.com/nikandfor/tlog/actions/workflows/go.yml/badge.svg)](https://github.com/nikandfor/tlog/actions/workflows/go.yml) 3 [![CircleCI](https://circleci.com/gh/nikandfor/tlog.svg?style=svg)](https://circleci.com/gh/nikandfor/tlog) 4 [![codecov](https://codecov.io/gh/nikandfor/tlog/tags/latest/graph/badge.svg)](https://codecov.io/gh/nikandfor/tlog) 5 [![Go Report Card](https://goreportcard.com/badge/github.com/nikandfor/tlog)](https://goreportcard.com/report/github.com/nikandfor/tlog) 6 ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/nikandfor/tlog?sort=semver) 7 8 **The repo was moved to https://github.com/tlog-dev/tlog** 9 10 # tlog 11 12 At least it is a logger, but it is much more than that. 13 It is an observability events system. 14 Event is a log or tracing message, tracing span start or finish, metric value, or anything you need. 15 Tons of work has been done to make it effective yet comfortable to use. 16 The events are encoded in a machine-readable format to be processed in any way, instant or later. 17 Events could be printed as logs, combined to build distributed traces, filtered and sent to an alerting service, processed and analyzed, and more. 18 19 tlog is a new way of instrumentation. Log once use smart. 20 21 Explore [examples](examples) and [extensions](ext). 22 23 # Status 24 25 The logging API is pretty solid. Now I'm working mostly on backend parts, web interface, integrations. 26 27 # Quick Start 28 29 ## Logger 30 31 ```go 32 tlog.Printf("just like log.Printf") 33 34 tlog.Printw("but structured is", "much", "better") 35 36 type Req struct { 37 Start time.Time 38 Path string 39 } 40 41 tlog.Printw("any value type is", "supported", &Req{Start: time.Now(), Path: "/resource/path"}) 42 43 l := tlog.New(ioWriter) 44 l.Printw("yet another logger, seriously?") 45 ``` 46 47 ## Debug Topics Instead of Log Levels 48 49 No need to choose between tons of unrelated Debug logs and scant Info logs. 50 Each event can be filtered precisely and filter can be changed at runtime. 51 52 ```go 53 tlog.SetVerbosity("rawdb,dump_request") 54 55 tlog.V("rawdb").Printw("make db query", "query", query) // V is inspired by glog.V 56 57 if tlog.If("dump_request") { 58 // some heavy calculations could also be here 59 tlog.Printw("full request data", "request", request) 60 } 61 62 if tlog.If("full_token") { 63 tlog.Printw("db token", "token", token) 64 } else { 65 tlog.Printw("db token", "token", token.ID) 66 } 67 ``` 68 69 Filtering is very flexible. 70 You can select topics, functions, types, files, packages, topics in locations. 71 You can select all in the file and then unselect some functions, etc. 72 73 ## Traces 74 75 Traces are vital if you have simultaneous requests or distributed request propagation. 76 So they integrated into the logger to have the best experience. 77 78 ```go 79 func ServeRequest(req *Request) { 80 span := tlog.Start("request_root", "client", req.RemoteAddr, "path", req.URL.Path) 81 defer span.Finish() 82 83 ctx := tlog.ContextWithSpan(req.Context(), span) 84 85 doc, err := loadFromDB(ctx, req.URL.Path) 86 // if err ... 87 88 _ = doc 89 } 90 91 func loadFromDB(ctx context.Context, doc string) (err error) { 92 parent := tlog.SpanFromContext(ctx) 93 span := parent.V("dbops").Spawn("load_from_db", "doc", doc) 94 defer func() { 95 span.Finish("err", err) // record result error 96 }() 97 98 span.Printw("prepare query") 99 // ... 100 101 if dirtyPages > tooMuch { 102 // record event to the local span or to the parent if the local was not selected 103 span.Or(parent).Printw("too much of dirty pages", "durty_pages", dirtyPages, 104 tlog.KeyLogLevel, tlog.Warn) 105 } 106 } 107 ``` 108 109 Trace events are the same to log events, except they have IDs. 110 You do not need to add the same data to trace attributes and write them to logs. It's the same! 111 112 ## Data Format 113 114 Events are just key-value associative arrays. All keys are optional, any can be added. 115 Some keys have special meaning, like event timestamp or log level. 116 But it's only a convention; representational parts primarily use it: console pretty text formatter moves time to the first column, for example. 117 118 The default format is a machine readable CBOR-like binary format. And the logger backend is just io.Writer. 119 Text, JSON, Logfmt converters are provided. Any other can be implemented. 120 121 There is also a special compression format: as fast and efficient as snappy 122 yet safe in a sense that each event (or batch write) emits single Write to the file (io.Writer actually). 123 124 # Performance 125 126 Performance was in mind from the very beginning. The idea is to emit as many events as you want and not to pay for that by performance. 127 In a typical efficient application CPU profile, the logger takes only 1-3% of CPU usage with no events economy. 128 Almost all allocations were eliminated. That means less work is done, no garbage collector pressure, and lower memory usage.