Skip to content

Commit

Permalink
Consul logging wrapper (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sotirios Mantziaris authored Aug 12, 2020
1 parent 8a39391 commit 35cab1c
Show file tree
Hide file tree
Showing 14 changed files with 211 additions and 40 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
name: Running CI
on: [pull_request]
on:
push:
branches:
- master
pull_request:
jobs:
build:
name: CI
Expand Down
3 changes: 2 additions & 1 deletion change/change.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package change supports change management of config values.
package change

import "github.com/beatlabs/harvester/config"
Expand All @@ -11,7 +12,7 @@ type Change struct {
}

// New constructor.
func New(src config.Source, key string, value string, version uint64) *Change {
func New(src config.Source, key, value string, version uint64) *Change {
return &Change{src: src, key: key, value: value, version: version}
}

Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package config handles config struct parsing.
package config

import (
Expand Down
2 changes: 2 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package harvester is a configuration library which helps setting up and monitoring configuration values in order to dynamically reconfigure your application.
package harvester
4 changes: 2 additions & 2 deletions harvester.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func (b *Builder) WithConsulSeed(addr, dataCenter, token string, timeout time.Du
return b
}

// WithConsulMonitor enables support for monitoring key/prefixes on Consul. It automatically parses the config
// and monitors every field found tagged with Consul.
// WithConsulMonitor enables support for monitoring key/prefixes on ConsulLogger. It automatically parses the config
// and monitors every field found tagged with ConsulLogger.
func (b *Builder) WithConsulMonitor(addr, dc, token string, timeout time.Duration) *Builder {
if b.err != nil {
return b
Expand Down
106 changes: 106 additions & 0 deletions log/consul.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package log

import (
"io"
"log"
"os"

hclog "github.com/hashicorp/go-hclog"
)

var consulLog = &consul{}

// ConsulLogger return a consul compatible logger.
func ConsulLogger() hclog.Logger {
return consulLog
}

type consul struct {
}

func (l consul) Log(level hclog.Level, msg string, args ...interface{}) {
switch level {
case hclog.NoLevel:
case hclog.Trace:
debugf(msg, args)
case hclog.Debug:
debugf(msg, args)
case hclog.Info:
infof(msg, args)
case hclog.Warn:
warnf(msg, args)
case hclog.Error:
errorf(msg, args)
}
}

func (l consul) Trace(msg string, args ...interface{}) {
debugf(msg, args)
}

func (l consul) Debug(msg string, args ...interface{}) {
debugf(msg, args)
}

func (l consul) Info(msg string, args ...interface{}) {
infof(msg, args)
}

func (l consul) Warn(msg string, args ...interface{}) {
warnf(msg, args)
}

func (l consul) Error(msg string, args ...interface{}) {
errorf(msg, args)
}

func (l consul) IsTrace() bool {
return true
}

func (l consul) IsDebug() bool {
return true
}

func (l consul) IsInfo() bool {
return true
}

func (l consul) IsWarn() bool {
return true
}

func (l consul) IsError() bool {
return true
}

func (l consul) ImpliedArgs() []interface{} {
return []interface{}{}
}

func (l consul) With(_ ...interface{}) hclog.Logger {
return consulLog
}

func (l consul) Name() string {
return "consul"
}

func (l consul) Named(_ string) hclog.Logger {
return consulLog
}

func (l consul) ResetNamed(_ string) hclog.Logger {
return consulLog
}

func (l consul) SetLevel(_ hclog.Level) {
}

func (l consul) StandardLogger(_ *hclog.StandardLoggerOptions) *log.Logger {
return log.New(os.Stderr, "", log.LstdFlags)
}

func (l consul) StandardWriter(_ *hclog.StandardLoggerOptions) io.Writer {
return os.Stderr
}
67 changes: 67 additions & 0 deletions log/consul_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package log

import (
"bytes"
"log"
"os"
"testing"

hclog "github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/assert"
)

func TestConsul(t *testing.T) {
var buf bytes.Buffer
log.SetOutput(&buf)

logger := ConsulLogger()

t.Run("Level", func(t *testing.T) {
logger.Log(hclog.Warn, "TEST: %d", 123)
assert.Contains(t, buf.String(), "WARN: TEST: [123]")
buf.Reset()
})

t.Run("Trace", func(t *testing.T) {
logger.Trace("TEST: %d", 123)
assert.Contains(t, buf.String(), "DEBUG: TEST: [123]")
buf.Reset()
})

t.Run("Debug", func(t *testing.T) {
logger.Debug("TEST: %d", 123)
assert.Contains(t, buf.String(), "DEBUG: TEST: [123]")
buf.Reset()
})

t.Run("Info", func(t *testing.T) {
logger.Info("TEST: %d", 123)
assert.Contains(t, buf.String(), "INFO: TEST: [123]")
buf.Reset()
})

t.Run("Warn", func(t *testing.T) {
logger.Warn("TEST: %d", 123)
assert.Contains(t, buf.String(), "WARN: TEST: [123]")
buf.Reset()
})

t.Run("Error", func(t *testing.T) {
logger.Error("TEST: %d", 123)
assert.Contains(t, buf.String(), "ERROR: TEST: [123]")
buf.Reset()
})

assert.True(t, logger.IsTrace())
assert.True(t, logger.IsDebug())
assert.True(t, logger.IsInfo())
assert.True(t, logger.IsWarn())
assert.True(t, logger.IsError())
assert.Empty(t, logger.ImpliedArgs())
assert.Equal(t, logger, logger.With())
assert.Equal(t, "consul", logger.Name())
assert.Equal(t, logger, logger.Named("test"))
assert.Equal(t, logger, logger.ResetNamed("test"))
assert.IsType(t, &log.Logger{}, logger.StandardLogger(nil))
assert.Equal(t, os.Stderr, logger.StandardWriter(nil))
}
18 changes: 5 additions & 13 deletions log/log.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Package log handles logging capabilities of harvester.
package log

import (
"errors"
"io"
"log"
"os"

hclog "github.com/hashicorp/go-hclog"
)

// Func function definition.
Expand All @@ -23,11 +24,10 @@ var (
errorf = func(format string, v ...interface{}) {
log.Printf("ERROR: "+format, v...)
}
writer io.Writer = os.Stdout
)

// Setup allows for setting up custom loggers.
func Setup(wr io.Writer, inf, waf, erf, dbf Func) error {
func Setup(inf, waf, erf, dbf Func) error {
if inf == nil {
return errors.New("info log function is nil")
}
Expand All @@ -40,22 +40,14 @@ func Setup(wr io.Writer, inf, waf, erf, dbf Func) error {
if dbf == nil {
return errors.New("debug log function is nil")
}
if wr == nil {
return errors.New("writer is nil")
}
infof = inf
warnf = waf
errorf = erf
debugf = dbf
writer = wr
hclog.SetDefault(consulLog)
return nil
}

// Writer returns the loggers writer interface.
func Writer() io.Writer {
return writer
}

// Infof provides log info capabilities.
func Infof(format string, v ...interface{}) {
infof(format, v...)
Expand Down
17 changes: 6 additions & 11 deletions log/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package log

import (
"bytes"
"io"
"log"
"os"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -24,13 +22,11 @@ func TestLog(t *testing.T) {
buf.Reset()
Errorf("Test %s", "logging")
assert.Contains(t, buf.String(), "ERROR: Test logging")
assert.Equal(t, os.Stdout, Writer())
}

func TestSetupLogging(t *testing.T) {
stubLogf := func(string, ...interface{}) {}
type args struct {
writer io.Writer
infof Func
warnf Func
errorf Func
Expand All @@ -41,16 +37,15 @@ func TestSetupLogging(t *testing.T) {
args args
wantErr bool
}{
{name: "success", args: args{writer: os.Stdin, infof: stubLogf, warnf: stubLogf, errorf: stubLogf, debugf: stubLogf}, wantErr: false},
{name: "missing writer", args: args{writer: nil, infof: stubLogf, warnf: stubLogf, errorf: stubLogf, debugf: stubLogf}, wantErr: true},
{name: "missing info", args: args{writer: os.Stdin, infof: nil, warnf: stubLogf, errorf: stubLogf, debugf: stubLogf}, wantErr: true},
{name: "missing warn", args: args{writer: os.Stdin, infof: stubLogf, warnf: nil, errorf: stubLogf, debugf: stubLogf}, wantErr: true},
{name: "missing error", args: args{writer: os.Stdin, infof: stubLogf, warnf: stubLogf, errorf: nil, debugf: stubLogf}, wantErr: true},
{name: "missing debug", args: args{writer: os.Stdin, infof: stubLogf, warnf: stubLogf, errorf: stubLogf}, wantErr: true},
{name: "success", args: args{infof: stubLogf, warnf: stubLogf, errorf: stubLogf, debugf: stubLogf}, wantErr: false},
{name: "missing info", args: args{infof: nil, warnf: stubLogf, errorf: stubLogf, debugf: stubLogf}, wantErr: true},
{name: "missing warn", args: args{infof: stubLogf, warnf: nil, errorf: stubLogf, debugf: stubLogf}, wantErr: true},
{name: "missing error", args: args{infof: stubLogf, warnf: stubLogf, errorf: nil, debugf: stubLogf}, wantErr: true},
{name: "missing debug", args: args{infof: stubLogf, warnf: stubLogf, errorf: stubLogf}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Setup(tt.args.writer, tt.args.infof, tt.args.warnf, tt.args.errorf, tt.args.debugf)
err := Setup(tt.args.infof, tt.args.warnf, tt.args.errorf, tt.args.debugf)
if tt.wantErr {
assert.Error(t, err)
} else {
Expand Down
Loading

0 comments on commit 35cab1c

Please sign in to comment.