Merge lp:~axwalk/juju-core/lp1166863-debug-logs-all into lp:~go-bot/juju-core/trunk

Proposed by Andrew Wilkins
Status: Merged
Approved by: Andrew Wilkins
Approved revision: no longer in the source branch.
Merged at revision: 1649
Proposed branch: lp:~axwalk/juju-core/lp1166863-debug-logs-all
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 161 lines (+88/-12)
2 files modified
cmd/juju/debuglog.go (+48/-2)
cmd/juju/debuglog_test.go (+40/-10)
To merge this branch: bzr merge lp:~axwalk/juju-core/lp1166863-debug-logs-all
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+178028@code.launchpad.net

Commit message

debug-log: add flag to get last N log lines

Same format as expected by "tail".

Fixes bug 1166863

https://codereview.appspot.com/12241043/

Description of the change

debug-log: add flag to get last N log lines

Same format as expected by "tail".

Fixes bug 1166863

https://codereview.appspot.com/12241043/

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :

Reviewers: mp+178028_code.launchpad.net,

Message:
Please take a look.

Description:
debug-log: add -a/--all to get entire log contents

Fixes bug 1166863

https://code.launchpad.net/~axwalk/juju-core/lp1166863-debug-logs-all/+merge/178028

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/12241043/

Affected files:
   A [revision details]
   M cmd/juju/debuglog.go
   M cmd/juju/debuglog_test.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: tarmac-20130801070802-cgvry3o76nnocyq9
+New revision: <email address hidden>

Index: cmd/juju/debuglog.go
=== modified file 'cmd/juju/debuglog.go'
--- cmd/juju/debuglog.go 2013-05-02 15:55:42 +0000
+++ cmd/juju/debuglog.go 2013-08-01 09:25:00 +0000
@@ -10,7 +10,8 @@

  type DebugLogCommand struct {
   // The debug log command simply invokes juju ssh with the required
arguments.
- sshCmd cmd.Command
+ sshCmd cmd.Command
+ showAll bool
  }

  const debuglogDoc = `
@@ -29,11 +30,19 @@

  func (c *DebugLogCommand) SetFlags(f *gnuflag.FlagSet) {
   c.sshCmd.SetFlags(f)
+ f.BoolVar(&c.showAll, "a", false, "show the complete log file contents")
+ f.BoolVar(&c.showAll, "all", false, "")
  }

  func (c *DebugLogCommand) Init(args []string) error {
- args = append([]string{"0"}, args...)
- args = append(args, "tail -f /var/log/juju/all-machines.log")
+ args = append([]string{"0"}, args...) // machine 0
+ tailcmd := "tail "
+ if c.showAll {
+ // tail starting from line 1
+ tailcmd += "-n +1 "
+ }
+ tailcmd += "-f /var/log/juju/all-machines.log"
+ args = append(args, tailcmd)
   return c.sshCmd.Init(args)
  }

Index: cmd/juju/debuglog_test.go
=== modified file 'cmd/juju/debuglog_test.go'
--- cmd/juju/debuglog_test.go 2013-05-10 20:55:57 +0000
+++ cmd/juju/debuglog_test.go 2013-08-01 09:25:00 +0000
@@ -42,4 +42,11 @@
   c.Assert(debugCmd.runCalled, Equals, true)
   c.Assert(debugCmd.Target, Equals, "0")
   c.Assert([]string{"tail -f /var/log/juju/all-machines.log"}, DeepEquals,
debugCmd.Args)
+
+ debugLogCmd, err = runDebugLog(c, "--all")
+ c.Assert(err, IsNil)
+ debugCmd = debugLogCmd.sshCmd.(*dummySSHCommand)
+ c.Assert(debugCmd.runCalled, Equals, true)
+ c.Assert(debugCmd.Target, Equals, "0")
+ c.Assert([]string{"tail -n +1 -f /var/log/juju/all-machines.log"},
DeepEquals, debugCmd.Args)
  }

Revision history for this message
Ian Booth (wallyworld) wrote :

LGTM with the suggested test change

https://codereview.appspot.com/12241043/diff/1/cmd/juju/debuglog_test.go
File cmd/juju/debuglog_test.go (right):

https://codereview.appspot.com/12241043/diff/1/cmd/juju/debuglog_test.go#newcode52
cmd/juju/debuglog_test.go:52: }
Please split this out to a separate test. A common pattern used is along
the lines of:

func (s *DebugLogSuite) assertDebugLogInvokesSSHCommand(arg, expected
string) {
  defer testing.MakeEmptyFakeHome(c).Restore()
  debugLogCmd, err := runDebugLog(c, arg)
  c.Assert(err, IsNil)
  // etc etc
}

func (s *DebugLogSuite) TestDebugLog(c *C) {
    s.assertDebugLogInvokesSSHCommand("", "........")
}

func (s *DebugLogSuite) TestDebugLogAll(c *C) {
    s.assertDebugLogInvokesSSHCommand("--all", "........")
}

https://codereview.appspot.com/12241043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

https://codereview.appspot.com/12241043/diff/1/cmd/juju/debuglog_test.go
File cmd/juju/debuglog_test.go (right):

https://codereview.appspot.com/12241043/diff/1/cmd/juju/debuglog_test.go#newcode52
cmd/juju/debuglog_test.go:52: }
On 2013/08/01 23:11:28, wallyworld wrote:
> Please split this out to a separate test. A common pattern used is
along the
> lines of:

> func (s *DebugLogSuite) assertDebugLogInvokesSSHCommand(arg, expected
string) {
> defer testing.MakeEmptyFakeHome(c).Restore()
> debugLogCmd, err := runDebugLog(c, arg)
> c.Assert(err, IsNil)
> // etc etc
> }

> func (s *DebugLogSuite) TestDebugLog(c *C) {
> s.assertDebugLogInvokesSSHCommand("", "........")
> }

> func (s *DebugLogSuite) TestDebugLogAll(c *C) {
> s.assertDebugLogInvokesSSHCommand("--all", "........")
> }

Done.

https://codereview.appspot.com/12241043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :
Revision history for this message
William Reade (fwereade) wrote :

Implementation looks good, but I have some concerns. Thoughts?

https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go
File cmd/juju/debuglog.go (right):

https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go#newcode34
cmd/juju/debuglog.go:34: f.BoolVar(&c.showAll, "all", false, "")
Hmm, I'm a little bit uncertain about this behaviour -- the whole debug
log for a large and/or long-lived environment is *not* a dainty thing,
and I'm not sure it's very helpful to expose it here -- if you want
events as they happen you want debug-log, and if you want a complete
record you can just `juju scp`.

What may be useful, I think, is the ability to specify a certain number
of lines of context. Roger, what are your thoughts here? It's your bug,
and maybe I misunderstand your use case, but I'm reluctant to add this
to the interface without a bit more thought.

https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go#newcode38
cmd/juju/debuglog.go:38: args = append([]string{"0"}, args...) //
machine 0
Preexisting behaviour, so not a blocker for this CL, but I'm a bit
twitchy about passing arbitrary command line args through to the SSH
command. Is this something we just have to do across the board? Is there
any way we could kill this with fire, like by offering an
ssh-config-path in the config settings and using that where possible?

https://codereview.appspot.com/12241043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2013/08/02 16:54:39, fwereade wrote:
> Implementation looks good, but I have some concerns. Thoughts?

> https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go
> File cmd/juju/debuglog.go (right):

https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go#newcode34
> cmd/juju/debuglog.go:34: f.BoolVar(&c.showAll, "all", false, "")
> Hmm, I'm a little bit uncertain about this behaviour -- the whole
debug log for
> a large and/or long-lived environment is *not* a dainty thing, and I'm
not sure
> it's very helpful to expose it here -- if you want events as they
happen you
> want debug-log, and if you want a complete record you can just `juju
scp`.

The only difference being that you don't get to follow updates after
that.
The bug report mentions the GUI requiring this, but I don't know what
the
requirements are specifically, so will have to leave it to rogpeppe to
speak up.

> What may be useful, I think, is the ability to specify a certain
number of lines
> of context. Roger, what are your thoughts here? It's your bug, and
maybe I
> misunderstand your use case, but I'm reluctant to add this to the
interface
> without a bit more thought.

https://codereview.appspot.com/12241043/diff/7001/cmd/juju/debuglog.go#newcode38
> cmd/juju/debuglog.go:38: args = append([]string{"0"}, args...) //
machine 0
> Preexisting behaviour, so not a blocker for this CL, but I'm a bit
twitchy about
> passing arbitrary command line args through to the SSH command. Is
this
> something we just have to do across the board? Is there any way we
could kill
> this with fire, like by offering an ssh-config-path in the config
settings and
> using that where possible?

I also this is a bit ugly, as it's exposing the implementation detail of
using SSH.
I'm not sure what you mean by "offering an ssh-config path in the config
settings",
though. Can you please elaborate?

https://codereview.appspot.com/12241043/

Revision history for this message
John A Meinel (jameinel) wrote :

I do think that bug #1166863 is more about having the ability to get the
recent items, rather than the ability to get the entire log file.

Currently we don't rotate the log file, which means the log file gets
*BIG*.

I'm not terribly opposed to having a '-a', but I think a '--recent'
would be more generally useful (tell me what just happened on my
environment). And '--recent 1000' or something like that.

For bonus points, we can just implement '--recent' and pass it through
to 'tail -n' so that we have "--recent +1" as a subtle way of actually
requesting All.

Thoughts?

https://codereview.appspot.com/12241043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2013/08/08 17:11:26, jameinel wrote:
> I do think that bug #1166863 is more about having the ability to get
the recent
> items, rather than the ability to get the entire log file.

> Currently we don't rotate the log file, which means the log file gets
*BIG*.

> I'm not terribly opposed to having a '-a', but I think a '--recent'
would be
> more generally useful (tell me what just happened on my environment).
And
> '--recent 1000' or something like that.

> For bonus points, we can just implement '--recent' and pass it through
to 'tail
> -n' so that we have "--recent +1" as a subtle way of actually
requesting All.

> Thoughts?

SGTM. Mind if we just call it -n/--lines though (same as tail)?

https://codereview.appspot.com/12241043/

Revision history for this message
William Reade (fwereade) wrote :

On 2013/08/09 01:44:04, axw1 wrote:
> On 2013/08/08 17:11:26, jameinel wrote:
> > For bonus points, we can just implement '--recent' and pass it
through to
> 'tail
> > -n' so that we have "--recent +1" as a subtle way of actually
requesting All.
> >
> > Thoughts?

> SGTM. Mind if we just call it -n/--lines though (same as tail)?

-n/--lines SGTM. I'm not really that keen on supporting + but I can't
actually see any serious negative consequences so... go for it, I guess.
But please validate what we pass through, don't just leave it to tail
:).

https://codereview.appspot.com/12241043/

Revision history for this message
Andrew Wilkins (axwalk) wrote :
Revision history for this message
William Reade (fwereade) wrote :

LGTM, thanks

https://codereview.appspot.com/12241043/diff/16001/cmd/juju/debuglog.go
File cmd/juju/debuglog.go (right):

https://codereview.appspot.com/12241043/diff/16001/cmd/juju/debuglog.go#newcode84
cmd/juju/debuglog.go:84: "0", // machine 0
Heh, this is bad, but preexisting... so let's leave it as it is for now
:(.

https://codereview.appspot.com/12241043/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmd/juju/debuglog.go'
2--- cmd/juju/debuglog.go 2013-05-02 15:55:42 +0000
3+++ cmd/juju/debuglog.go 2013-08-13 09:25:16 +0000
4@@ -4,13 +4,55 @@
5 package main
6
7 import (
8+ "fmt"
9+ "strconv"
10+
11 "launchpad.net/gnuflag"
12+
13 "launchpad.net/juju-core/cmd"
14 )
15
16 type DebugLogCommand struct {
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@@ -21,7 +63,6 @@
61 func (c *DebugLogCommand) Info() *cmd.Info {
62 return &cmd.Info{
63 Name: "debug-log",
64- Args: "[<ssh args>...]",
65 Purpose: "display the consolidated log file",
66 Doc: debuglogDoc,
67 }
68@@ -29,11 +70,16 @@
69
70 func (c *DebugLogCommand) SetFlags(f *gnuflag.FlagSet) {
71 c.sshCmd.SetFlags(f)
72+
73+ c.lines = -defaultLineCount
74+ f.Var(&c.lines, "n", "output the last K lines; or use -n +K to output lines starting with the Kth")
75+ f.Var(&c.lines, "lines", "")
76 }
77
78 func (c *DebugLogCommand) Init(args []string) error {
79+ tailcmd := fmt.Sprintf("tail -n %s -f /var/log/juju/all-machines.log", &c.lines)
80 args = append([]string{"0"}, args...)
81- args = append(args, "tail -f /var/log/juju/all-machines.log")
82+ args = append(args, tailcmd)
83 return c.sshCmd.Init(args)
84 }
85
86
87=== modified file 'cmd/juju/debuglog_test.go'
88--- cmd/juju/debuglog_test.go 2013-05-10 20:55:57 +0000
89+++ cmd/juju/debuglog_test.go 2013-08-13 09:25:16 +0000
90@@ -4,7 +4,8 @@
91 package main
92
93 import (
94- . "launchpad.net/gocheck"
95+ gc "launchpad.net/gocheck"
96+
97 "launchpad.net/juju-core/cmd"
98 "launchpad.net/juju-core/testing"
99 )
100@@ -12,9 +13,9 @@
101 type DebugLogSuite struct {
102 }
103
104-var _ = Suite(&DebugLogSuite{})
105+var _ = gc.Suite(&DebugLogSuite{})
106
107-func runDebugLog(c *C, args ...string) (*DebugLogCommand, error) {
108+func runDebugLog(c *gc.C, args ...string) (*DebugLogCommand, error) {
109 cmd := &DebugLogCommand{
110 sshCmd: &dummySSHCommand{},
111 }
112@@ -33,13 +34,42 @@
113 }
114
115 // debug-log is implemented by invoking juju ssh with the correct arguments.
116-// This test checks for the expected invocation.
117-func (s *DebugLogSuite) TestDebugLogInvokesSSHCommand(c *C) {
118+// This test helper checks for the expected invocation.
119+func (s *DebugLogSuite) assertDebugLogInvokesSSHCommand(c *gc.C, expected string, args ...string) {
120 defer testing.MakeEmptyFakeHome(c).Restore()
121- debugLogCmd, err := runDebugLog(c)
122- c.Assert(err, IsNil)
123+ debugLogCmd, err := runDebugLog(c, args...)
124+ c.Assert(err, gc.IsNil)
125 debugCmd := debugLogCmd.sshCmd.(*dummySSHCommand)
126- c.Assert(debugCmd.runCalled, Equals, true)
127- c.Assert(debugCmd.Target, Equals, "0")
128- c.Assert([]string{"tail -f /var/log/juju/all-machines.log"}, DeepEquals, debugCmd.Args)
129+ c.Assert(debugCmd.runCalled, gc.Equals, true)
130+ c.Assert(debugCmd.Target, gc.Equals, "0")
131+ c.Assert([]string{expected}, gc.DeepEquals, debugCmd.Args)
132+}
133+
134+const logLocation = "/var/log/juju/all-machines.log"
135+
136+func (s *DebugLogSuite) TestDebugLog(c *gc.C) {
137+ const expected = "tail -n 10 -f " + logLocation
138+ s.assertDebugLogInvokesSSHCommand(c, expected)
139+}
140+
141+func (s *DebugLogSuite) TestDebugLogFrom(c *gc.C) {
142+ const expected = "tail -n +1 -f " + logLocation
143+ s.assertDebugLogInvokesSSHCommand(c, expected, "-n", "+1")
144+ s.assertDebugLogInvokesSSHCommand(c, expected, "--lines=+1")
145+}
146+
147+func (s *DebugLogSuite) TestDebugLogLast(c *gc.C) {
148+ const expected = "tail -n 100 -f " + logLocation
149+ s.assertDebugLogInvokesSSHCommand(c, expected, "-n", "100")
150+ s.assertDebugLogInvokesSSHCommand(c, expected, "--lines=100")
151+}
152+
153+func (s *DebugLogSuite) TestDebugLogValidation(c *gc.C) {
154+ defer testing.MakeEmptyFakeHome(c).Restore()
155+ _, err := runDebugLog(c, "-n", "0")
156+ c.Assert(err, gc.ErrorMatches, "invalid value \"0\" for flag -n: invalid number of lines")
157+ _, err = runDebugLog(c, "-n", "-1")
158+ c.Assert(err, gc.ErrorMatches, "invalid value \"-1\" for flag -n: invalid number of lines")
159+ _, err = runDebugLog(c, "-n", "fnord")
160+ c.Assert(err, gc.ErrorMatches, "invalid value \"fnord\" for flag -n: invalid number of lines")
161 }

Subscribers

People subscribed via source and target branches

to status/vote changes: