gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/debug/service/handler/debug.go (about) 1 // Pacjage handler implements service debug handler 2 package handler 3 4 import ( 5 "context" 6 "runtime" 7 "time" 8 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/log" 10 proto "gitee.com/liuxuezhan/go-micro-v1.18.0/debug/service/proto" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/server" 12 ) 13 14 var ( 15 // DefaultHandler is default debug handler 16 DefaultHandler = newDebug() 17 ) 18 19 type Debug struct { 20 started int64 21 proto.DebugHandler 22 log log.Log 23 } 24 25 func newDebug() *Debug { 26 return &Debug{ 27 started: time.Now().Unix(), 28 log: log.DefaultLog, 29 } 30 } 31 32 func (d *Debug) Health(ctx context.Context, req *proto.HealthRequest, rsp *proto.HealthResponse) error { 33 rsp.Status = "ok" 34 return nil 35 } 36 37 func (d *Debug) Stats(ctx context.Context, req *proto.StatsRequest, rsp *proto.StatsResponse) error { 38 var mstat runtime.MemStats 39 runtime.ReadMemStats(&mstat) 40 41 rsp.Timestamp = uint64(time.Now().Unix()) 42 rsp.Started = uint64(d.started) 43 rsp.Uptime = uint64(time.Now().Unix() - d.started) 44 rsp.Memory = mstat.Alloc 45 rsp.Gc = mstat.PauseTotalNs 46 rsp.Threads = uint64(runtime.NumGoroutine()) 47 return nil 48 } 49 50 func (d *Debug) Log(ctx context.Context, stream server.Stream) error { 51 req := new(proto.LogRequest) 52 if err := stream.Recv(req); err != nil { 53 return err 54 } 55 56 var options []log.ReadOption 57 58 since := time.Unix(req.Since, 0) 59 if !since.IsZero() { 60 options = append(options, log.Since(since)) 61 } 62 63 count := int(req.Count) 64 if count > 0 { 65 options = append(options, log.Count(count)) 66 } 67 68 if req.Stream { 69 stop := make(chan bool) 70 defer close(stop) 71 72 // TODO: we need to figure out how to close ithe log stream 73 // It seems like when a client disconnects, 74 // the connection stays open until some timeout expires 75 // or something like that; that means the map of streams 76 // might end up leaking memory if not cleaned up properly 77 records := d.log.Stream(stop) 78 for record := range records { 79 if err := d.sendRecord(record, stream); err != nil { 80 return err 81 } 82 } 83 // done streaming, return 84 return nil 85 } 86 87 // get the log records 88 records := d.log.Read(options...) 89 // send all the logs downstream 90 for _, record := range records { 91 if err := d.sendRecord(record, stream); err != nil { 92 return err 93 } 94 } 95 96 return nil 97 } 98 99 func (d *Debug) sendRecord(record log.Record, stream server.Stream) error { 100 metadata := make(map[string]string) 101 for k, v := range record.Metadata { 102 metadata[k] = v 103 } 104 105 pbRecord := &proto.Record{ 106 Timestamp: record.Timestamp.Unix(), 107 Value: record.Value.(string), 108 Metadata: metadata, 109 } 110 111 if err := stream.Send(pbRecord); err != nil { 112 return err 113 } 114 115 return nil 116 }