Skip to content

Commit

Permalink
Make logging requests configurable
Browse files Browse the repository at this point in the history
not requiring the app logging level to be set to TRACE
and with configurable log address (stdout/stderr/syslog etc.)
  • Loading branch information
Greg Dubicki committed May 20, 2020
1 parent f8963ae commit c5ec9df
Show file tree
Hide file tree
Showing 14 changed files with 87 additions and 23 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ Usage of ./haproxy-consul-connect:
-http-addr string
Consul agent address (default "127.0.0.1:8500")
-log-level string
Log level (default "INFO")
This app log level (default "INFO")
-log-requests
Enable logging requests by HAproxy
-log-address
Haproxy logs address (default: stderr with this app logs)
-sidecar-for string
The consul service id to proxy
-sidecar-for-tag string
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/haproxytech/haproxy-consul-connect
go 1.13

require (
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/criteo/haproxy-spoe-go v0.0.0-20190925130734-97891c13d324
github.com/d4l3k/messagediff v1.2.1 // indirect
github.com/facebookgo/freeport v0.0.0-20150612182905-d4adf43b75b9
Expand Down
3 changes: 1 addition & 2 deletions haproxy/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ global
tune.ssl.default-dh-param 1024
nbproc 1
nbthread {{.NbThread}}
log-tag haproxy_sidecar
userlist controller
user {{.DataplaneUser}} insecure-password {{.DataplanePass}}
Expand Down Expand Up @@ -57,7 +58,6 @@ type baseParams struct {
SocketPath string
DataplaneUser string
DataplanePass string
LogsPath string
}

type haConfig struct {
Expand Down Expand Up @@ -113,7 +113,6 @@ func newHaConfig(baseDir string, sd *lib.Shutdown) (*haConfig, error) {
err = tmpl.Execute(cfgFile, baseParams{
NbThread: runtime.GOMAXPROCS(0),
SocketPath: cfg.StatsSock,
LogsPath: cfg.LogsSock,
DataplaneUser: dataplaneUser,
DataplanePass: dataplanePass,
})
Expand Down
7 changes: 6 additions & 1 deletion haproxy/haproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ func (h *HAProxy) start(sd *lib.Shutdown) error {
}
h.haConfig = hc

if h.opts.LogRequests {
if h.opts.LogAddress == "" {
err := h.startLogger()
if err != nil {
return err
}
} else {
log.Infof("not starting built-in syslog - using %s as syslog address", h.opts.LogAddress)
}

if h.opts.EnableIntentions {
Expand All @@ -77,6 +79,7 @@ func (h *HAProxy) start(sd *lib.Shutdown) error {
dpc, err := haproxy_cmd.Start(sd, haproxy_cmd.Config{
HAProxyPath: h.opts.HAProxyBin,
HAProxyConfigPath: hc.HAProxy,
HAProxyLogWithThisApp: h.opts.LogAddress == "",
DataplanePath: h.opts.DataplaneBin,
DataplaneTransactionDir: hc.DataplaneTransactionDir,
DataplaneSock: hc.DataplaneSock,
Expand Down Expand Up @@ -112,6 +115,8 @@ func (h *HAProxy) startLogger() error {
}
}(channel)

log.Infof("starting built-in syslog server at %s", h.haConfig.LogsSock)

return nil
}

Expand Down
6 changes: 4 additions & 2 deletions haproxy/haproxy_cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import (
log "github.com/sirupsen/logrus"
)

func runCommand(sd *lib.Shutdown, cmdPath string, args ...string) (*exec.Cmd, error) {
func runCommand(sd *lib.Shutdown, cmdPath string, logPrefix string, logWithThisApp bool, args ...string) (*exec.Cmd, error) {
_, file := path.Split(cmdPath)
cmd := exec.Command(cmdPath, args...)
halog.Cmd("haproxy", cmd)
if logWithThisApp {
halog.Cmd(logPrefix, cmd)
}

sd.Add(1)
err := cmd.Start()
Expand Down
4 changes: 2 additions & 2 deletions haproxy/haproxy_cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import (
func Test_runCommand_ok(t *testing.T) {
t.Parallel()
sd := lib.NewShutdown()
cmd, err := runCommand(sd, "ls", ".")
cmd, err := runCommand(sd, "ls", "foobar", true, ".")
require.NoError(t, err)
cmd.Wait()
}

func Test_runCommand_nok_wrong_path(t *testing.T) {
t.Parallel()
sd := lib.NewShutdown()
cmd, err := runCommand(sd, "/path/to/nowhere/that/can/be/found/myExec", "--help")
cmd, err := runCommand(sd, "/path/to/nowhere/that/can/be/found/myExec", "foobar", true, "--help")
require.NotNil(t, err)
require.Contains(t, err.Error(), "no such file or directory")
require.Nil(t, cmd)
Expand Down
5 changes: 5 additions & 0 deletions haproxy/haproxy_cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
type Config struct {
HAProxyPath string
HAProxyConfigPath string
HAProxyLogWithThisApp bool
DataplanePath string
DataplaneTransactionDir string
DataplaneSock string
Expand All @@ -35,6 +36,8 @@ type Config struct {
func Start(sd *lib.Shutdown, cfg Config) (*dataplane.Dataplane, error) {
haCmd, err := runCommand(sd,
cfg.HAProxyPath,
"haproxy",
cfg.HAProxyLogWithThisApp,
"-f",
cfg.HAProxyConfigPath,
)
Expand All @@ -47,6 +50,8 @@ func Start(sd *lib.Shutdown, cfg Config) (*dataplane.Dataplane, error) {

cmd, err := runCommand(sd,
cfg.DataplanePath,
"dataplaneapi",
true,
"--scheme", "unix",
"--socket-path", cfg.DataplaneSock,
"--haproxy-bin", cfg.HAProxyPath,
Expand Down
1 change: 1 addition & 0 deletions haproxy/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ type Options struct {
StatsListenAddr string
StatsRegisterService bool
LogRequests bool
LogAddress string
}
7 changes: 6 additions & 1 deletion haproxy/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,15 @@ func (h *HAProxy) watch(sd *lib.Shutdown) error {

newConsulCfg := nextState.Load().(consul.Config)

logAddress := h.haConfig.LogsSock
if h.opts.LogAddress != "" {
logAddress = h.opts.LogAddress
}

newState, err := state.Generate(state.Options{
EnableIntentions: h.opts.EnableIntentions,
LogRequests: h.opts.LogRequests,
LogSocket: h.haConfig.LogsSock,
LogAddress: logAddress,
SPOEConfigPath: h.haConfig.SPOE,
SPOESocket: h.haConfig.SPOESock,
}, h.haConfig, currentState, newConsulCfg)
Expand Down
8 changes: 4 additions & 4 deletions haproxy/state/downstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ func generateDownstream(opts Options, certStore CertificateStore, cfg consul.Dow
}

// Logging
if opts.LogRequests && opts.LogSocket != "" {
if opts.LogRequests {
fe.LogTarget = &models.LogTarget{
ID: int64p(0),
Address: opts.LogSocket,
Address: opts.LogAddress,
Facility: models.LogTargetFacilityLocal0,
Format: models.LogTargetFormatRfc5424,
}
Expand Down Expand Up @@ -100,10 +100,10 @@ func generateDownstream(opts Options, certStore CertificateStore, cfg consul.Dow
}

// Logging
if opts.LogRequests && opts.LogSocket != "" {
if opts.LogRequests {
be.LogTarget = &models.LogTarget{
ID: int64p(0),
Address: opts.LogSocket,
Address: opts.LogAddress,
Facility: models.LogTargetFacilityLocal0,
Format: models.LogTargetFormatRfc5424,
}
Expand Down
2 changes: 1 addition & 1 deletion haproxy/state/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func GetTestHAConfig(baseCfg string) State {
var TestOpts = Options{
EnableIntentions: true,
LogRequests: true,
LogSocket: "//logs.sock",
LogAddress: "//logs.sock",
SPOEConfigPath: "//spoe",
}

Expand Down
2 changes: 1 addition & 1 deletion haproxy/state/states.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type Options struct {
EnableIntentions bool
LogRequests bool
LogSocket string
LogAddress string
SPOEConfigPath string
SPOESocket string
}
Expand Down
8 changes: 4 additions & 4 deletions haproxy/state/upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ func generateUpstream(opts Options, certStore CertificateStore, cfg consul.Upstr
Port: &fePort64,
},
}
if opts.LogRequests && opts.LogSocket != "" {
if opts.LogRequests && opts.LogAddress != "" {
fe.LogTarget = &models.LogTarget{
ID: int64p(0),
Address: opts.LogSocket,
Address: opts.LogAddress,
Facility: models.LogTargetFacilityLocal0,
Format: models.LogTargetFormatRfc5424,
}
Expand All @@ -56,10 +56,10 @@ func generateUpstream(opts Options, certStore CertificateStore, cfg consul.Upstr
Mode: beMode,
},
}
if opts.LogRequests && opts.LogSocket != "" {
if opts.LogRequests && opts.LogAddress != "" {
be.LogTarget = &models.LogTarget{
ID: int64p(0),
Address: opts.LogSocket,
Address: opts.LogAddress,
Facility: models.LogTargetFacilityLocal0,
Format: models.LogTargetFormatRfc5424,
}
Expand Down
49 changes: 46 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package main

import (
"errors"
"flag"
"fmt"
"net"
"os"
"strings"

"github.com/asaskevich/govalidator"
log "github.com/sirupsen/logrus"

haproxy "github.com/haproxytech/haproxy-consul-connect/haproxy"
"github.com/haproxytech/haproxy-consul-connect/haproxy"
"github.com/haproxytech/haproxy-consul-connect/haproxy/haproxy_cmd"
"github.com/haproxytech/haproxy-consul-connect/lib"

Expand Down Expand Up @@ -40,7 +43,7 @@ func (consulLogger) Infof(format string, args ...interface{}) {

// Warnf Display warning message
func (consulLogger) Warnf(format string, args ...interface{}) {
log.Infof(format, args...)
log.Warnf(format, args...)
}

// Errorf Display error message
Expand All @@ -59,9 +62,41 @@ func validateRequirements(dataplaneBin, haproxyBin string) error {
return nil
}

func validateLogAddress(logAddress string) error {
fi, err := os.Stat(logAddress)
if err != nil {
// maybe it's a syslog host[:port]
if len(strings.Split(logAddress, ":")) == 1 {
// only host - default syslog port is 514 UDP
logAddress += ":514"
}
if govalidator.IsDialString(logAddress) {
conn, err := net.Dial("udp", logAddress)
if err != nil {
return errors.New(fmt.Sprintf("cannot open %s as syslog", logAddress))
}
_, err = conn.Write([]byte("syslog test\n"))
if err != nil {
return errors.New(fmt.Sprintf("cannot send data to %s as syslog", logAddress))
}
defer conn.Close()
} else {
return errors.New(fmt.Sprintf("%s should be either syslog host[:port] or a socket", logAddress))
}
} else {
// maybe it's a socket
if fi.Mode()&os.ModeSocket == 0 {
return errors.New(fmt.Sprintf("%s is a file but not a socket", logAddress))
}
}
return nil
}

func main() {
versionFlag := flag.Bool("version", false, "Show version and exit")
logLevel := flag.String("log-level", "INFO", "Log level")
logRequests := flag.Bool("log-requests", false, "Enable logging requests by Haproxy")
logAddress := flag.String("log-address", "", "Syslog address for Haproxy logs (default: log to stderr with this app)")
consulAddr := flag.String("http-addr", "127.0.0.1:8500", "Consul agent address")
service := flag.String("sidecar-for", "", "The consul service id to proxy")
serviceTag := flag.String("sidecar-for-tag", "", "The consul service id to proxy")
Expand Down Expand Up @@ -89,6 +124,13 @@ func main() {
}
log.SetLevel(ll)

if *logAddress != "" {
err := validateLogAddress(*logAddress)
if err != nil {
log.Fatal(err)
}
}

sd := lib.NewShutdown()

consulConfig := &api.Config{
Expand Down Expand Up @@ -144,7 +186,8 @@ func main() {
EnableIntentions: *enableIntentions,
StatsListenAddr: *statsListenAddr,
StatsRegisterService: *statsServiceRegister,
LogRequests: ll == log.TraceLevel,
LogRequests: *logRequests,
LogAddress: *logAddress,
})
sd.Add(1)
go func() {
Expand Down

0 comments on commit c5ec9df

Please sign in to comment.