gitstack

grindlemire/gothem-stack code browser

2.0 KB Go 107 lines 2024-07-19 · 8d2d733 raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package log

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/pkg/errors"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// Initializes the log depending on the environment
func InitGlobal() error {
	var core zapcore.Core

	var logger *zap.Logger
	if strings.ToLower(os.Getenv("ENV")) == "prod" {
		zapconf := zap.NewProductionConfig()
		zapconf.EncoderConfig.FunctionKey = "func"
		core = zapcore.NewCore(
			zapcore.NewJSONEncoder(zapconf.EncoderConfig),
			zapcore.Lock(os.Stdout),
			zapcore.InfoLevel,
		)

		logger = zap.New(
			core,
			zap.AddCaller(),
		).Named("prod")
	} else {
		// if we are not in gcp use a console logger
		config := zap.NewDevelopmentConfig()
		config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
		config.EncoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
			enc.AppendString(t.UTC().Format("2006-01-02T15:04:05.000Z"))
		}

		logLevel := zapcore.InfoLevel
		debug := strings.ToLower(os.Getenv("DEBUG"))
		if debug == "1" || debug == "true" {
			logLevel = zapcore.DebugLevel
		}

		core = zapcore.NewCore(
			zapcore.NewConsoleEncoder(config.EncoderConfig),
			zapcore.Lock(os.Stdout),
			logLevel,
		)

		logger = zap.New(
			core,
			zap.AddCaller(),
		).Named("dev")
	}

	zap.ReplaceGlobals(logger)
	return nil
}

type stackTracer interface {
	StackTrace() errors.StackTrace
}

type stackOpt struct {
	withStack bool
}

type opt func(*stackOpt)

func WithStack() opt {
	return func(o *stackOpt) {
		o.withStack = true
	}
}

func Callers(err error, opts ...opt) []zap.Field {
	o := &stackOpt{}
	for _, opt := range opts {
		opt(o)
	}

	stack := ""
	caller := ""
	fun := ""
	if err, ok := err.(stackTracer); ok {
		for i, f := range err.StackTrace() {
			if i == 0 {
				caller = fmt.Sprintf("%s:%d", f, f)
				fun = fmt.Sprintf("%n", f)
			}
			stack = fmt.Sprintf("%s%+s:%d\n", stack, f, f)
		}
	}

	fields := []zap.Field{
		zap.String("err_caller", caller),
		zap.String("err_func", fun),
	}

	if o.withStack {
		fields = append(fields, zap.String("err_stack", stack))
	}

	return fields
}