Skip to content

Commit

Permalink
Merge pull request #409 from axw/errors-frame
Browse files Browse the repository at this point in the history
 apm: add support for github.com/pkg/errors@master
  • Loading branch information
axw authored Jan 7, 2019
2 parents 2f96ceb + cff2898 commit 2773fa2
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Changelog

## [Unreleased](https://github.com/elastic/apm-agent-go/compare/v1.1.2...master)
## [Unreleased](https://github.com/elastic/apm-agent-go/compare/v1.1.3...master)

## [v1.1.3](https://github.com/elastic/apm-agent-go/releases/tag/v1.1.3)

- Remove the `agent.*` metrics (#407)
- Add support for new github.com/pkg/errors.Frame type (#409)

## [v1.1.2](https://github.com/elastic/apm-agent-go/releases/tag/v1.1.2)

Expand Down
31 changes: 27 additions & 4 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@ import (
"net"
"os"
"reflect"
"runtime"
"syscall"
"time"
"unsafe"

"github.com/pkg/errors"

"go.elastic.co/apm/stacktrace"
)

var (
uintptrType = reflect.TypeOf(uintptr(0))
runtimeFrameType = reflect.TypeOf(runtime.Frame{})
errorsStackTraceUintptr = uintptrType.ConvertibleTo(reflect.TypeOf(*new(errors.Frame)))
errorsStackTraceFrame = reflect.TypeOf(*new(errors.Frame)).ConvertibleTo(runtimeFrameType)
)

// Recovered creates an Error with t.NewError(err), where
// err is either v (if v implements error), or otherwise
// fmt.Errorf("%v", v). The value v is expected to have
Expand Down Expand Up @@ -355,12 +364,26 @@ func initStacktrace(e *Error, err error) {
case internalStackTracer:
e.stacktrace = append(e.stacktrace[:0], stackTracer.StackTrace()...)
case errorsStackTracer:
// github.com/pkg/errors 0.8.x and earlier represent
// stack frames as uintptr; 0.9.0 and later represent
// them as runtime.Frames.
//
// TODO(axw) drop support for older github.com/pkg/errors
// versions when we release go.elastic.co/apm v2.0.0.
stackTrace := stackTracer.StackTrace()
pc := make([]uintptr, len(stackTrace))
for i, frame := range stackTrace {
pc[i] = uintptr(frame)
if errorsStackTraceUintptr {
pc := make([]uintptr, len(stackTrace))
for i, frame := range stackTrace {
pc[i] = *(*uintptr)(unsafe.Pointer(&frame))
}
e.stacktrace = stacktrace.AppendCallerFrames(e.stacktrace[:0], pc, -1)
} else if errorsStackTraceFrame {
e.stacktrace = e.stacktrace[:0]
for _, frame := range stackTrace {
rf := (*runtime.Frame)(unsafe.Pointer(&frame))
e.stacktrace = append(e.stacktrace, stacktrace.RuntimeFrame(*rf))
}
}
e.stacktrace = stacktrace.AppendCallerFrames(e.stacktrace[:0], pc, -1)
}
}

Expand Down
31 changes: 28 additions & 3 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"path/filepath"
"reflect"
"runtime"
"testing"

Expand Down Expand Up @@ -171,9 +172,33 @@ func (e *errorsStackTracer) StackTrace() errors.StackTrace {
func newErrorsStackTrace(skip, n int) errors.StackTrace {
callers := make([]uintptr, 2)
callers = callers[:runtime.Callers(1, callers)]
frames := make([]errors.Frame, len(callers))
for i, pc := range callers {
frames[i] = errors.Frame(pc)

var (
uintptrType = reflect.TypeOf(uintptr(0))
errorsFrameType = reflect.TypeOf(*new(errors.Frame))
runtimeFrameType = reflect.TypeOf(runtime.Frame{})
)

var frames []errors.Frame
switch {
case errorsFrameType.ConvertibleTo(uintptrType):
frames = make([]errors.Frame, len(callers))
for i, pc := range callers {
reflect.ValueOf(&frames[i]).Elem().Set(reflect.ValueOf(pc).Convert(errorsFrameType))
}
case errorsFrameType.ConvertibleTo(runtimeFrameType):
fs := runtime.CallersFrames(callers)
for {
var frame errors.Frame
runtimeFrame, more := fs.Next()
reflect.ValueOf(&frame).Elem().Set(reflect.ValueOf(runtimeFrame).Convert(errorsFrameType))
frames = append(frames, frame)
if !more {
break
}
}
default:
panic(fmt.Errorf("unhandled errors.Frame type %s", errorsFrameType))
}
return errors.StackTrace(frames)
}
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package apm

const (
// AgentVersion is the Elastic APM Go Agent version.
AgentVersion = "1.1.2"
AgentVersion = "1.1.3"
)

0 comments on commit 2773fa2

Please sign in to comment.