Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Default to STDERR instead of STDOUT #19

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

![demo](https://github.com/mgutz/logxi/raw/master/images/demo.gif)
![demo](https://github.com/serussell/logxi/raw/master/images/demo.gif)

# logxi

Expand All @@ -22,12 +22,12 @@ logger built for speed and happy development.

### Installation

go get -u github.com/mgutz/logxi/v1
go get -u github.com/serussell/logxi/v1

### Getting Started

```go
import "github.com/mgutz/logxi/v1"
import "github.com/serussell/logxi/v1"

// create package variable for Logger interface
var logger log.Logger
Expand Down
3 changes: 1 addition & 2 deletions v1/bench/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import (
"testing"

"github.com/Sirupsen/logrus"
"github.com/mgutz/logxi/v1"
"gopkg.in/inconshreveable/log15.v2"
"github.com/serussell/logxi/v1"
)

type M map[string]interface{}
Expand Down
145 changes: 46 additions & 99 deletions v1/callstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"

Expand All @@ -20,6 +21,7 @@ type frameInfo struct {
filename string
lineno int
method string
pc uintptr
context []*sourceLine
contextLines int
}
Expand Down Expand Up @@ -97,7 +99,7 @@ func (ci *frameInfo) String(color string, sourceColor string) string {
buf.WriteString(strconv.Itoa(ci.lineno))
buf.WriteString(")")

if ci.contextLines == -1 {
if contextLines == -1 {
return buf.String()
}
buf.WriteString("\n")
Expand All @@ -118,17 +120,26 @@ func (ci *frameInfo) String(color string, sourceColor string) string {
}

for _, li := range ci.context {
if !disableColors {
// need to reset here. If source is set to default color, then the message
// color will bleed over into the source context lines
buf.WriteString(ansi.Reset)
}
var format string
format = fmt.Sprintf("%%s%%%dd: %%s\n", linenoWidth)

if li.lineno == ci.lineno {
buf.WriteString(color)
if ci.contextLines > 2 {
if !disableColors {
buf.WriteString(color)
}
if contextLines > 0 {
format = fmt.Sprintf("%%s=> %%%dd: %%s\n", linenoWidth)
}
} else {
buf.WriteString(sourceColor)
if ci.contextLines > 2 {
if !disableColors {
buf.WriteString(sourceColor)
}
if contextLines > 0 {
// account for "=> "
format = fmt.Sprintf("%%s%%%dd: %%s\n", linenoWidth+3)
}
Expand All @@ -145,117 +156,53 @@ func (ci *frameInfo) String(color string, sourceColor string) string {
return buf.String()
}

// parseDebugStack parases a stack created by debug.Stack()
//
// This is what the string looks like
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:45 (0x5fa70)
// (*JSONFormatter).writeError: jf.writeString(buf, err.Error()+"\n"+string(debug.Stack()))
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:82 (0x5fdc3)
// (*JSONFormatter).appendValue: jf.writeError(buf, err)
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:109 (0x605ca)
// (*JSONFormatter).set: jf.appendValue(buf, val)
// ...
// /Users/mgutz/goroot/src/runtime/asm_amd64.s:2232 (0x38bf1)
// goexit:
func parseDebugStack(stack string, skip int, ignoreRuntime bool) []*frameInfo {
// Generates a stack from runtime.Callers()
func stackFrames(skip int, ignoreRuntime bool) []*frameInfo {
frames := []*frameInfo{}
// BUG temporarily disable since there is a bug with embedded newlines
if true {
return frames
}

lines := strings.Split(stack, "\n")

for i := skip * 2; i < len(lines); i += 2 {
ci := &frameInfo{}
sourceLine := lines[i]
if sourceLine == "" {
size := 20
pcs := make([]uintptr, size)
// always skip the first frame, since it's runtime.Callers itself
pcs = pcs[:runtime.Callers(1+skip, pcs)]

for _, pc := range pcs {
fn := runtime.FuncForPC(pc)
name := fn.Name()
file, line := fn.FileLine(pc - 1)
if ignoreRuntime && strings.Contains(file, filepath.Join("src", "runtime")) {
break
}
if ignoreRuntime && strings.Contains(sourceLine, filepath.Join("src", "runtime")) {
break
}

colon := strings.Index(sourceLine, ":")
slash := strings.Index(sourceLine, "/")
if colon < slash {
// must be on Windows where paths look like c:/foo/bar.go:lineno
colon = strings.Index(sourceLine[slash:], ":") + slash
}
space := strings.Index(sourceLine, " ")
ci.filename = sourceLine[0:colon]

// BUG with callstack where the error message has embedded newlines
// if colon > space {
// fmt.Println("lines", lines)
// }
// fmt.Println("SOURCELINE", sourceLine, "len", len(sourceLine), "COLON", colon, "SPACE", space)
numstr := sourceLine[colon+1 : space]
lineno, err := strconv.Atoi(numstr)
if err != nil {
InternalLog.Warn("Could not parse line number", "sourceLine", sourceLine, "numstr", numstr)
continue
ci := &frameInfo{
filename: file,
lineno: line,
method: name,
pc: pc,
}
ci.lineno = lineno

methodLine := lines[i+1]
colon = strings.Index(methodLine, ":")
ci.method = strings.Trim(methodLine[0:colon], "\t ")
frames = append(frames, ci)
}
return frames
}

// parseDebugStack parases a stack created by debug.Stack()
//
// This is what the string looks like
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:45 (0x5fa70)
// (*JSONFormatter).writeError: jf.writeString(buf, err.Error()+"\n"+string(debug.Stack()))
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:82 (0x5fdc3)
// (*JSONFormatter).appendValue: jf.writeError(buf, err)
// /Users/mgutz/go/src/github.com/mgutz/logxi/v1/jsonFormatter.go:109 (0x605ca)
// (*JSONFormatter).set: jf.appendValue(buf, val)
// ...
// /Users/mgutz/goroot/src/runtime/asm_amd64.s:2232 (0x38bf1)
// goexit:
func trimDebugStack(stack string) string {
// Returns debug stack excluding logxi frames
func trimmedStackTrace() string {
buf := pool.Get()
defer pool.Put(buf)
lines := strings.Split(stack, "\n")
for i := 0; i < len(lines); i += 2 {
sourceLine := lines[i]
if sourceLine == "" {
break
}

colon := strings.Index(sourceLine, ":")
slash := strings.Index(sourceLine, "/")
if colon < slash {
// must be on Windows where paths look like c:/foo/bar.go:lineno
colon = strings.Index(sourceLine[slash:], ":") + slash
}
filename := sourceLine[0:colon]
frames := stackFrames(0, false)
for _, frame := range frames {
// skip anything in the logxi package
if isLogxiCode(filename) {
if isLogxiCode(frame.filename) {
continue
}
buf.WriteString(sourceLine)
buf.WriteRune('\n')
buf.WriteString(lines[i+1])
buf.WriteRune('\n')
}
return buf.String()
}

func parseLogxiStack(entry map[string]interface{}, skip int, ignoreRuntime bool) []*frameInfo {
kv := entry[KeyMap.CallStack]
if kv == nil {
return nil
}
fmt.Fprintf(buf, "%s:%d (0x%x)\n", frame.filename, frame.lineno, frame.pc)

err := frame.readSource(0)
if err != nil || len(frame.context) < 1 {
continue
}

var frames []*frameInfo
if stack, ok := kv.(string); ok {
frames = parseDebugStack(stack, skip, ignoreRuntime)
fmt.Fprintf(buf, "\t%s: %s\n", frame.method, frame.context[0].line)
}
return frames
return buf.String()
}
2 changes: 1 addition & 1 deletion v1/cmd/demo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"os"

"github.com/mgutz/logxi/v1"
"github.com/serussell/logxi/v1"
)

var errConfig = fmt.Errorf("file not found")
Expand Down
2 changes: 1 addition & 1 deletion v1/cmd/filter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"io"
"os"

"github.com/mgutz/logxi/v1"
"github.com/serussell/logxi/v1"
)

func sendExternal(obj map[string]interface{}) {
Expand Down
2 changes: 1 addition & 1 deletion v1/cmd/reldir/foo.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package reldir

import "github.com/mgutz/logxi/v1"
import "github.com/serussell/logxi/v1"

// Foo returns error
func Foo() {
Expand Down
2 changes: 1 addition & 1 deletion v1/defaultLogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func NewLogger3(writer io.Writer, name string, formatter Formatter) Logger {

// New creates a colorable default logger.
func New(name string) Logger {
return NewLogger(colorableStdout, name)
return NewLogger(colorableStderr, name)
}

// Trace logs a debug entry.
Expand Down
2 changes: 2 additions & 0 deletions v1/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func formatFactory(name string, kind string) (Formatter, error) {
formatter = NewTextFormatter(name)
case FormatJSON:
formatter = NewJSONFormatter(name)
case FormatRFC5424:
formatter = NewRFC5424Formatter(name)
}
return formatter, err
}
Expand Down
Loading