-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
agent: remove leading whitespace from agent log lines #10338
Changes from all commits
e573641
2fc988d
b4b85bd
2261a46
cec8bc8
99956cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
```release-note:bug | ||
agent: fix logging output by removing leading whitespace from every log line | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"context" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"os" | ||
"os/signal" | ||
"path/filepath" | ||
|
@@ -13,31 +14,25 @@ import ( | |
|
||
"github.com/hashicorp/go-checkpoint" | ||
"github.com/hashicorp/go-hclog" | ||
"github.com/mitchellh/cli" | ||
mcli "github.com/mitchellh/cli" | ||
|
||
"github.com/hashicorp/consul/agent" | ||
"github.com/hashicorp/consul/agent/config" | ||
"github.com/hashicorp/consul/command/cli" | ||
"github.com/hashicorp/consul/command/flags" | ||
"github.com/hashicorp/consul/lib" | ||
"github.com/hashicorp/consul/logging" | ||
"github.com/hashicorp/consul/service_os" | ||
consulversion "github.com/hashicorp/consul/version" | ||
) | ||
|
||
func New(ui cli.Ui, revision, version, versionPre, versionHuman string, shutdownCh <-chan struct{}) *cmd { | ||
ui = &cli.PrefixedUi{ | ||
OutputPrefix: "==> ", | ||
InfoPrefix: " ", | ||
ErrorPrefix: "==> ", | ||
Ui: ui, | ||
} | ||
|
||
func New(ui cli.Ui) *cmd { | ||
c := &cmd{ | ||
UI: ui, | ||
revision: revision, | ||
version: version, | ||
versionPrerelease: versionPre, | ||
versionHuman: versionHuman, | ||
shutdownCh: shutdownCh, | ||
ui: ui, | ||
revision: consulversion.GitCommit, | ||
version: consulversion.Version, | ||
versionPrerelease: consulversion.VersionPrerelease, | ||
versionHuman: consulversion.GetHumanVersion(), | ||
flags: flag.NewFlagSet("", flag.ContinueOnError), | ||
} | ||
config.AddFlags(c.flags, &c.configLoadOpts) | ||
|
@@ -50,15 +45,14 @@ func New(ui cli.Ui, revision, version, versionPre, versionHuman string, shutdown | |
// ShutdownCh. If two messages are sent on the ShutdownCh it will forcibly | ||
// exit. | ||
type cmd struct { | ||
UI cli.Ui | ||
ui cli.Ui | ||
flags *flag.FlagSet | ||
http *flags.HTTPFlags | ||
help string | ||
revision string | ||
version string | ||
versionPrerelease string | ||
versionHuman string | ||
shutdownCh <-chan struct{} | ||
configLoadOpts config.LoadOpts | ||
logger hclog.InterceptLogger | ||
} | ||
|
@@ -119,7 +113,7 @@ func (c *cmd) startupJoin(agent *agent.Agent, cfg *config.RuntimeConfig) error { | |
return nil | ||
} | ||
|
||
c.UI.Output("Joining cluster...") | ||
c.logger.Info("Joining cluster") | ||
n, err := agent.JoinLAN(cfg.StartJoinAddrsLAN) | ||
if err != nil { | ||
return err | ||
|
@@ -135,75 +129,83 @@ func (c *cmd) startupJoinWan(agent *agent.Agent, cfg *config.RuntimeConfig) erro | |
return nil | ||
} | ||
|
||
c.UI.Output("Joining -wan cluster...") | ||
c.logger.Info("Joining wan cluster") | ||
n, err := agent.JoinWAN(cfg.StartJoinAddrsWAN) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
c.logger.Info("Join -wan completed. Initial agents synced with", "agent_count", n) | ||
c.logger.Info("Join wan completed. Initial agents synced with", "agent_count", n) | ||
return nil | ||
} | ||
|
||
func (c *cmd) run(args []string) int { | ||
ui := &mcli.PrefixedUi{ | ||
OutputPrefix: "==> ", | ||
InfoPrefix: " ", | ||
ErrorPrefix: "==> ", | ||
Ui: c.ui, | ||
} | ||
|
||
if err := c.flags.Parse(args); err != nil { | ||
if !strings.Contains(err.Error(), "help requested") { | ||
c.UI.Error(fmt.Sprintf("error parsing flags: %v", err)) | ||
ui.Error(fmt.Sprintf("error parsing flags: %v", err)) | ||
} | ||
return 1 | ||
} | ||
if len(c.flags.Args()) > 0 { | ||
c.UI.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args())) | ||
ui.Error(fmt.Sprintf("Unexpected extra arguments: %v", c.flags.Args())) | ||
return 1 | ||
} | ||
|
||
logGate := &logging.GatedWriter{Writer: &cli.UiWriter{Ui: c.UI}} | ||
// FIXME: logs should always go to stderr, but previously they were sent to | ||
// stdout, so continue to use Stdout for now, and fix this in a future release. | ||
logGate := &logging.GatedWriter{Writer: c.ui.Stdout()} | ||
Comment on lines
+161
to
+163
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the fix for the primary issue, but other changes were required to make this possible. |
||
loader := func(source config.Source) (config.LoadResult, error) { | ||
c.configLoadOpts.DefaultConfig = source | ||
return config.Load(c.configLoadOpts) | ||
} | ||
bd, err := agent.NewBaseDeps(loader, logGate) | ||
if err != nil { | ||
c.UI.Error(err.Error()) | ||
ui.Error(err.Error()) | ||
return 1 | ||
} | ||
|
||
c.logger = bd.Logger | ||
agent, err := agent.New(bd) | ||
if err != nil { | ||
c.UI.Error(err.Error()) | ||
ui.Error(err.Error()) | ||
return 1 | ||
} | ||
|
||
config := bd.RuntimeConfig | ||
|
||
// Setup gate to check if we should output CLI information | ||
cli := GatedUi{ | ||
JSONoutput: config.Logging.LogJSON, | ||
ui: c.UI, | ||
if config.Logging.LogJSON { | ||
// Hide all non-error output when JSON logging is enabled. | ||
ui.Ui = &cli.BasicUI{ | ||
BasicUi: mcli.BasicUi{ErrorWriter: c.ui.Stderr(), Writer: io.Discard}, | ||
} | ||
} | ||
|
||
// Create the agent | ||
cli.output("Starting Consul agent...") | ||
ui.Output("Starting Consul agent...") | ||
|
||
segment := config.SegmentName | ||
if config.ServerMode { | ||
segment = "<all>" | ||
} | ||
cli.info(fmt.Sprintf(" Version: '%s'", c.versionHuman)) | ||
cli.info(fmt.Sprintf(" Node ID: '%s'", config.NodeID)) | ||
cli.info(fmt.Sprintf(" Node name: '%s'", config.NodeName)) | ||
cli.info(fmt.Sprintf(" Datacenter: '%s' (Segment: '%s')", config.Datacenter, segment)) | ||
cli.info(fmt.Sprintf(" Server: %v (Bootstrap: %v)", config.ServerMode, config.Bootstrap)) | ||
cli.info(fmt.Sprintf(" Client Addr: %v (HTTP: %d, HTTPS: %d, gRPC: %d, DNS: %d)", config.ClientAddrs, | ||
ui.Info(fmt.Sprintf(" Version: '%s'", c.versionHuman)) | ||
ui.Info(fmt.Sprintf(" Node ID: '%s'", config.NodeID)) | ||
ui.Info(fmt.Sprintf(" Node name: '%s'", config.NodeName)) | ||
ui.Info(fmt.Sprintf(" Datacenter: '%s' (Segment: '%s')", config.Datacenter, segment)) | ||
ui.Info(fmt.Sprintf(" Server: %v (Bootstrap: %v)", config.ServerMode, config.Bootstrap)) | ||
ui.Info(fmt.Sprintf(" Client Addr: %v (HTTP: %d, HTTPS: %d, gRPC: %d, DNS: %d)", config.ClientAddrs, | ||
config.HTTPPort, config.HTTPSPort, config.GRPCPort, config.DNSPort)) | ||
cli.info(fmt.Sprintf(" Cluster Addr: %v (LAN: %d, WAN: %d)", config.AdvertiseAddrLAN, | ||
ui.Info(fmt.Sprintf(" Cluster Addr: %v (LAN: %d, WAN: %d)", config.AdvertiseAddrLAN, | ||
config.SerfPortLAN, config.SerfPortWAN)) | ||
cli.info(fmt.Sprintf(" Encrypt: Gossip: %v, TLS-Outgoing: %v, TLS-Incoming: %v, Auto-Encrypt-TLS: %t", | ||
ui.Info(fmt.Sprintf(" Encrypt: Gossip: %v, TLS-Outgoing: %v, TLS-Incoming: %v, Auto-Encrypt-TLS: %t", | ||
config.EncryptKey != "", config.VerifyOutgoing, config.VerifyIncoming, config.AutoEncryptTLS || config.AutoEncryptAllowTLS)) | ||
// Enable log streaming | ||
cli.output("") | ||
cli.output("Log data will now stream in as it occurs:\n") | ||
ui.Output("") | ||
ui.Output("Log data will now stream in as it occurs:\n") | ||
logGate.Flush() | ||
|
||
// wait for signal | ||
|
@@ -256,19 +258,19 @@ func (c *cmd) run(args []string) int { | |
} | ||
|
||
if err := c.startupJoin(agent, config); err != nil { | ||
c.logger.Error((err.Error())) | ||
c.logger.Error(err.Error()) | ||
return 1 | ||
} | ||
|
||
if err := c.startupJoinWan(agent, config); err != nil { | ||
c.logger.Error((err.Error())) | ||
c.logger.Error(err.Error()) | ||
return 1 | ||
} | ||
|
||
// Let the agent know we've finished registration | ||
agent.StartSync() | ||
|
||
cli.output("Consul agent running!") | ||
c.logger.Info("Consul agent running!") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This also changed to use the logger (as mentioned in the commit message). Previously this was leading to very odd looking output, where the log lines were broken up by a random With this change the message will be included in the logs when json logs are enabled. |
||
|
||
// wait for signal | ||
signalCh = make(chan os.Signal, 10) | ||
|
@@ -281,8 +283,6 @@ func (c *cmd) run(args []string) int { | |
sig = s | ||
case <-service_os.Shutdown_Channel(): | ||
sig = os.Interrupt | ||
case <-c.shutdownCh: | ||
sig = os.Interrupt | ||
Comment on lines
-284
to
-285
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was removed because it did nothing (the channel was never closed), and we already have a case for handling signals. |
||
case err := <-agent.RetryJoinCh(): | ||
c.logger.Error("Retry join failed", "error", err) | ||
return 1 | ||
|
@@ -341,23 +341,6 @@ func (c *cmd) run(args []string) int { | |
} | ||
} | ||
|
||
type GatedUi struct { | ||
JSONoutput bool | ||
ui cli.Ui | ||
} | ||
|
||
func (g *GatedUi) output(s string) { | ||
if !g.JSONoutput { | ||
g.ui.Output(s) | ||
} | ||
} | ||
|
||
func (g *GatedUi) info(s string) { | ||
if !g.JSONoutput { | ||
g.ui.Info(s) | ||
} | ||
} | ||
|
||
func (c *cmd) Synopsis() string { | ||
return synopsis | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package cli | ||
|
||
import ( | ||
"io" | ||
|
||
mcli "github.com/mitchellh/cli" | ||
) | ||
|
||
// Ui implements the mitchellh/cli.Ui interface, while exposing the underlying | ||
// io.Writer used for stdout and stderr. | ||
// TODO: rename to UI to match golang style guide | ||
type Ui interface { | ||
mcli.Ui | ||
Stdout() io.Writer | ||
Stderr() io.Writer | ||
} | ||
|
||
// BasicUI augments mitchellh/cli.BasicUi by exposing the underlying io.Writer. | ||
type BasicUI struct { | ||
mcli.BasicUi | ||
} | ||
|
||
func (b *BasicUI) Stdout() io.Writer { | ||
return b.BasicUi.Writer | ||
} | ||
|
||
func (b *BasicUI) Stderr() io.Writer { | ||
return b.BasicUi.ErrorWriter | ||
} | ||
|
||
// Command is an alias to reduce the diff. It can be removed at any time. | ||
type Command mcli.Command |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change to use a logger (and mentioned in the commit message). Using the logger for this seems much better, that way the output is not lost when json logging is enabled.
Same below.