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 }