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  }