Skip to content

Commit 4b21cdc

Browse files
authored
provide default config for logging (#183)
* provide default config for logging * swap the json/yaml parsers for viper
1 parent e9f9314 commit 4b21cdc

File tree

5 files changed

+94
-36
lines changed

5 files changed

+94
-36
lines changed

nconf/args.go

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,24 @@ type RootArgs struct {
1818
ConfigFile string
1919
}
2020

21-
func (args *RootArgs) Setup(config interface{}, serviceName, version string) (logrus.FieldLogger, error) {
22-
// first load the logger and BugSnag config
23-
rootConfig := &struct {
24-
Log *LoggingConfig
25-
BugSnag *BugSnagConfig
26-
Metrics metriks.Config
27-
Tracing tracing.Config
28-
FeatureFlag featureflag.Config
29-
}{}
21+
type RootConfig struct {
22+
Log LoggingConfig
23+
BugSnag BugSnagConfig `mapstructure:",squash"`
24+
Metrics metriks.Config `mapstructure:",squash"`
25+
Tracing tracing.Config `mapstructure:",squash"`
26+
FeatureFlag featureflag.Config `mapstructure:",squash"`
27+
}
3028

31-
loader := func(cfg interface{}) error {
32-
return LoadFromEnv(args.Prefix, args.ConfigFile, cfg)
33-
}
34-
if !strings.HasSuffix(args.ConfigFile, ".env") {
35-
loader = func(cfg interface{}) error {
36-
return LoadFromFile(args.ConfigFile, cfg)
37-
}
29+
func (args *RootArgs) Setup(config interface{}, serviceName, version string) (logrus.FieldLogger, error) {
30+
rootConfig := RootConfig{
31+
Log: DefaultLoggingConfig,
3832
}
3933

40-
if err := loader(rootConfig); err != nil {
41-
return nil, errors.Wrap(err, "Failed to load the logging configuration")
34+
if err := args.load(&rootConfig); err != nil {
35+
return nil, errors.Wrap(err, "Failed to load the root configuration")
4236
}
4337

44-
log, err := ConfigureLogging(rootConfig.Log)
38+
log, err := ConfigureLogging(&rootConfig.Log)
4539
if err != nil {
4640
return nil, errors.Wrap(err, "Failed to create the logger")
4741
}
@@ -50,7 +44,7 @@ func (args *RootArgs) Setup(config interface{}, serviceName, version string) (lo
5044
}
5145
log = log.WithField("version", version)
5246

53-
if err := SetupBugSnag(rootConfig.BugSnag, version); err != nil {
47+
if err := SetupBugSnag(&rootConfig.BugSnag, version); err != nil {
5448
return nil, errors.Wrap(err, "Failed to configure bugsnag")
5549
}
5650

@@ -71,14 +65,26 @@ func (args *RootArgs) Setup(config interface{}, serviceName, version string) (lo
7165

7266
if config != nil {
7367
// second load the config for this project
74-
if err := loader(config); err != nil {
68+
if err := args.load(config); err != nil {
7569
return log, errors.Wrap(err, "Failed to load the config object")
7670
}
7771
log.Debug("Loaded configuration")
7872
}
7973
return log, nil
8074
}
8175

76+
func (args *RootArgs) load(cfg interface{}) error {
77+
loader := func(cfg interface{}) error {
78+
return LoadFromEnv(args.Prefix, args.ConfigFile, cfg)
79+
}
80+
if !strings.HasSuffix(args.ConfigFile, ".env") {
81+
loader = func(cfg interface{}) error {
82+
return LoadFromFile(args.ConfigFile, cfg)
83+
}
84+
}
85+
return loader(cfg)
86+
}
87+
8288
func (args *RootArgs) MustSetup(config interface{}, serviceName, version string) logrus.FieldLogger {
8389
logger, err := args.Setup(config, serviceName, version)
8490
if err != nil {

nconf/args_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package nconf
22

33
import (
44
"io/ioutil"
5+
"os"
56
"testing"
67

78
"github.com/spf13/cobra"
@@ -67,3 +68,45 @@ func TestArgsAddToCmd(t *testing.T) {
6768
require.NoError(t, cmd.Execute())
6869
assert.Equal(t, 1, called)
6970
}
71+
72+
func TestArgsLoadFromYAML(t *testing.T) {
73+
f, err := ioutil.TempFile("", "test-config-*.yaml")
74+
require.NoError(t, err)
75+
defer os.Remove(f.Name())
76+
77+
args := RootArgs{
78+
ConfigFile: f.Name(),
79+
}
80+
81+
t.Run("empty-file", func(t *testing.T) {
82+
cfg := RootConfig{
83+
Log: DefaultLoggingConfig,
84+
}
85+
require.NoError(t, args.load(&cfg))
86+
87+
assert.True(t, cfg.Log.QuoteEmptyFields)
88+
assert.Equal(t, DefaultLoggingConfig, cfg.Log)
89+
assert.Empty(t, cfg.BugSnag.APIKey)
90+
})
91+
92+
_, err = f.WriteString(`
93+
log:
94+
level: debug
95+
fields:
96+
string: value
97+
int: 4
98+
`)
99+
require.NoError(t, err)
100+
101+
t.Run("set log field", func(t *testing.T) {
102+
cfg := RootConfig{Log: DefaultLoggingConfig}
103+
require.NoError(t, args.load(&cfg))
104+
105+
// retains original value
106+
assert.True(t, cfg.Log.QuoteEmptyFields)
107+
assert.Equal(t, "debug", cfg.Log.Level)
108+
require.Len(t, cfg.Log.Fields, 2)
109+
assert.Equal(t, "value", cfg.Log.Fields["string"])
110+
assert.Equal(t, 4, cfg.Log.Fields["int"])
111+
})
112+
}

nconf/configuration.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
package nconf
22

33
import (
4+
"encoding/json"
5+
"io/ioutil"
46
"os"
57
"strings"
68

79
"github.com/joho/godotenv"
810
"github.com/kelseyhightower/envconfig"
9-
"github.com/pkg/errors"
10-
"github.com/spf13/viper"
11+
"gopkg.in/yaml.v3"
1112
)
1213

1314
// LoadFromFile will load the configuration from the specified file based on the file type
@@ -17,24 +18,21 @@ func LoadFromFile(configFile string, input interface{}) error {
1718
return nil
1819
}
1920

21+
// read in all the bytes
22+
data, err := ioutil.ReadFile(configFile)
23+
if err != nil {
24+
return err
25+
}
26+
2027
switch {
2128
case strings.HasSuffix(configFile, ".json"):
22-
viper.SetConfigType("json")
29+
err = json.Unmarshal(data, input)
2330
case strings.HasSuffix(configFile, ".yaml"):
2431
fallthrough
2532
case strings.HasSuffix(configFile, ".yml"):
26-
viper.SetConfigType("yaml")
33+
err = yaml.Unmarshal(data, input)
2734
}
28-
viper.SetConfigFile(configFile)
29-
30-
if err := viper.ReadInConfig(); err != nil && !os.IsNotExist(err) {
31-
_, ok := err.(viper.ConfigFileNotFoundError)
32-
if !ok {
33-
return errors.Wrap(err, "reading configuration from files")
34-
}
35-
}
36-
37-
return viper.Unmarshal(input)
35+
return err
3836
}
3937

4038
func LoadFromEnv(prefix, filename string, face interface{}) error {

nconf/configuration_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/stretchr/testify/assert"
1111
"github.com/stretchr/testify/require"
12+
"gopkg.in/yaml.v3"
1213
)
1314

1415
type testConfig struct {
@@ -96,7 +97,7 @@ func TestFileLoadJSON(t *testing.T) {
9697

9798
func TestFileLoadYAML(t *testing.T) {
9899
expected := exampleConfig()
99-
bytes, err := json.Marshal(&expected)
100+
bytes, err := yaml.Marshal(&expected)
100101
require.NoError(t, err)
101102
filename := writeTestFile(t, "yaml", bytes)
102103
defer os.Remove(filename)

nconf/logging.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@ type LoggingConfig struct {
1717
UseNewLogger bool `mapstructure:"use_new_logger",split_words:"true"`
1818
}
1919

20+
var DefaultLoggingConfig = LoggingConfig{
21+
Level: "info",
22+
QuoteEmptyFields: true,
23+
Fields: make(map[string]interface{}),
24+
}
25+
2026
func ConfigureLogging(config *LoggingConfig) (*logrus.Entry, error) {
2127
logger := logrus.New()
2228

29+
if config == nil {
30+
config = &DefaultLoggingConfig
31+
}
32+
2333
tsFormat := time.RFC3339Nano
2434
if config.TSFormat != "" {
2535
tsFormat = config.TSFormat

0 commit comments

Comments
 (0)