github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/logtool/watch.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/Cloud-Foundations/Dominator/lib/errors"
    11  	"github.com/Cloud-Foundations/Dominator/lib/log"
    12  	"github.com/Cloud-Foundations/Dominator/lib/srpc"
    13  	proto "github.com/Cloud-Foundations/Dominator/proto/logger"
    14  )
    15  
    16  func watchSubcommand(args []string, logger log.DebugLogger) error {
    17  	level, err := strconv.ParseInt(args[0], 10, 16)
    18  	if err != nil {
    19  		return fmt.Errorf("Error parsing level: %s", err)
    20  	}
    21  	clients, addrs, err := dial(true)
    22  	if err != nil {
    23  		return err
    24  	}
    25  	if err := watchAll(clients, addrs, int16(level)); err != nil {
    26  		return fmt.Errorf("Error watching: %s", err)
    27  	}
    28  	return nil
    29  }
    30  
    31  func watchAll(clients []*srpc.Client, addrs []string, level int16) error {
    32  	if len(clients) == 1 {
    33  		return watchOne(clients[0], level, "")
    34  	}
    35  	maxWidth := 0
    36  	for _, addr := range addrs {
    37  		if len(addr) > maxWidth {
    38  			maxWidth = len(addr)
    39  		}
    40  	}
    41  	errors := make(chan error, 1)
    42  	for index, client := range clients {
    43  		prefix := addrs[index]
    44  		if len(prefix) < maxWidth {
    45  			prefix += strings.Repeat(" ", maxWidth-len(prefix))
    46  		}
    47  		go func(client *srpc.Client, level int16, prefix string) {
    48  			errors <- watchOne(client, level, prefix)
    49  		}(client, level, prefix)
    50  	}
    51  	for range clients {
    52  		if err := <-errors; err != nil {
    53  			return err
    54  		}
    55  	}
    56  	return nil
    57  }
    58  
    59  func watchOne(client *srpc.Client, level int16, prefix string) error {
    60  	request := proto.WatchRequest{
    61  		ExcludeRegex: *excludeRegex,
    62  		IncludeRegex: *includeRegex,
    63  		Name:         *loggerName,
    64  		DebugLevel:   level,
    65  	}
    66  	if conn, err := client.Call("Logger.Watch"); err != nil {
    67  		return err
    68  	} else {
    69  		defer conn.Close()
    70  		if err := conn.Encode(request); err != nil {
    71  			return err
    72  		}
    73  		if err := conn.Flush(); err != nil {
    74  			return err
    75  		}
    76  		var response proto.WatchResponse
    77  		if err := conn.Decode(&response); err != nil {
    78  			return fmt.Errorf("error decoding: %s", err)
    79  		}
    80  		if response.Error != "" {
    81  			return errors.New(response.Error)
    82  		}
    83  		if prefix == "" {
    84  			_, err := io.Copy(os.Stdout, conn)
    85  			return err
    86  		}
    87  		for {
    88  			line, err := conn.ReadString('\n')
    89  			if len(line) > 0 {
    90  				if prefix != "" {
    91  					line = prefix + " " + line
    92  				}
    93  				if _, err := os.Stdout.Write([]byte(line)); err != nil {
    94  					return err
    95  				}
    96  			}
    97  			if err != nil {
    98  				if err == io.EOF {
    99  					return nil
   100  				}
   101  				return err
   102  			}
   103  		}
   104  	}
   105  }