launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/juju/debuglog.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  	"strconv"
     9  
    10  	"launchpad.net/gnuflag"
    11  
    12  	"launchpad.net/juju-core/cmd"
    13  )
    14  
    15  type DebugLogCommand struct {
    16  	cmd.CommandBase
    17  	// The debug log command simply invokes juju ssh with the required arguments.
    18  	sshCmd cmd.Command
    19  	lines  linesValue
    20  }
    21  
    22  // defaultLineCount is the default number of lines to
    23  // display, from the end of the consolidated log.
    24  const defaultLineCount = 10
    25  
    26  // linesValue implements gnuflag.Value, and represents
    27  // a -n/--lines flag value compatible with "tail".
    28  //
    29  // A negative value (-K) corresponds to --lines=K,
    30  // i.e. the last K lines; a positive value (+K)
    31  // corresponds to --lines=+K, i.e. from line K onwards.
    32  type linesValue int
    33  
    34  func (v *linesValue) String() string {
    35  	if *v > 0 {
    36  		return fmt.Sprintf("+%d", *v)
    37  	}
    38  	return fmt.Sprint(-*v)
    39  }
    40  
    41  func (v *linesValue) Set(value string) error {
    42  	if len(value) > 0 {
    43  		sign := -1
    44  		if value[0] == '+' {
    45  			value = value[1:]
    46  			sign = 1
    47  		}
    48  		n, err := strconv.ParseInt(value, 10, 0)
    49  		if err == nil && n > 0 {
    50  			*v = linesValue(sign * int(n))
    51  			return nil
    52  		}
    53  		// err is quite verbose, and doesn't convey
    54  		// any additional useful information.
    55  	}
    56  	return fmt.Errorf("invalid number of lines")
    57  }
    58  
    59  const debuglogDoc = `
    60  Launch an ssh shell on the state server machine and tail the consolidated log file.
    61  The consolidated log file contains log messages from all nodes in the environment.
    62  `
    63  
    64  func (c *DebugLogCommand) Info() *cmd.Info {
    65  	return &cmd.Info{
    66  		Name:    "debug-log",
    67  		Purpose: "display the consolidated log file",
    68  		Doc:     debuglogDoc,
    69  	}
    70  }
    71  
    72  func (c *DebugLogCommand) SetFlags(f *gnuflag.FlagSet) {
    73  	c.sshCmd.SetFlags(f)
    74  
    75  	c.lines = -defaultLineCount
    76  	f.Var(&c.lines, "n", "output the last K lines; or use -n +K to output lines starting with the Kth")
    77  	f.Var(&c.lines, "lines", "")
    78  }
    79  
    80  func (c *DebugLogCommand) AllowInterspersedFlags() bool {
    81  	return true
    82  }
    83  
    84  func (c *DebugLogCommand) Init(args []string) error {
    85  	tailcmd := fmt.Sprintf("tail -n %s -f /var/log/juju/all-machines.log", &c.lines)
    86  	args = append([]string{"0"}, args...)
    87  	args = append(args, tailcmd)
    88  	return c.sshCmd.Init(args)
    89  }
    90  
    91  // Run uses "juju ssh" to log into the state server node
    92  // and tails the consolidated log file which captures log
    93  // messages from all nodes.
    94  func (c *DebugLogCommand) Run(ctx *cmd.Context) error {
    95  	return c.sshCmd.Run(ctx)
    96  }