Browse Source

store a runtime.Frame in Entry instead of the caller function name

tags/v1.2.0
David Bariod 11 months ago
parent
commit
ec57031db1
4 changed files with 14 additions and 13 deletions
  1. 8
    8
      entry.go
  2. 1
    1
      json_formatter.go
  3. 4
    3
      json_formatter_test.go
  4. 1
    1
      text_formatter.go

+ 8
- 8
entry.go View File

@@ -61,7 +61,7 @@ type Entry struct {
61 61
 	Level Level
62 62
 
63 63
 	// Calling method, with package name
64
-	Caller string
64
+	Caller *runtime.Frame
65 65
 
66 66
 	// Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
67 67
 	Message string
@@ -144,10 +144,11 @@ func getPackageName(f string) string {
144 144
 }
145 145
 
146 146
 // getCaller retrieves the name of the first non-logrus calling function
147
-func getCaller() (method string) {
147
+func getCaller() *runtime.Frame {
148 148
 	// Restrict the lookback frames to avoid runaway lookups
149 149
 	pcs := make([]uintptr, maximumCallerDepth)
150 150
 	depth := runtime.Callers(minimumCallerDepth, pcs)
151
+	frames := runtime.CallersFrames(pcs[:depth])
151 152
 
152 153
 	// cache this package's fully-qualified name
153 154
 	callerInitOnce.Do(func() {
@@ -158,24 +159,23 @@ func getCaller() (method string) {
158 159
 		minimumCallerDepth = knownLogrusFrames
159 160
 	})
160 161
 
161
-	for i := 0; i < depth; i++ {
162
-		fullFuncName := runtime.FuncForPC(pcs[i]).Name()
163
-		pkg := getPackageName(fullFuncName)
162
+	for f, again := frames.Next(); again; f, again = frames.Next() {
163
+		pkg := getPackageName(f.Function)
164 164
 
165 165
 		// If the caller isn't part of this package, we're done
166 166
 		if pkg != logrusPackage {
167
-			return fullFuncName
167
+			return &f
168 168
 		}
169 169
 	}
170 170
 
171 171
 	// if we got here, we failed to find the caller's context
172
-	return ""
172
+	return nil
173 173
 }
174 174
 
175 175
 func (entry Entry) HasCaller() (has bool) {
176 176
 	return entry.Logger != nil &&
177 177
 		entry.Logger.ReportCaller &&
178
-		entry.Caller != ""
178
+		entry.Caller != nil
179 179
 }
180 180
 
181 181
 // This function is not declared with a pointer value because otherwise

+ 1
- 1
json_formatter.go View File

@@ -82,7 +82,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
82 82
 	data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
83 83
 	data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
84 84
 	if entry.HasCaller() {
85
-		data[f.FieldMap.resolve(FieldKeyFunc)] = entry.Caller
85
+		data[f.FieldMap.resolve(FieldKeyFunc)] = entry.Caller.Function
86 86
 	}
87 87
 
88 88
 	var b *bytes.Buffer

+ 4
- 3
json_formatter_test.go View File

@@ -4,6 +4,7 @@ import (
4 4
 	"encoding/json"
5 5
 	"errors"
6 6
 	"fmt"
7
+	"runtime"
7 8
 	"strings"
8 9
 	"testing"
9 10
 )
@@ -167,8 +168,8 @@ func TestFieldsInNestedDictionary(t *testing.T) {
167 168
 	}
168 169
 
169 170
 	logEntry := WithFields(Fields{
170
-		"level":      "level",
171
-		"test":		  "test",
171
+		"level": "level",
172
+		"test":  "test",
172 173
 	})
173 174
 	logEntry.Level = InfoLevel
174 175
 
@@ -291,7 +292,7 @@ func TestFieldClashWithCaller(t *testing.T) {
291 292
 	SetReportCaller(true)
292 293
 	formatter := &JSONFormatter{}
293 294
 	e := WithField("func", "howdy pardner")
294
-	e.Caller = "somefunc"
295
+	e.Caller = &runtime.Frame{Function: "somefunc"}
295 296
 	b, err := formatter.Format(e)
296 297
 	if err != nil {
297 298
 		t.Fatal("Unable to format entry: ", err)

+ 1
- 1
text_formatter.go View File

@@ -208,7 +208,7 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
208 208
 	caller := ""
209 209
 
210 210
 	if entry.HasCaller() {
211
-		caller = fmt.Sprintf(" %s()", entry.Caller)
211
+		caller = fmt.Sprintf(" %s()", entry.Caller.Function)
212 212
 	}
213 213
 
214 214
 	if f.DisableTimestamp {

Loading…
Cancel
Save