-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: DRAGON <anantvijay3@gmail.com>
- Loading branch information
1 parent
4b73283
commit adf71a5
Showing
10 changed files
with
395 additions
and
111 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package iconlogger | ||
|
||
import ( | ||
"io" | ||
|
||
"github.com/kubescape/go-logger/helpers" | ||
|
||
"github.com/fatih/color" | ||
) | ||
|
||
var prefixError = color.New(color.Bold, color.FgHiRed).FprintfFunc() | ||
var prefixWarning = color.New(color.Bold, color.FgHiYellow).FprintfFunc() | ||
var prefixInfo = color.New(color.Bold, color.FgCyan).FprintfFunc() | ||
var prefixSuccess = color.New(color.Bold, color.FgHiGreen).FprintfFunc() | ||
var prefixDebug = color.New(color.Bold, color.FgWhite).FprintfFunc() | ||
var message = color.New().FprintfFunc() | ||
|
||
func prefix(l helpers.Level) func(w io.Writer, format string, a ...interface{}) { | ||
switch l { | ||
case helpers.DebugLevel: | ||
return prefixDebug | ||
case helpers.InfoLevel: | ||
return prefixInfo | ||
case helpers.SuccessLevel: | ||
return prefixSuccess | ||
case helpers.WarningLevel: | ||
return prefixWarning | ||
case helpers.ErrorLevel, helpers.FatalLevel: | ||
return prefixError | ||
} | ||
return message | ||
} | ||
|
||
func DisableColor(flag bool) { | ||
if flag { | ||
color.NoColor = true | ||
} | ||
} | ||
|
||
func EnableColor(flag bool) { | ||
if flag { | ||
color.NoColor = false | ||
} | ||
} |
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,118 @@ | ||
package iconlogger | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
"sync" | ||
|
||
spinnerpkg "github.com/briandowns/spinner" | ||
"github.com/kubescape/go-logger/helpers" | ||
) | ||
|
||
const LoggerName string = "icon" | ||
|
||
type IconLogger struct { | ||
writer *os.File | ||
level helpers.Level | ||
spinner *spinnerpkg.Spinner | ||
mutex sync.Mutex | ||
} | ||
|
||
var _ helpers.ILogger = (*IconLogger)(nil) // ensure all interface methods are here | ||
|
||
func NewIconLogger() *IconLogger { | ||
|
||
return &IconLogger{ | ||
writer: os.Stderr, // default to stderr | ||
level: helpers.InfoLevel, | ||
spinner: nil, | ||
mutex: sync.Mutex{}, | ||
} | ||
} | ||
|
||
func (il *IconLogger) GetLevel() string { return il.level.String() } | ||
func (il *IconLogger) SetWriter(w *os.File) { il.writer = w } | ||
func (il *IconLogger) GetWriter() *os.File { return il.writer } | ||
func (il *IconLogger) Ctx(_ context.Context) helpers.ILogger { return il } | ||
func (il *IconLogger) LoggerName() string { return LoggerName } | ||
|
||
func (il *IconLogger) SetLevel(level string) error { | ||
il.level = helpers.ToLevel(level) | ||
if il.level == helpers.UnknownLevel { | ||
return fmt.Errorf("level '%s' unknown", level) | ||
} | ||
return nil | ||
} | ||
func (il *IconLogger) Fatal(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.FatalLevel, msg, details...) | ||
os.Exit(1) | ||
} | ||
func (il *IconLogger) Error(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.ErrorLevel, msg, details...) | ||
} | ||
func (il *IconLogger) Warning(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.WarningLevel, msg, details...) | ||
} | ||
func (il *IconLogger) Info(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.InfoLevel, msg, details...) | ||
} | ||
func (il *IconLogger) Debug(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.DebugLevel, msg, details...) | ||
} | ||
func (il *IconLogger) Success(msg string, details ...helpers.IDetails) { | ||
il.print(helpers.SuccessLevel, msg, details...) | ||
} | ||
func (il *IconLogger) Start(msg string, details ...helpers.IDetails) { | ||
il.StartSpinner(il.writer, generateMessage(msg, details)) | ||
} | ||
func (il *IconLogger) StopSuccess(msg string, details ...helpers.IDetails) { | ||
il.StopSpinner(getSymbol("success") + generateMessage(msg, details) + "\n") | ||
} | ||
func (il *IconLogger) StopError(msg string, details ...helpers.IDetails) { | ||
il.StopSpinner(getSymbol("error") + generateMessage(msg, details) + "\n") | ||
} | ||
|
||
func (il *IconLogger) print(level helpers.Level, msg string, details ...helpers.IDetails) { | ||
il.PauseSpinner() | ||
if !level.Skip(il.level) { | ||
il.mutex.Lock() | ||
prefix(level)(il.writer, "%s", getSymbol(level.String())) | ||
message(il.writer, fmt.Sprintf("%s\n", generateMessage(msg, details))) | ||
il.mutex.Unlock() | ||
} | ||
il.ResumeSpinner() | ||
} | ||
|
||
func detailsToString(details []helpers.IDetails) string { | ||
s := "" | ||
for i := range details { | ||
s += fmt.Sprintf("%s: %v", details[i].Key(), details[i].Value()) | ||
if i < len(details)-1 { | ||
s += "; " | ||
} | ||
} | ||
return s | ||
} | ||
|
||
func getSymbol(level string) string { | ||
switch level { | ||
case "warning": | ||
return " ❗ " | ||
case "success": | ||
return "✅ " | ||
case "fatal", "error": | ||
return "❌ " | ||
case "debug": | ||
return "🐞 " | ||
default: | ||
return "ℹ️ " | ||
} | ||
} | ||
|
||
func generateMessage(msg string, details []helpers.IDetails) string { | ||
if d := detailsToString(details); d != "" { | ||
msg = fmt.Sprintf("%s. %s", msg, d) | ||
} | ||
return msg | ||
} |
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,154 @@ | ||
package iconlogger | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/kubescape/go-logger/helpers" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestIconLoggerPrint(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
loggerLevel helpers.Level | ||
printLevel helpers.Level | ||
msg string | ||
details []helpers.IDetails | ||
expected string | ||
shouldPrint bool | ||
}{ | ||
{ | ||
"Print Info", | ||
helpers.InfoLevel, | ||
helpers.InfoLevel, | ||
"Info Message", | ||
[]helpers.IDetails{ | ||
helpers.String("key1", "value1"), | ||
helpers.Int("key2", 123), | ||
}, | ||
"〜 Info Message\n", | ||
true, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
logger := &IconLogger{ | ||
level: tt.loggerLevel, | ||
} | ||
|
||
// Use a WaitGroup to wait for all goroutines to finish | ||
var wg sync.WaitGroup | ||
|
||
// Start multiple goroutines to call the print method concurrently | ||
for i := 0; i < 1000; i++ { | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
logger.print(tt.printLevel, tt.msg, tt.details...) | ||
}() | ||
} | ||
|
||
// Wait for all goroutines to finish | ||
wg.Wait() | ||
|
||
}) | ||
} | ||
} | ||
|
||
type mockDetail struct { | ||
key string | ||
value interface{} | ||
} | ||
|
||
func (m *mockDetail) Key() string { | ||
return m.key | ||
} | ||
|
||
func (m *mockDetail) Value() interface{} { | ||
return m.value | ||
} | ||
|
||
func TestDetailsToString(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
details []helpers.IDetails | ||
expected string | ||
}{ | ||
{ | ||
"Single Detail", | ||
[]helpers.IDetails{&mockDetail{"key1", "value1"}}, | ||
"key1: value1", | ||
}, | ||
{ | ||
"Multiple Details", | ||
[]helpers.IDetails{ | ||
&mockDetail{"key1", "value1"}, | ||
&mockDetail{"key2", 123}, | ||
}, | ||
"key1: value1; key2: 123", | ||
}, | ||
{ | ||
"No Details", | ||
[]helpers.IDetails{}, | ||
"", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
result := detailsToString(tt.details) | ||
assert.Equal(t, tt.expected, result) | ||
}) | ||
} | ||
} | ||
|
||
func TestGetSymbol(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
level string | ||
expect string | ||
}{ | ||
{"Warning", "warning", " ❗ "}, | ||
{"Success", "success", "✅ "}, | ||
{"Fatal", "fatal", "❌ "}, | ||
{"Error", "error", "❌ "}, | ||
{"Debug", "debug", "🐞 "}, | ||
{"Default", "info", "ℹ️ "}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
got := getSymbol(tt.level) | ||
assert.Equal(t, tt.expect, got) | ||
}) | ||
} | ||
} | ||
|
||
func TestIconLoggerGetLevel(t *testing.T) { | ||
logger := &IconLogger{ | ||
level: helpers.InfoLevel, | ||
} | ||
assert.Equal(t, "info", logger.GetLevel()) | ||
} | ||
|
||
func TestIconLoggerSetAndGetWriter(t *testing.T) { | ||
logger := &IconLogger{} | ||
writer := os.Stdout | ||
logger.SetWriter(writer) | ||
assert.Equal(t, writer, logger.GetWriter()) | ||
} | ||
|
||
func TestIconLoggerCtx(t *testing.T) { | ||
logger := &IconLogger{} | ||
ctx := context.Background() | ||
assert.Equal(t, logger, logger.Ctx(ctx)) | ||
} | ||
|
||
func TestIconLoggerLoggerName(t *testing.T) { | ||
logger := &IconLogger{} | ||
assert.Equal(t, LoggerName, logger.LoggerName()) | ||
} |
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,57 @@ | ||
package iconlogger | ||
|
||
import ( | ||
"os" | ||
"time" | ||
|
||
spinnerpkg "github.com/briandowns/spinner" | ||
"github.com/mattn/go-isatty" | ||
) | ||
|
||
func (il *IconLogger) StartSpinner(w *os.File, message string) { | ||
il.mutex.Lock() | ||
defer il.mutex.Unlock() | ||
|
||
if il.spinner != nil && il.spinner.Active() { | ||
return | ||
} | ||
if isSupported() { | ||
il.spinner = spinnerpkg.New(spinnerpkg.CharSets[14], 100*time.Millisecond, spinnerpkg.WithWriterFile(w)) // Build our new spinner | ||
il.spinner.Suffix = " " + message | ||
il.spinner.Start() | ||
} | ||
} | ||
|
||
func (il *IconLogger) StopSpinner(message string) { | ||
il.mutex.Lock() | ||
defer il.mutex.Unlock() | ||
|
||
if il.spinner == nil || !il.spinner.Active() { | ||
return | ||
} | ||
il.spinner.FinalMSG = message | ||
il.spinner.Stop() | ||
il.spinner = nil | ||
} | ||
|
||
func (il *IconLogger) PauseSpinner() { | ||
if il.spinner == nil || !il.spinner.Active() { | ||
return | ||
} | ||
|
||
il.spinner.Stop() | ||
} | ||
|
||
func (il *IconLogger) ResumeSpinner() { | ||
if il.spinner == nil || il.spinner.Active() { | ||
return | ||
} | ||
if !isSupported() { | ||
return | ||
} | ||
il.spinner.Start() | ||
} | ||
|
||
func isSupported() bool { | ||
return isatty.IsTerminal(os.Stdout.Fd()) | ||
} |
Oops, something went wrong.