Skip to content

Commit 06c5fd3

Browse files
committed
openshift-install: log debug output to file
This changes the logging strategy so that it logs all output to a local file in addition to logging at the desired level to the console. Unfortunately, logrus doesn't have a facility for capturing all log entries (the hooks are only fired for entries which are at or below the specified level) so this disables the console output and sets up two hooks: one for the console and one for the local file.
1 parent 0600ff7 commit 06c5fd3

File tree

6 files changed

+111
-7
lines changed

6 files changed

+111
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
bin/
2+
.openshift-install.log

cmd/openshift-install/create.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ func newCreateCmd() *cobra.Command {
133133

134134
func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args []string) error {
135135
return func(cmd *cobra.Command, args []string) error {
136+
cleanup, err := setupFileHook(rootOpts.dir)
137+
if err != nil {
138+
return errors.Wrap(err, "failed to setup logging hook")
139+
}
140+
defer cleanup()
141+
136142
assetStore, err := asset.NewStore(rootOpts.dir)
137143
if err != nil {
138144
return errors.Wrapf(err, "failed to create asset store")
@@ -167,6 +173,12 @@ func runTargetCmd(targets ...asset.WritableAsset) func(cmd *cobra.Command, args
167173
// FIXME: pulling the kubeconfig and metadata out of the root
168174
// directory is a bit cludgy when we already have them in memory.
169175
func destroyBootstrap(ctx context.Context, directory string) (err error) {
176+
cleanup, err := setupFileHook(rootOpts.dir)
177+
if err != nil {
178+
return errors.Wrap(err, "failed to setup logging hook")
179+
}
180+
defer cleanup()
181+
170182
logrus.Info("Waiting for bootstrap completion...")
171183
config, err := clientcmd.BuildConfigFromFlags("", filepath.Join(directory, "auth", "kubeconfig"))
172184
if err != nil {

cmd/openshift-install/destroy.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,18 @@ func newDestroyClusterCmd() *cobra.Command {
4343
}
4444

4545
func runDestroyCmd(cmd *cobra.Command, args []string) error {
46+
cleanup, err := setupFileHook(rootOpts.dir)
47+
if err != nil {
48+
return errors.Wrap(err, "failed to setup logging hook")
49+
}
50+
defer cleanup()
51+
4652
destroyer, err := destroy.New(logrus.StandardLogger(), rootOpts.dir)
4753
if err != nil {
4854
return errors.Wrap(err, "Failed while preparing to destroy cluster")
4955
}
5056
if err := destroyer.Run(); err != nil {
5157
return errors.Wrap(err, "Failed to destroy cluster")
52-
5358
}
5459

5560
store, err := asset.NewStore(rootOpts.dir)

cmd/openshift-install/log.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/pkg/errors"
9+
"github.com/sirupsen/logrus"
10+
)
11+
12+
type fileHook struct {
13+
file io.Writer
14+
formatter logrus.Formatter
15+
level logrus.Level
16+
}
17+
18+
func newFileHook(file io.Writer, level logrus.Level, formatter logrus.Formatter) *fileHook {
19+
return &fileHook{
20+
file: file,
21+
formatter: formatter,
22+
level: level,
23+
}
24+
}
25+
26+
func (h fileHook) Levels() []logrus.Level {
27+
var levels []logrus.Level
28+
for _, level := range logrus.AllLevels {
29+
if level <= h.level {
30+
levels = append(levels, level)
31+
}
32+
}
33+
34+
return levels
35+
}
36+
37+
func (h *fileHook) Fire(entry *logrus.Entry) error {
38+
line, err := h.formatter.Format(entry)
39+
if err != nil {
40+
return err
41+
}
42+
43+
_, err = h.file.Write(line)
44+
return err
45+
}
46+
47+
func setupFileHook(baseDir string) (func(), error) {
48+
if err := os.MkdirAll(baseDir, 0755); err != nil {
49+
return nil, errors.Wrap(err, "failed to create base directory for logs")
50+
}
51+
52+
logfile, err := os.OpenFile(filepath.Join(baseDir, ".openshift_install.log"), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
53+
if err != nil {
54+
return nil, errors.Wrap(err, "failed to open log file")
55+
}
56+
57+
originalHooks := logrus.LevelHooks{}
58+
for k, v := range logrus.StandardLogger().Hooks {
59+
originalHooks[k] = v
60+
}
61+
logrus.AddHook(newFileHook(logfile, logrus.TraceLevel, &logrus.TextFormatter{
62+
DisableColors: true,
63+
DisableTimestamp: false,
64+
FullTimestamp: true,
65+
DisableLevelTruncation: false,
66+
}))
67+
68+
return func() {
69+
logfile.Close()
70+
logrus.StandardLogger().ReplaceHooks(originalHooks)
71+
}, nil
72+
}

cmd/openshift-install/main.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package main
22

33
import (
4+
"io/ioutil"
5+
"os"
6+
47
"github.com/pkg/errors"
58
"github.com/sirupsen/logrus"
69
"github.com/spf13/cobra"
10+
"golang.org/x/crypto/ssh/terminal"
711
)
812

913
var (
@@ -50,14 +54,24 @@ func newRootCmd() *cobra.Command {
5054
}
5155

5256
func runRootCmd(cmd *cobra.Command, args []string) error {
53-
logrus.SetFormatter(&logrus.TextFormatter{
54-
DisableTimestamp: true,
55-
DisableLevelTruncation: true,
56-
})
57+
logrus.SetOutput(ioutil.Discard)
58+
logrus.SetLevel(logrus.TraceLevel)
59+
5760
level, err := logrus.ParseLevel(rootOpts.logLevel)
5861
if err != nil {
5962
return errors.Wrap(err, "invalid log-level")
6063
}
61-
logrus.SetLevel(level)
64+
65+
logrus.AddHook(newFileHook(os.Stderr, level, &logrus.TextFormatter{
66+
// Setting ForceColors is necessary because logrus.TextFormatter determines
67+
// whether or not to enable colors by looking at the output of the logger.
68+
// In this case, the output is ioutil.Discard, which is not a terminal.
69+
// Overriding it here allows the same check to be done, but against the
70+
// hook's output instead of the logger's output.
71+
ForceColors: terminal.IsTerminal(int(os.Stderr.Fd())),
72+
DisableTimestamp: true,
73+
DisableLevelTruncation: true,
74+
}))
75+
6276
return nil
6377
}

docs/user/troubleshooting.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ This is safe to ignore and merely indicates that the etcd bootstrapping is still
8888

8989
### Installer Fails to Create Resources
9090

91-
The easiest way to get more debugging information from the installer is to increase the logging level. This can be done by adding `--log-level=debug` to the command line arguments. Of course, this cannot be retroactively applied, so it won't help to debug an installation that has already failed. The installation will have to be attempted again.
91+
The easiest way to get more debugging information from the installer is to check the log file (`.openshift-install.log`) in the install directory. Regardless of the logging level specified, the installer will write its logs in case they need to be inspected retroactively.
9292

9393
## Generic Troubleshooting
9494

0 commit comments

Comments
 (0)