Skip to content

Commit f4c1663

Browse files
committed
rewrite by logrus, fix func position not correct
1 parent 597c7a8 commit f4c1663

5 files changed

Lines changed: 142 additions & 97 deletions

File tree

example/main.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ import (
55
)
66

77
func init() {
8-
fixByFile := []string{"asm_amd64.s", "proc.go"}
9-
fixByFunc := []string{}
10-
log.Init("debug", fixByFile, fixByFunc)
8+
log.Init("debug")
119
}
1210

1311
func main() {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module github.com/pion/ion-log
22

33
go 1.15
44

5-
require github.com/rs/zerolog v1.20.0
5+
require github.com/sirupsen/logrus v1.8.1

go.sum

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
2-
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
3-
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
4-
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
5-
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
6-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
7-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
8-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
9-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
10-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
11-
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
12-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
6+
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
7+
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
8+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
9+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
10+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

log.go

Lines changed: 129 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
11
package log
22

33
import (
4+
"bytes"
45
"fmt"
5-
"os"
66
"path/filepath"
77
"runtime"
8+
"strconv"
89
"strings"
10+
"sync"
11+
"time"
912

10-
"github.com/rs/zerolog"
13+
log "github.com/sirupsen/logrus"
1114
)
1215

13-
var Log zerolog.Logger
16+
var (
17+
// Used for caller information initialisation
18+
callerInitOnce sync.Once
19+
logrusPackage string
20+
minimumCallerDepth = 1
21+
)
22+
23+
const (
24+
maximumCallerDepth int = 25
25+
knownLogrusFrames int = 4
26+
)
1427

1528
const timeFormat = "2006-01-02 15:04:05.000"
1629

@@ -19,71 +32,128 @@ type Config struct {
1932
Level string `mapstructure:"level"`
2033
}
2134

22-
// Init initializes the package logger.
23-
// Supported levels are: ["debug", "info", "warn", "error"]
24-
func Init(level string, fixByFile, fixByFunc []string) {
25-
l := zerolog.GlobalLevel()
26-
switch level {
27-
case "trace":
28-
l = zerolog.TraceLevel
29-
case "debug":
30-
l = zerolog.DebugLevel
31-
case "info":
32-
l = zerolog.InfoLevel
33-
case "warn":
34-
l = zerolog.WarnLevel
35-
case "error":
36-
l = zerolog.ErrorLevel
37-
}
38-
zerolog.TimeFieldFormat = timeFormat
39-
output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: timeFormat}
40-
output.FormatTimestamp = func(i interface{}) string {
41-
return "[" + i.(string) + "]"
42-
}
43-
output.FormatLevel = func(i interface{}) string {
44-
return strings.ToUpper(fmt.Sprintf("[%-3s]", i))
45-
}
46-
output.FormatMessage = func(i interface{}) string {
47-
caller, file, line, _ := runtime.Caller(9)
48-
fileName := filepath.Base(file)
49-
funcName := strings.TrimPrefix(filepath.Ext((runtime.FuncForPC(caller).Name())), ".")
50-
var needfix bool
51-
for _, b := range fixByFile {
52-
if strings.Contains(fileName, b) {
53-
needfix = true
54-
}
55-
}
56-
for _, b := range fixByFunc {
57-
if strings.Contains(funcName, b) {
58-
needfix = true
59-
}
60-
}
61-
if needfix {
62-
caller, file, line, _ = runtime.Caller(8)
63-
fileName = filepath.Base(file)
64-
funcName = strings.TrimPrefix(filepath.Ext((runtime.FuncForPC(caller).Name())), ".")
65-
}
66-
return fmt.Sprintf("[%d][%s][%s] => %s", line, fileName, funcName, i)
67-
}
68-
69-
Log = zerolog.New(output).Level(l).With().Timestamp().Logger()
70-
}
71-
7235
// Infof logs a formatted info level log to the console
73-
func Infof(format string, v ...interface{}) { Log.Info().Msgf(format, v...) }
36+
func Infof(format string, v ...interface{}) { log.Infof(format, v...) }
7437

7538
// Tracef logs a formatted debug level log to the console
76-
func Tracef(format string, v ...interface{}) { Log.Trace().Msgf(format, v...) }
39+
func Tracef(format string, v ...interface{}) { log.Tracef(format, v...) }
7740

7841
// Debugf logs a formatted debug level log to the console
79-
func Debugf(format string, v ...interface{}) { Log.Debug().Msgf(format, v...) }
42+
func Debugf(format string, v ...interface{}) { log.Debugf(format, v...) }
8043

8144
// Warnf logs a formatted warn level log to the console
82-
func Warnf(format string, v ...interface{}) { Log.Warn().Msgf(format, v...) }
45+
func Warnf(format string, v ...interface{}) { log.Warnf(format, v...) }
8346

8447
// Errorf logs a formatted error level log to the console
85-
func Errorf(format string, v ...interface{}) { Log.Error().Msgf(format, v...) }
48+
func Errorf(format string, v ...interface{}) { log.Errorf(format, v...) }
8649

8750
// Panicf logs a formatted panic level log to the console.
8851
// The panic() function is called, which stops the ordinary flow of a goroutine.
89-
func Panicf(format string, v ...interface{}) { Log.Panic().Msgf(format, v...) }
52+
func Panicf(format string, v ...interface{}) { log.Panicf(format, v...) }
53+
54+
type LogFormatter struct{}
55+
56+
func getPackageName(f string) string {
57+
for {
58+
lastPeriod := strings.LastIndex(f, ".")
59+
lastSlash := strings.LastIndex(f, "/")
60+
if lastPeriod > lastSlash {
61+
f = f[:lastPeriod]
62+
} else {
63+
break
64+
}
65+
}
66+
67+
return f
68+
}
69+
70+
func getFuncName(f string) string {
71+
n := strings.LastIndex(f, "/")
72+
if n == -1 {
73+
return f
74+
}
75+
return f[n+1:]
76+
}
77+
78+
// getCaller retrieves the name of the first non-logrus calling function
79+
func getCaller() *runtime.Frame {
80+
// cache this package's fully-qualified name
81+
callerInitOnce.Do(func() {
82+
pcs := make([]uintptr, maximumCallerDepth)
83+
_ = runtime.Callers(0, pcs)
84+
85+
// dynamic get the package name and the minimum caller depth
86+
for i := 0; i < maximumCallerDepth; i++ {
87+
funcName := runtime.FuncForPC(pcs[i]).Name()
88+
if strings.Contains(funcName, "getCaller") {
89+
logrusPackage = getPackageName(funcName)
90+
break
91+
}
92+
}
93+
94+
minimumCallerDepth = knownLogrusFrames
95+
})
96+
97+
// Restrict the lookback frames to avoid runaway lookups
98+
pcs := make([]uintptr, maximumCallerDepth)
99+
depth := runtime.Callers(minimumCallerDepth, pcs)
100+
frames := runtime.CallersFrames(pcs[:depth])
101+
102+
for f, again := frames.Next(); again; f, again = frames.Next() {
103+
pkg := getPackageName(f.Function)
104+
// find the function which is not logrus and ion-log
105+
if !strings.Contains(pkg, "logrus") && pkg != logrusPackage {
106+
return &f //nolint:scopelint
107+
}
108+
}
109+
110+
// if we got here, we failed to find the caller's context
111+
return nil
112+
}
113+
114+
func (s *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
115+
timestamp := time.Now().Local().Format("2006-01-02 15:04:05")
116+
var file string
117+
var len int
118+
// use custom getCaller because default getCaller worked bad after we wrapper it
119+
entry.Caller = getCaller()
120+
if entry.Caller != nil {
121+
file = filepath.Base(entry.Caller.File)
122+
len = entry.Caller.Line
123+
}
124+
125+
msg := fmt.Sprintf("[%s][%s:%d][%s][%s] %s\n", timestamp, file, len, strings.ToUpper(entry.Level.String()), getFuncName(entry.Caller.Function), entry.Message)
126+
return []byte(msg), nil
127+
}
128+
129+
// get goroutine id
130+
func getGID() uint64 {
131+
b := make([]byte, 64)
132+
b = b[:runtime.Stack(b, false)]
133+
b = bytes.TrimPrefix(b, []byte("goroutine "))
134+
b = b[:bytes.IndexByte(b, ' ')]
135+
n, _ := strconv.ParseUint(string(b), 10, 64)
136+
return n
137+
}
138+
139+
// func Init(level string) *log.Logger {
140+
func Init(level string) {
141+
l := log.DebugLevel
142+
switch level {
143+
case "trace":
144+
l = log.TraceLevel
145+
case "debug":
146+
l = log.DebugLevel
147+
case "info":
148+
l = log.InfoLevel
149+
case "warn":
150+
l = log.WarnLevel
151+
case "error":
152+
l = log.ErrorLevel
153+
}
154+
// log := log.New()
155+
log.SetLevel(l)
156+
log.SetReportCaller(true)
157+
log.SetFormatter(new(LogFormatter))
158+
// return logger
159+
}

log_test.go

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,6 @@ package log
33
import "testing"
44

55
func TestLogFormat(t *testing.T) {
6-
fixByFile := []string{"asm_amd64.s", "proc.go"}
7-
fixByFunc := []string{}
8-
Init("debug", fixByFile, fixByFunc)
6+
Init("debug")
97
Infof("Hello %s!", "ION")
108
}
11-
12-
func TestLogFixByFunc(t *testing.T) {
13-
fixByFile := []string{"asm_amd64.s", "proc.go"}
14-
fixByFunc := []string{"tRunner"}
15-
Init("debug", fixByFile, fixByFunc)
16-
Infof("Hello %s!", "ION")
17-
}
18-
19-
func TestLogFixByFile(t *testing.T) {
20-
fixByFile := []string{"asm_amd64.s", "proc.go"}
21-
fixByFunc := []string{}
22-
Init("debug", fixByFile, fixByFunc)
23-
printOK := make(chan struct{})
24-
go func() {
25-
Infof("Hello %s!", "ION")
26-
printOK <- struct{}{}
27-
}()
28-
<-printOK
29-
}

0 commit comments

Comments
 (0)