Skip to content

Commit

Permalink
pretty dev log
Browse files Browse the repository at this point in the history
  • Loading branch information
NorseGaud committed Mar 29, 2024
1 parent 5aeda99 commit 32da318
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 33 deletions.
3 changes: 1 addition & 2 deletions cmd/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"log/slog"
"os"
"os/signal"
"strconv"
"sync"
"time"

Expand Down Expand Up @@ -85,7 +84,7 @@ func main() {
if ctx.Err() != nil {
return
}
logger.InfoContext(serviceCtx, "runner completed, scanning for more work in "+strconv.Itoa(service.SleepInterval)+" seconds")
// logger.DebugContext(serviceCtx, "runner completed, scanning for more work in "+strconv.Itoa(service.SleepInterval)+" seconds")
time.Sleep(time.Duration(service.SleepInterval) * time.Second)
}
}
Expand Down
18 changes: 5 additions & 13 deletions internal/anka/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,29 +153,21 @@ func (cli *Cli) ExecuteAndParseJsonOnError(ctx context.Context, args ...string)

func (cli *Cli) AnkaRegistryPull(ctx context.Context, template string, tag string) error {
logger := logging.GetLoggerFromContext(ctx)
var tagInfo string
if tag == "(using latest)" {
tagInfo = "latest tag"
} else {
tagInfo = fmt.Sprintf("tag %s", tag)
}
logger.InfoContext(ctx, "pulling template to host", "template", template, "tagInfo", tagInfo)
logger.DebugContext(ctx, "pulling template to host")
var args []string
if tag != "(using latest)" {
args = []string{"anka", "-j", "registry", "pull", "--shrink", template, "--tag", tag}
} else {
args = []string{"anka", "-j", "registry", "pull", "--shrink", template}
}

pulledTemplate, err := cli.ExecuteParseJson(ctx, args...)
if err != nil {
return err
}
if pulledTemplate.Status != "OK" {
return fmt.Errorf("error pulling template from registry: %s", pulledTemplate.Message)
}

logger.InfoContext(ctx, "successfully pulled template from registry", "template", template, "tagInfo", tagInfo)
logger.DebugContext(ctx, "successfully pulled template from registry")
return nil
}

Expand All @@ -185,7 +177,7 @@ func (cli *Cli) AnkaDelete(ctx context.Context, vmName string) error {
if err != nil {
return err
}
logger.InfoContext(ctx, "successfully deleted vm", "vm_name", vmName, "std", deleteOutput.Message)
logger.DebugContext(ctx, "successfully deleted vm", "std", deleteOutput.Message)
return nil
}

Expand All @@ -198,7 +190,7 @@ func (cli *Cli) AnkaClone(ctx context.Context, template string, newVmName string
if cloneOutput.Status != "OK" {
return fmt.Errorf("error cloning template: %s", cloneOutput.Message)
}
logger.InfoContext(ctx, "successfully cloned template to new vm", "template", template, "vm_name", newVmName)
logger.InfoContext(ctx, "successfully cloned template to new vm")
return nil
}

Expand All @@ -211,7 +203,7 @@ func (cli *Cli) AnkaStart(ctx context.Context, vmName string) error {
if startOutput.Status != "OK" {
return fmt.Errorf("error starting vm: %s", startOutput.Message)
}
logger.InfoContext(ctx, "successfully started vm", "vm_name", vmName)
logger.InfoContext(ctx, "successfully started vm")
return nil
}

Expand Down
10 changes: 9 additions & 1 deletion internal/logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ import (
func New() *slog.Logger {
logLevel := os.Getenv("LOG_LEVEL")
var options *slog.HandlerOptions
if strings.ToUpper(logLevel) == "DEBUG" {
if logLevel == "dev" {
options = &slog.HandlerOptions{Level: slog.LevelDebug}
handler := &ContextHandler{Handler: NewPrettyHandler(&slog.HandlerOptions{
Level: slog.LevelDebug,
AddSource: false,
ReplaceAttr: nil,
})}
return slog.New(handler)
} else if strings.ToUpper(logLevel) == "DEBUG" {
options = &slog.HandlerOptions{Level: slog.LevelDebug}
} else if strings.ToUpper(logLevel) == "ERROR" {
options = &slog.HandlerOptions{Level: slog.LevelError}
Expand Down
195 changes: 195 additions & 0 deletions internal/logging/prettylog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package logging

import (
"bytes"
"context"
"encoding/json"
"fmt"
"log/slog"
"strconv"
"strings"
"sync"
)

const (
timeFormat = "[15:04:05.000]"

reset = "\033[0m"

black = 30
red = 31
green = 32
yellow = 33
blue = 34
magenta = 35
cyan = 36
lightGray = 37
darkGray = 90
lightRed = 91
lightGreen = 92
lightYellow = 93
lightBlue = 94
lightMagenta = 95
lightCyan = 96
white = 97
)

func colorize(colorCode int, v string) string {
return fmt.Sprintf("\033[%sm%s%s", strconv.Itoa(colorCode), v, reset)
}

type Handler struct {
h slog.Handler
r func([]string, slog.Attr) slog.Attr
b *bytes.Buffer
m *sync.Mutex
}

func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool {
return h.h.Enabled(ctx, level)
}

func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &Handler{h: h.h.WithAttrs(attrs), b: h.b, r: h.r, m: h.m}
}

func (h *Handler) WithGroup(name string) slog.Handler {
return &Handler{h: h.h.WithGroup(name), b: h.b, r: h.r, m: h.m}
}

func (h *Handler) computeAttrs(
ctx context.Context,
r slog.Record,
) (map[string]any, error) {
h.m.Lock()
defer func() {
h.b.Reset()
h.m.Unlock()
}()
if err := h.h.Handle(ctx, r); err != nil {
return nil, fmt.Errorf("error when calling inner handler's Handle: %w", err)
}

var attrs map[string]any
err := json.Unmarshal(h.b.Bytes(), &attrs)
if err != nil {
return nil, fmt.Errorf("error when unmarshaling inner handler's Handle result: %w", err)
}
return attrs, nil
}

func (h *Handler) Handle(ctx context.Context, r slog.Record) error {

var level string
levelAttr := slog.Attr{
Key: slog.LevelKey,
Value: slog.AnyValue(r.Level),
}
if h.r != nil {
levelAttr = h.r([]string{}, levelAttr)
}

if !levelAttr.Equal(slog.Attr{}) {
level = levelAttr.Value.String() + ":"

if r.Level <= slog.LevelDebug {
level = colorize(lightGray, level)
} else if r.Level <= slog.LevelInfo {
level = colorize(cyan, level)
} else if r.Level < slog.LevelWarn {
level = colorize(lightBlue, level)
} else if r.Level < slog.LevelError {
level = colorize(lightYellow, level)
} else if r.Level <= slog.LevelError+1 {
level = colorize(lightRed, level)
} else if r.Level > slog.LevelError+1 {
level = colorize(lightMagenta, level)
}
}

var timestamp string
timeAttr := slog.Attr{
Key: slog.TimeKey,
Value: slog.StringValue(r.Time.Format(timeFormat)),
}
if h.r != nil {
timeAttr = h.r([]string{}, timeAttr)
}
if !timeAttr.Equal(slog.Attr{}) {
timestamp = colorize(lightGray, timeAttr.Value.String())
}

var msg string
msgAttr := slog.Attr{
Key: slog.MessageKey,
Value: slog.StringValue(r.Message),
}
if h.r != nil {
msgAttr = h.r([]string{}, msgAttr)
}
if !msgAttr.Equal(slog.Attr{}) {
msg = colorize(white, msgAttr.Value.String())
}

attrs, err := h.computeAttrs(ctx, r)
if err != nil {
return err
}
bytes, err := json.MarshalIndent(attrs, "", " ")
if err != nil {
return fmt.Errorf("error when marshaling attrs: %w", err)
}

out := strings.Builder{}
if len(timestamp) > 0 {
out.WriteString(timestamp)
out.WriteString(" ")
}
if len(level) > 0 {
out.WriteString(level)
out.WriteString(" ")
}
if len(msg) > 0 {
out.WriteString(msg)
out.WriteString(" ")
}
if len(bytes) > 0 {
out.WriteString(colorize(darkGray, string(bytes)))
}
fmt.Println(out.String())

return nil
}

func suppressDefaults(
next func([]string, slog.Attr) slog.Attr,
) func([]string, slog.Attr) slog.Attr {
return func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey ||
a.Key == slog.LevelKey ||
a.Key == slog.MessageKey {
return slog.Attr{}
}
if next == nil {
return a
}
return next(groups, a)
}
}

func NewPrettyHandler(opts *slog.HandlerOptions) *Handler {
if opts == nil {
opts = &slog.HandlerOptions{}
}
b := &bytes.Buffer{}
return &Handler{
b: b,
h: slog.NewJSONHandler(b, &slog.HandlerOptions{
Level: opts.Level,
AddSource: opts.AddSource,
ReplaceAttr: suppressDefaults(opts.ReplaceAttr),
}),
r: opts.ReplaceAttr,
m: &sync.Mutex{},
}
}
Loading

0 comments on commit 32da318

Please sign in to comment.