Skip to content

Commit 5f1f942

Browse files
committed
Add function start stop log
1 parent 8678caa commit 5f1f942

5 files changed

Lines changed: 183 additions & 66 deletions

File tree

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ go 1.19
55
require (
66
github.com/sirupsen/logrus v1.9.1
77
github.com/stretchr/testify v1.8.1
8-
go.uber.org/zap v1.24.0
8+
go.uber.org/zap v1.27.1
99
)
1010

1111
require (
1212
github.com/davecgh/go-spew v1.1.1 // indirect
1313
github.com/pmezard/go-difflib v1.0.0 // indirect
1414
go.uber.org/atomic v1.7.0 // indirect
15-
go.uber.org/multierr v1.6.0 // indirect
15+
go.uber.org/multierr v1.11.0 // indirect
1616
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
17+
gopkg.in/natefinch/lumberjack.v2 v2.2.1
1718
gopkg.in/yaml.v3 v3.0.1 // indirect
1819
)

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,20 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
2121
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
2222
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
2323
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
24+
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
25+
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
26+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
27+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
2428
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
2529
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
30+
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
31+
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
2632
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
2733
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2834
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2935
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
36+
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
37+
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
3038
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3139
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3240
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

logging.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022-2024 Thorsten A. Knieling
2+
* Copyright 2022-2026 Thorsten A. Knieling
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@ package log
1414
import (
1515
"fmt"
1616
"os"
17+
"runtime"
1718
"strings"
1819
"time"
1920
)
@@ -85,7 +86,7 @@ type LogI interface {
8586

8687
// Central central configuration
8788
var Log = LogI(lognil())
88-
var debug = false
89+
var debugEnabled = false
8990

9091
func InitLog(newLog LogI) {
9192
Log = newLog
@@ -106,12 +107,12 @@ func InitLog(newLog LogI) {
106107
}
107108

108109
func IsDebugLevel() bool {
109-
return debug
110+
return debugEnabled
110111
}
111112

112113
func SetDebugLevel(debugIn bool) {
113-
debug = debugIn
114-
if debug {
114+
debugEnabled = debugIn
115+
if debugEnabled {
115116
fmt.Println("Warning DB debug is enabled")
116117
}
117118
}
@@ -139,3 +140,29 @@ func TimeTrack(start time.Time, name string) {
139140
elapsed := time.Since(start)
140141
Log.Infof("%s took %s", name, elapsed)
141142
}
143+
144+
// LogFunctionStart log function start if debug is enabled
145+
func LogFunctionStart() {
146+
if !debugEnabled {
147+
return
148+
}
149+
pc, _, _, ok := runtime.Caller(1)
150+
details := runtime.FuncForPC(pc)
151+
if ok && details != nil {
152+
Log.Debugf("Entering %s())", details.Name())
153+
}
154+
}
155+
156+
// LogFunctionEnd log function end if debug is enabled
157+
// Usage: defer LogFunctionEnd(time.Now())
158+
func LogFunctionEnd(start time.Time) {
159+
if !debugEnabled {
160+
return
161+
}
162+
pc, _, _, ok := runtime.Caller(1)
163+
details := runtime.FuncForPC(pc)
164+
if ok && details != nil {
165+
elapsed := time.Since(start)
166+
Log.Debugf("Leaving %s() tooks %s ms", details.Name(), elapsed)
167+
}
168+
}

logging_test.go

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022-2024 Thorsten A. Knieling
2+
* Copyright 2022-2026 Thorsten A. Knieling
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -12,13 +12,10 @@
1212
package log
1313

1414
import (
15-
"encoding/json"
1615
"fmt"
1716
"io"
1817
"net/url"
1918
"os"
20-
"path/filepath"
21-
"runtime"
2219
"testing"
2320
"time"
2421

@@ -29,8 +26,8 @@ import (
2926
)
3027

3128
func initTestLogWithFile(t *testing.T, fileName string) error {
32-
err := initLogLevelWithFile(fileName, zapcore.DebugLevel)
33-
if err != nil {
29+
err := InitZapLogLevelWithFile(fileName, zapcore.DebugLevel)
30+
if !assert.NoError(t, err) {
3431
t.Fatalf("error opening file: %v", err)
3532
}
3633
return err
@@ -41,59 +38,16 @@ func newWinFileSink(u *url.URL) (zap.Sink, error) {
4138
return os.OpenFile(u.Path[1:], os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
4239
}
4340

44-
func initLogLevelWithFile(fileName string, level zapcore.Level) (err error) {
45-
p := os.Getenv("LOGPATH")
46-
if p == "" {
47-
p = os.TempDir()
48-
}
49-
var name string
50-
if runtime.GOOS == "windows" {
51-
zap.RegisterSink("winfile", newWinFileSink)
52-
// OutputPaths: []string{"stdout", "winfile:///" + filepath.Join(GlobalConfigDir.Path, "info.log.json")},
53-
name = "winfile:///" + p + string(os.PathSeparator) + fileName
54-
} else {
55-
name = "file://" + filepath.ToSlash(p+string(os.PathSeparator)+fileName)
56-
}
57-
58-
rawJSON := []byte(`{
59-
"level": "error",
60-
"encoding": "console",
61-
"outputPaths": [ "XXX"],
62-
"errorOutputPaths": ["stderr"],
63-
"encoderConfig": {
64-
"messageKey": "message",
65-
"levelKey": "level",
66-
"levelEncoder": "lowercase"
67-
}
68-
}`)
69-
70-
var cfg zap.Config
71-
if err := json.Unmarshal(rawJSON, &cfg); err != nil {
72-
return err
73-
}
74-
cfg.Level.SetLevel(level)
75-
cfg.OutputPaths = []string{name}
76-
logger, err := cfg.Build()
77-
if err != nil {
78-
return err
79-
}
80-
defer logger.Sync()
81-
82-
sugar := logger.Sugar()
83-
InitLog(sugar)
84-
85-
sugar.Infof("AdabasGoApi logger initialization succeeded")
86-
return nil
87-
}
88-
8941
func doTrackCall() {
9042
defer TimeTrack(time.Now(), "Time Track Unit test ")
9143

9244
}
9345

9446
func TestLogZap(t *testing.T) {
9547
fileName := "zap.log"
96-
os.Remove(os.TempDir() + "/" + fileName)
48+
fileName = os.TempDir() + "/" + fileName
49+
fmt.Println("Use log file:", fileName)
50+
os.Remove(fileName)
9751
err := initTestLogWithFile(t, fileName)
9852
if !assert.NoError(t, err) {
9953
fmt.Println(err)
@@ -111,20 +65,21 @@ func TestLogZap(t *testing.T) {
11165
SetDebugLevel(false)
11266
SetDebugLevel(d)
11367

114-
flog, err := os.Open(os.TempDir() + "/" + fileName)
68+
flog, err := os.Open(fileName)
11569
if !assert.NoError(t, err) {
11670
return
11771
}
11872
logInfo, err := io.ReadAll(flog)
11973
if !assert.NoError(t, err) {
12074
return
12175
}
122-
assert.Regexp(t, `info AdabasGoApi logger initialization succeeded
123-
info Time Track Unit test took \d*ns
124-
debug This is a test of data HELLO
125-
debug ABC
126-
debug XXXX
127-
debug`, string(logInfo))
76+
assert.Regexp(t, `....-..-.. ..:..:..\tinfo\tStart logging with level debug
77+
....-..-.. ..:..:..\tinfo\tTime Track Unit test took [0-8]*ns
78+
....-..-.. ..:..:..\tdebug\tThis is a test of data HELLO
79+
....-..-.. ..:..:..\tdebug\tABC
80+
....-..-.. ..:..:..\tdebug\tXXXX
81+
....-..-.. ..:..:..\tdebug\t
82+
`, string(logInfo))
12883
}
12984

13085
func TestLogrus(t *testing.T) {
@@ -208,3 +163,32 @@ func TestCache(t *testing.T) {
208163
Log.Errorf("ERROR: Post-log information")
209164
assert.Equal(t, testResult, testLog.testLog)
210165
}
166+
167+
func TestStackTest(t *testing.T) {
168+
InitZapLogLevelWithFile("StackTest.log", zapcore.DebugLevel)
169+
Log.Debugf("DEBUG: Post-log information")
170+
Log.Infof("INFO: Post-log information")
171+
Log.Errorf("ERROR: Post-log information")
172+
stack1()
173+
}
174+
175+
func stack1() {
176+
LogFunctionStart()
177+
stack2()
178+
defer LogFunctionEnd(time.Now())
179+
180+
}
181+
182+
func stack2() {
183+
LogFunctionStart()
184+
stack3()
185+
defer LogFunctionEnd(time.Now())
186+
187+
}
188+
189+
func stack3() {
190+
LogFunctionStart()
191+
Log.Debugf("In stack3")
192+
defer LogFunctionEnd(time.Now())
193+
194+
}

zaplog.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2026 Thorsten A. Knieling
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
*/
11+
12+
package log
13+
14+
import (
15+
"fmt"
16+
"os"
17+
"strings"
18+
"time"
19+
20+
"go.uber.org/zap"
21+
"go.uber.org/zap/zapcore"
22+
"gopkg.in/natefinch/lumberjack.v2"
23+
)
24+
25+
var level = zapcore.ErrorLevel
26+
27+
func init() {
28+
ed := os.Getenv("ENABLE_LOGLEVEL")
29+
switch strings.ToLower(ed) {
30+
case "0", "error":
31+
level = zapcore.ErrorLevel
32+
case "1":
33+
level = zapcore.FatalLevel
34+
case "2", "warn", "warning":
35+
level = zapcore.WarnLevel
36+
case "3", "info":
37+
level = zapcore.InfoLevel
38+
case "4", "debug":
39+
level = zapcore.DebugLevel
40+
}
41+
}
42+
43+
func InitZapLogLevelWithFilename(fileName string, levelIn zapcore.Level) (err error) {
44+
level = levelIn
45+
p := os.Getenv("LOGPATH")
46+
if p == "" {
47+
p = "."
48+
} else {
49+
if _, err := os.Stat(p); os.IsNotExist(err) {
50+
err := os.Mkdir(p, os.ModePerm)
51+
if err != nil {
52+
fmt.Printf("Error creating log path '%s': %v\n", p, err)
53+
os.Exit(255)
54+
}
55+
}
56+
}
57+
58+
name := p + string(os.PathSeparator) + fileName
59+
return InitZapLogWithFile(name)
60+
}
61+
62+
func InitZapLogLevelWithFile(fileName string, levelIn zapcore.Level) (err error) {
63+
level = levelIn
64+
65+
return InitZapLogWithFile(fileName)
66+
}
67+
68+
func InitZapLogWithFile(name string) (err error) {
69+
lumberLog := &lumberjack.Logger{
70+
Filename: name, // Location of the log file
71+
MaxSize: 10, // Maximum file size (in MB)
72+
MaxBackups: 3, // Maximum number of old files to retain
73+
MaxAge: 28, // Maximum number of days to retain old files
74+
Compress: true, // Whether to compress/archive old files
75+
LocalTime: true, // Use local time for timestamps
76+
}
77+
writer := zapcore.AddSync(lumberLog)
78+
cfg := zap.NewProductionEncoderConfig()
79+
cfg.TimeKey = "timestamp"
80+
cfg.EncodeTime = zapcore.TimeEncoderOfLayout(time.DateTime)
81+
82+
core := zapcore.NewCore(
83+
zapcore.NewConsoleEncoder(cfg),
84+
writer,
85+
level,
86+
)
87+
logger := zap.New(core)
88+
defer logger.Sync() // Flush any buffered log entries
89+
90+
sugar := logger.Sugar()
91+
92+
sugar.Infof("Start logging with level %s", level)
93+
Log = sugar
94+
SetDebugLevel(level == zapcore.DebugLevel)
95+
96+
return
97+
}

0 commit comments

Comments
 (0)