github.com/kjdelisle/consul@v1.4.5/command/monitor/monitor.go (about)

     1  package monitor
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/hashicorp/consul/command/flags"
     9  	"github.com/mitchellh/cli"
    10  )
    11  
    12  // cmd is a Command implementation that queries a running
    13  // Consul agent what members are part of the cluster currently.
    14  type cmd struct {
    15  	UI    cli.Ui
    16  	help  string
    17  	flags *flag.FlagSet
    18  	http  *flags.HTTPFlags
    19  
    20  	shutdownCh <-chan struct{}
    21  
    22  	lock     sync.Mutex
    23  	quitting bool
    24  
    25  	// flags
    26  	logLevel string
    27  }
    28  
    29  func New(ui cli.Ui, shutdownCh <-chan struct{}) *cmd {
    30  	c := &cmd{UI: ui, shutdownCh: shutdownCh}
    31  	c.init()
    32  	return c
    33  }
    34  
    35  func (c *cmd) init() {
    36  	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
    37  	c.flags.StringVar(&c.logLevel, "log-level", "INFO",
    38  		"Log level of the agent.")
    39  
    40  	c.http = &flags.HTTPFlags{}
    41  	flags.Merge(c.flags, c.http.ClientFlags())
    42  	c.help = flags.Usage(help, c.flags)
    43  }
    44  
    45  func (c *cmd) Run(args []string) int {
    46  	if err := c.flags.Parse(args); err != nil {
    47  		return 1
    48  	}
    49  
    50  	client, err := c.http.APIClient()
    51  	if err != nil {
    52  		c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
    53  		return 1
    54  	}
    55  
    56  	eventDoneCh := make(chan struct{})
    57  	logCh, err := client.Agent().Monitor(c.logLevel, eventDoneCh, nil)
    58  	if err != nil {
    59  		c.UI.Error(fmt.Sprintf("Error starting monitor: %s", err))
    60  		return 1
    61  	}
    62  
    63  	go func() {
    64  		defer close(eventDoneCh)
    65  	OUTER:
    66  		for {
    67  			select {
    68  			case log := <-logCh:
    69  				if log == "" {
    70  					break OUTER
    71  				}
    72  				c.UI.Info(log)
    73  			}
    74  		}
    75  
    76  		c.lock.Lock()
    77  		defer c.lock.Unlock()
    78  		if !c.quitting {
    79  			c.UI.Info("")
    80  			c.UI.Output("Remote side ended the monitor! This usually means that the\n" +
    81  				"remote side has exited or crashed.")
    82  		}
    83  	}()
    84  
    85  	select {
    86  	case <-eventDoneCh:
    87  		return 1
    88  	case <-c.shutdownCh:
    89  		c.lock.Lock()
    90  		c.quitting = true
    91  		c.lock.Unlock()
    92  	}
    93  
    94  	return 0
    95  }
    96  
    97  func (c *cmd) Synopsis() string {
    98  	return synopsis
    99  }
   100  
   101  func (c *cmd) Help() string {
   102  	return c.help
   103  }
   104  
   105  const synopsis = "Stream logs from a Consul agent"
   106  const help = `
   107  Usage: consul monitor [options]
   108  
   109    Shows recent log messages of a Consul agent, and attaches to the agent,
   110    outputting log messages as they occur in real time. The monitor lets you
   111    listen for log levels that may be filtered out of the Consul agent. For
   112    example your agent may only be logging at INFO level, but with the monitor
   113    you can see the DEBUG level logs.
   114  `