-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* command: add context to initConfig errors When the `initConfig()` function fails, the previous behaviour was to just print out the error. This made it hard to understand where the problem was coming from since most of the errors are internal to viper and don't provide a lot of context of when the error happened. * command: unmarshal configuration after load Without unmarshalling the configuration, callers need call it themselves or rely on `viper.Get*()` calls to read configuration values. By unmarshalling it internally we remove this requirement from users. Use the `mapstructure.TextUnmarshallerHookFunc()` hook so configuration fields with complex structs can provide customized unmarshalling by implementing the `encoding.TextUnmarshaler` interface. * log: add logger based on stdlib slog --------- Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io> Co-authored-by: Shivansh Vij <shivanshvij@loopholelabs.io>
- Loading branch information
1 parent
6dc0f96
commit a531957
Showing
9 changed files
with
593 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
Copyright 2022 Loophole Labs | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package log | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// Format represents a log output format. | ||
type Format int | ||
|
||
const ( | ||
FormatText Format = iota | ||
FormatJSON | ||
) | ||
|
||
// String returns the string representation of a log format. | ||
// | ||
// Implements the fmt.Stringer and pflag.Value interfaces. | ||
func (f Format) String() string { | ||
switch f { | ||
case FormatText: | ||
return "text" | ||
case FormatJSON: | ||
return "json" | ||
default: | ||
return "<undefined>" | ||
} | ||
} | ||
|
||
// Type returns the string type of a log format. | ||
// | ||
// Implements the pflag.Value interface. | ||
func (f Format) Type() string { | ||
return "string" | ||
} | ||
|
||
// Set updates the value of a Format variable. | ||
// | ||
// Implements the pflag.Value interface. | ||
func (f *Format) Set(s string) error { | ||
switch strings.ToLower(s) { | ||
case "text": | ||
*f = FormatText | ||
case "json": | ||
*f = FormatJSON | ||
default: | ||
return fmt.Errorf("unknown log format %q", s) | ||
} | ||
return nil | ||
} | ||
|
||
// UnmarshalText decodes the text representation of a log format. | ||
// | ||
// Implements the encoding.TextUnmarshaler interface used by mapstructure and | ||
// viper. | ||
func (f *Format) UnmarshalText(text []byte) error { | ||
return f.Set(string(text)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
Copyright 2022 Loophole Labs | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package log | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/mitchellh/mapstructure" | ||
"github.com/spf13/viper" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_Format_String(t *testing.T) { | ||
t.Parallel() | ||
|
||
assert.Equal(t, "text", FormatText.String()) | ||
assert.Equal(t, "json", FormatJSON.String()) | ||
} | ||
|
||
func Test_Format_Set(t *testing.T) { | ||
t.Parallel() | ||
|
||
testCases := []struct { | ||
name string | ||
input string | ||
expected Format | ||
expectedErr string | ||
}{ | ||
{ | ||
name: "text", | ||
input: "text", | ||
expected: FormatText, | ||
}, | ||
{ | ||
name: "text all caps", | ||
input: "TEXT", | ||
expected: FormatText, | ||
}, | ||
{ | ||
name: "text mixed caps", | ||
input: "TeXt", | ||
expected: FormatText, | ||
}, | ||
{ | ||
name: "json", | ||
input: "json", | ||
expected: FormatJSON, | ||
}, | ||
{ | ||
name: "json all caps", | ||
input: "JSON", | ||
expected: FormatJSON, | ||
}, | ||
{ | ||
name: "json mixed caps", | ||
input: "jSoN", | ||
expected: FormatJSON, | ||
}, | ||
{ | ||
name: "invalid input", | ||
input: "not valid", | ||
expectedErr: "unknown log format", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
var f Format | ||
err := f.Set(tc.input) | ||
|
||
if tc.expectedErr != "" { | ||
require.ErrorContains(t, err, tc.expectedErr) | ||
} else { | ||
require.NoError(t, err) | ||
require.Equal(t, tc.expected, f) | ||
} | ||
|
||
}) | ||
} | ||
} | ||
|
||
func Test_Format_Unmarshal(t *testing.T) { | ||
t.Parallel() | ||
|
||
v := viper.New() | ||
v.Set("format", "json") | ||
|
||
c := struct{ Format Format }{} | ||
v.Unmarshal(&c, viper.DecodeHook(mapstructure.TextUnmarshallerHookFunc())) | ||
require.Equal(t, FormatJSON, c.Format) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/* | ||
Copyright 2022 Loophole Labs | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package log | ||
|
||
import "log/slog" | ||
|
||
// Level represents a log level threshold. | ||
type Level slog.Level | ||
|
||
const ( | ||
LevelDebug = Level(slog.LevelDebug) | ||
LevelInfo = Level(slog.LevelInfo) | ||
LevelWarn = Level(slog.LevelWarn) | ||
LevelError = Level(slog.LevelError) | ||
) | ||
|
||
// String returns the string representation of a log level. | ||
// | ||
// Implements the fmt.Stringer and pflag.Value interfaces. | ||
func (l Level) String() string { | ||
return slog.Level(l).String() | ||
} | ||
|
||
// Type returns the string type of a log level. | ||
// | ||
// Implements the pflag.Value interface. | ||
func (l Level) Type() string { | ||
return "string" | ||
} | ||
|
||
// Level returns the slog.Level value of a Level. | ||
// | ||
// Implements the slog.Leveler interface. | ||
func (l Level) Level() slog.Level { | ||
return slog.Level(l) | ||
} | ||
|
||
// Set updates the value of a Level variable. | ||
// | ||
// Implements the pflag.Value interface. | ||
func (l *Level) Set(s string) error { | ||
return (*slog.Level)(l).UnmarshalText([]byte(s)) | ||
} | ||
|
||
// UnmarshalText decodes the text representation of a log level. | ||
// | ||
// Implements the encoding.TextUnmarshaler interface used by mapstructure and | ||
// viper. | ||
func (l *Level) UnmarshalText(text []byte) error { | ||
return l.Set(string(text)) | ||
} |
Oops, something went wrong.