Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Levels Colorization #51

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package log

import "fmt"

// ColorizeLevel assigns a specific color to each log level based on its string representation.
func ColorizeLevel(level Level) {
switch level.String() {
case "DEBUG":
PrintColor(DebugColor{})
case "INFO":
PrintColor(InfoColor{})
case "NOTICE":
PrintColor(NoticeColor{})
case "WARN":
PrintColor(WarnColor{})
case "ERROR":
PrintColor(ErrorColor{})
case "PANIC":
PrintColor(PanicColor{})
case "ALERT":
PrintColor(AlertColor{})
case "FATAL":
PrintColor(FatalColor{})
default:
PrintColor(DefaultColor{})
}
}

// Custom color types for each log level.
type DefaultColor struct{ value string }
type DebugColor struct{ value string }
type InfoColor struct{ value string }
type NoticeColor struct{ value string }
type WarnColor struct{ value string }
type ErrorColor struct{ value string }
type PanicColor struct{ value string }
type AlertColor struct{ value string }
type FatalColor struct{ value string }

// Methods for each color type that returns the corresponding ANSI escape code.
// These methods implement the Color interface.

// Set Debug Color
func (LevelColor DebugColor) getLevelColor() string {
LevelColor.value = "\033[36m"
return LevelColor.value
}

// Set Info Color
func (LevelColor InfoColor) getLevelColor() string {
LevelColor.value = "\033[32m"
return LevelColor.value
}

// Set Notice Color
func (LevelColor NoticeColor) getLevelColor() string {
LevelColor.value = "\033[33m"
return LevelColor.value
}

// Set Warn Color
func (LevelColor WarnColor) getLevelColor() string {
LevelColor.value = "\033[35m"
return LevelColor.value
}

// Set Error Color
func (LevelColor ErrorColor) getLevelColor() string {
LevelColor.value = "\033[31m"
return LevelColor.value
}

// Set Panic Color
func (LevelColor PanicColor) getLevelColor() string {
LevelColor.value = "\033[91m"
return LevelColor.value
}

// Set Alert Color
func (LevelColor AlertColor) getLevelColor() string {
LevelColor.value = "\033[93m"
return LevelColor.value
}

// Set Fatal Color
func (LevelColor FatalColor) getLevelColor() string {
LevelColor.value = "\033[95m"
return LevelColor.value
}

// Set Default Color
func (LevelColor DefaultColor) getLevelColor() string {
LevelColor.value = "\033[0m"
return LevelColor.value
}

// Color interface defines the getLevelColor method to get the ANSI escape code.
type Color interface {
getLevelColor() string
}

// PrintColor sets the appropriate color for the log level and prints it.
func PrintColor(C Color) {
LevelColor := C.getLevelColor()
fmt.Print(LevelColor)
}
89 changes: 89 additions & 0 deletions color_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package log

import (
"bytes"
"fmt"
"os"
"testing"
)

// CustomWriter is a custom writer that wraps bytes.Buffer and implements io.Writer
type CustomWriter struct {
buffer *bytes.Buffer
}

// Write writes the data to the underlying buffer
func (w *CustomWriter) Write(p []byte) (n int, err error) {
return w.buffer.Write(p)
}

// File returns the underlying *os.File
func (w *CustomWriter) File() *os.File {
return os.Stdout
}

func TestColorizeLevel(t *testing.T) {
buff := new(bytes.Buffer)

// Create a custom writer that wraps the buffer
customWriter := &CustomWriter{buffer: buff}

// Redirect stdout to the buffer
old := os.Stdout
os.Stdout = customWriter.File()

// Test cases
testCases := []struct {
level Level
color string
expected string
expectedErr error
}{
{DebugLevel, "\033[36m", "", nil}, // Expected ANSI escape code for DEBUG: Cyan
{InfoLevel, "\033[32m", "", nil}, // Expected ANSI escape code for INFO: Green
{NoticeLevel, "\033[33m", "", nil}, // Expected ANSI escape code for NOTICE: Yellow
{WarnLevel, "\033[35m", "", nil}, // Expected ANSI escape code for WARN: Magenta
{ErrorLevel, "\033[31m", "", nil}, // Expected ANSI escape code for ERROR: Red
{PanicLevel, "\033[91m", "", nil}, // Expected ANSI escape code for PANIC: Light Red
{AlertLevel, "\033[93m", "", nil}, // Expected ANSI escape code for ALERT: Light Yellow
{FatalLevel, "\033[95m", "", nil}, // Expected ANSI escape code for FATAL: Light Magenta
{InfoLevel, "\033[32m", "", nil}, // Invalid color (for testing error handling)
//{UNKNOWN, "\033[0m", "\033[0m", nil}, // Expected ANSI escape code for unknown level: Reset to default
}

// Iterate over test cases
for _, tc := range testCases {
t.Run(tc.level.String(), func(t *testing.T) {
// Reset the buffer
buff.Reset()

// Call the ColorizeLevel function
err := func() (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v", r)
}
}()
ColorizeLevel(tc.level)
return nil
}()

// Check if an error occurred (for error handling testing)
if tc.expectedErr != nil {
if err == nil || err.Error() != tc.expectedErr.Error() {
t.Errorf("Expected error: %v, but got: %v", tc.expectedErr, err)
}
return
}

// Check if the printed output matches the expected ANSI escape code
actual := buff.String()
if actual != tc.expected {
t.Errorf("Expected: %s, but got: %s", tc.expected, actual)
}
})
}

// Restore stdout
os.Stdout = old
}
3 changes: 3 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ func HandleEntry(e Entry) {
}
e.Timestamp = time.Now()

//Adding colors for each output level
ColorizeLevel(e.Level)

rw.RLock()
for _, h := range logHandlers[e.Level] {
h.Log(e)
Expand Down