Move stream to interface

This commit is contained in:
Asim Aslam
2019-12-17 16:56:55 +00:00
parent 91e057440d
commit d2a3fd0b04
11 changed files with 269 additions and 217 deletions

View File

@@ -71,10 +71,13 @@ func (d *Debug) Log(ctx context.Context, stream server.Stream) error {
// the connection stays open until some timeout expires
// or something like that; that means the map of streams
// might end up leaking memory if not cleaned up properly
records, stop := d.log.Stream()
defer close(stop)
lgStream, err := d.log.Stream()
if err != nil {
return err
}
defer lgStream.Stop()
for record := range records {
for record := range lgStream.Chan() {
if err := d.sendRecord(record, stream); err != nil {
return err
}
@@ -85,7 +88,10 @@ func (d *Debug) Log(ctx context.Context, stream server.Stream) error {
}
// get the log records
records := d.log.Read(options...)
records, err := d.log.Read(options...)
if err != nil {
return err
}
// send all the logs downstream
for _, record := range records {

View File

@@ -1,6 +1,8 @@
package service
import (
"time"
"github.com/micro/go-micro/debug"
"github.com/micro/go-micro/debug/log"
)
@@ -10,50 +12,36 @@ type serviceLog struct {
}
// Read reads log entries from the logger
func (s *serviceLog) Read(opts ...log.ReadOption) []log.Record {
// TODO: parse opts
stream, err := s.Client.Log(opts...)
if err != nil {
return nil
func (s *serviceLog) Read(opts ...log.ReadOption) ([]log.Record, error) {
var options log.ReadOptions
for _, o := range opts {
o(&options)
}
stream, err := s.Client.Log(options.Since, options.Count, false)
if err != nil {
return nil, err
}
defer stream.Stop()
// stream the records until nothing is left
var records []log.Record
for record := range stream {
for record := range stream.Chan() {
records = append(records, record)
}
return records
return records, nil
}
// There is no write support
func (s *serviceLog) Write(r log.Record) {
return
func (s *serviceLog) Write(r log.Record) error {
return nil
}
// Stream log records
func (s *serviceLog) Stream() (<-chan log.Record, chan bool) {
stop := make(chan bool)
stream, err := s.Client.Log(log.Stream(true))
if err != nil {
// return a closed stream
deadStream := make(chan log.Record)
close(deadStream)
return deadStream, stop
}
newStream := make(chan log.Record, 128)
go func() {
for {
select {
case rec := <-stream:
newStream <- rec
case <-stop:
return
}
}
}()
return newStream, stop
func (s *serviceLog) Stream() (log.Stream, error) {
return s.Client.Log(time.Time{}, 0, true)
}
// NewLog returns a new log interface

View File

@@ -27,42 +27,40 @@ func NewClient(name string) *debugClient {
}
}
// Logs queries the service logs and returns a channel to read the logs from
func (d *debugClient) Log(opts ...log.ReadOption) (<-chan log.Record, error) {
var options log.ReadOptions
// initialize the read options
for _, o := range opts {
o(&options)
}
// Logs queries the services logs and returns a channel to read the logs from
func (d *debugClient) Log(since time.Time, count int, stream bool) (log.Stream, error) {
req := &pb.LogRequest{}
if !options.Since.IsZero() {
req.Since = options.Since.Unix()
if !since.IsZero() {
req.Since = since.Unix()
}
if options.Count > 0 {
req.Count = int64(options.Count)
if count > 0 {
req.Count = int64(count)
}
req.Stream = options.Stream
// set whether to stream
req.Stream = stream
// get the log stream
stream, err := d.Client.Log(context.Background(), req)
serverStream, err := d.Client.Log(context.Background(), req)
if err != nil {
return nil, fmt.Errorf("failed getting log stream: %s", err)
}
// log channel for streaming logs
logChan := make(chan log.Record)
lg := &logStream{
stream: make(chan log.Record),
stop: make(chan bool),
}
// go stream logs
go d.streamLogs(logChan, stream)
go d.streamLogs(lg, serverStream)
return logChan, nil
return lg, nil
}
func (d *debugClient) streamLogs(logChan chan log.Record, stream pb.Debug_LogService) {
func (d *debugClient) streamLogs(lg *logStream, stream pb.Debug_LogService) {
defer stream.Close()
defer lg.Stop()
for {
resp, err := stream.Recv()
@@ -81,8 +79,10 @@ func (d *debugClient) streamLogs(logChan chan log.Record, stream pb.Debug_LogSer
Metadata: metadata,
}
logChan <- record
select {
case <-lg.stop:
return
case lg.stream <- record:
}
}
close(logChan)
}

25
debug/service/stream.go Normal file
View File

@@ -0,0 +1,25 @@
package service
import (
"github.com/micro/go-micro/debug/log"
)
type logStream struct {
stream chan log.Record
stop chan bool
}
func (l *logStream) Chan() <-chan log.Record {
return l.stream
}
func (l *logStream) Stop() error {
select {
case <-l.stop:
return nil
default:
close(l.stream)
close(l.stop)
}
return nil
}