From 9f2631f383d30771c9c3a66ea884fdc906689748 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Wed, 21 May 2014 12:06:03 -0700 Subject: [PATCH] agent: syslog support. Fixes #105. --- CHANGELOG.md | 1 + command/agent/command.go | 22 ++++++++++++++++++- command/agent/config.go | 7 ++++++ command/agent/config_test.go | 12 ++++++++++ .../source/docs/agent/options.html.markdown | 5 +++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1051ad1e7..e66d190f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ IMPROVEMENTS: * Fixing potential name conflicts on the WAN gossip ring [GH-158] * /v1/catalog/services returns an empty slice instead of null. [GH-145] * `members` command returns exit code 2 if no results. [GH-116] + * Enable logging to syslog. [GH-105] BUG FIXES: diff --git a/command/agent/command.go b/command/agent/command.go index 7f0c2f687..2e516176c 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "github.com/armon/go-metrics" + "github.com/hashicorp/go-syslog" "github.com/hashicorp/logutils" "github.com/mitchellh/cli" "io" @@ -61,6 +62,8 @@ func (c *Command) readConfig() *Config { cmdFlags.IntVar(&cmdConfig.Protocol, "protocol", -1, "protocol version") + cmdFlags.BoolVar(&cmdConfig.EnableSyslog, "syslog", false, + "enable logging to syslog facility") cmdFlags.Var((*AppendSliceValue)(&cmdConfig.StartJoin), "join", "address of agent to join on startup") @@ -141,9 +144,25 @@ func (c *Command) setupLoggers(config *Config) (*GatedWriter, *logWriter, io.Wri return nil, nil, nil } + // Check if syslog is enabled + var syslog io.Writer + if config.EnableSyslog { + l, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, "consul") + if err != nil { + c.Ui.Error(fmt.Sprintf("Syslog setup failed: %v", err)) + return nil, nil, nil + } + syslog = &SyslogWrapper{l} + } + // Create a log writer, and wrap a logOutput around it logWriter := NewLogWriter(512) - logOutput := io.MultiWriter(c.logFilter, logWriter) + var logOutput io.Writer + if syslog != nil { + logOutput = io.MultiWriter(c.logFilter, logWriter, syslog) + } else { + logOutput = io.MultiWriter(c.logFilter, logWriter) + } return logGate, logWriter, logOutput } @@ -489,6 +508,7 @@ Options: -node=hostname Name of this node. Must be unique in the cluster -protocol=N Sets the protocol version. Defaults to latest. -server Switches agent to server mode. + -syslog Enables logging to syslog -ui-dir=path Path to directory containing the Web UI resources -pid-file=path Path to file to store agent PID diff --git a/command/agent/config.go b/command/agent/config.go index 2cb86cde4..eacfcc43e 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -131,6 +131,10 @@ type Config struct { // PidFile is the file to store our PID in PidFile string `mapstructure:"pid_file"` + // EnableSyslog is used to also tee all the logs over to syslog. Only supported + // on linux and OSX. Other platforms will generate an error. + EnableSyslog bool `mapstructure:"enable_syslog"` + // AEInterval controls the anti-entropy interval. This is how often // the agent attempts to reconcile it's local state with the server' // representation of our state. Defaults to every 60s. @@ -429,6 +433,9 @@ func MergeConfig(a, b *Config) *Config { if b.PidFile != "" { result.PidFile = b.PidFile } + if b.EnableSyslog { + result.EnableSyslog = true + } // Copy the start join addresses result.StartJoin = make([]string, 0, len(a.StartJoin)+len(b.StartJoin)) diff --git a/command/agent/config_test.go b/command/agent/config_test.go index e518b7768..e71b5e8e2 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -268,6 +268,17 @@ func TestDecodeConfig(t *testing.T) { if config.PidFile != "/tmp/consul/pid" { t.Fatalf("bad: %#v", config) } + + // Syslog + input = `{"enable_syslog": true}` + config, err = DecodeConfig(bytes.NewReader([]byte(input))) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !config.EnableSyslog { + t.Fatalf("bad: %#v", config) + } } func TestDecodeConfig_Service(t *testing.T) { @@ -400,6 +411,7 @@ func TestMergeConfig(t *testing.T) { Services: []*ServiceDefinition{nil}, StartJoin: []string{"1.1.1.1"}, UiDir: "/opt/consul-ui", + EnableSyslog: true, } c := MergeConfig(a, b) diff --git a/website/source/docs/agent/options.html.markdown b/website/source/docs/agent/options.html.markdown index 1cd445759..ece80457e 100644 --- a/website/source/docs/agent/options.html.markdown +++ b/website/source/docs/agent/options.html.markdown @@ -100,6 +100,9 @@ The options below are all specified on the command-line. participate in a WAN gossip pool with server nodes in other datacenters. Servers act as gateways to other datacenters and forward traffic as appropriate. +* `-syslog` - This flag enables logging to syslog. This is only supported on Linux + and OSX. It will result in an error if provided on Windows. + * `-ui-dir` - This flag provides a the directory containing the Web UI resources for Consul. This must be provided to enable the Web UI. Directory must be readable. @@ -159,6 +162,8 @@ definitions support being updated during a reload. * `advertise_addr` - Equivalent to the `-advertise` command-line flag. +* `enable_syslog` - Equivalent to the `-syslog` command-line flag. + * `ca_file` - This provides a the file path to a PEM encoded certificate authority. The certificate authority is used to check the authenticity of client and server connections with the appropriate `verify_incoming` or `verify_outgoing` flags.