Skip to content
This repository was archived by the owner on Aug 17, 2020. It is now read-only.

Commit 9509c96

Browse files
authored
Enable optional stacktrace tag in http and sql instrumentation. (#184)
* Enables optional stacktrace tag in http and sql instrumentation. * Removes the algorithm to ensure the first frame to be inside the source root. * Remove unused code and clean filepath
1 parent 2d2f202 commit 9509c96

File tree

6 files changed

+61
-9
lines changed

6 files changed

+61
-9
lines changed

env/vars.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,7 @@ var (
2020
ScopeConfiguration = newSliceEnvVar([]string{tags.PlatformName, tags.PlatformArchitecture, tags.GoVersion}, "SCOPE_CONFIGURATION")
2121
ScopeMetadata = newMapEnvVar(nil, "SCOPE_METADATA")
2222
ScopeInstrumentationHttpPayloads = newBooleanEnvVar(false, "SCOPE_INSTRUMENTATION_HTTP_PAYLOADS")
23+
ScopeInstrumentationHttpStacktrace = newBooleanEnvVar(false, "SCOPE_INSTRUMENTATION_HTTP_STACKTRACE")
2324
ScopeInstrumentationDbStatementValues = newBooleanEnvVar(false, "SCOPE_INSTRUMENTATION_DB_STATEMENT_VALUES")
25+
ScopeInstrumentationDbStacktrace = newBooleanEnvVar(false, "SCOPE_INSTRUMENTATION_DB_STACKTRACE")
2426
)

errors/handler.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package errors
22

33
import (
44
"fmt"
5+
"path/filepath"
56
"strings"
67
"time"
78

@@ -57,28 +58,44 @@ func LogErrorInRawSpan(rawSpan *tracer.RawSpan, err **errors.Error) {
5758
}
5859

5960
// Gets the current stack frames array
60-
func GetCurrentStackFrames(skip int) []StackFrames {
61+
func getCurrentStackFrames(skip int) []StackFrames {
6162
skip = skip + 1
6263
err := errors.New(nil)
6364
errStack := err.StackFrames()
6465
nLength := len(errStack) - skip
6566
if nLength < 0 {
6667
return nil
6768
}
68-
stackFrames := make([]StackFrames, nLength)
69+
stackFrames := make([]StackFrames, 0)
6970
for idx, frame := range errStack {
7071
if idx >= skip {
71-
stackFrames[idx-skip] = StackFrames{
72-
File: frame.File,
72+
stackFrames = append(stackFrames, StackFrames{
73+
File: filepath.Clean(frame.File),
7374
LineNumber: frame.LineNumber,
7475
Name: frame.Name,
7576
Package: frame.Package,
76-
}
77+
})
7778
}
7879
}
7980
return stackFrames
8081
}
8182

83+
// Gets the current stacktrace
84+
func GetCurrentStackTrace(skip int) map[string]interface{} {
85+
var exFrames []map[string]interface{}
86+
for _, frame := range getCurrentStackFrames(skip + 1) {
87+
exFrames = append(exFrames, map[string]interface{}{
88+
"name": frame.Name,
89+
"module": frame.Package,
90+
"file": frame.File,
91+
"line": frame.LineNumber,
92+
})
93+
}
94+
return map[string]interface{}{
95+
"frames": exFrames,
96+
}
97+
}
98+
8299
// Get the current error with the fixed stacktrace
83100
func GetCurrentError(recoverData interface{}) *errors.Error {
84101
return errors.Wrap(recoverData, 1)
@@ -138,7 +155,7 @@ func getExceptionFrameData(errMessage string, errStack []errors.StackFrame) map[
138155
exFrames = append(exFrames, map[string]interface{}{
139156
"name": frame.Name,
140157
"module": frame.Package,
141-
"file": frame.File,
158+
"file": filepath.Clean(frame.File),
142159
"line": frame.LineNumber,
143160
})
144161
}

instrumentation/nethttp/client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/opentracing/opentracing-go/ext"
1515
"github.com/opentracing/opentracing-go/log"
1616

17+
scopeerrors "go.undefinedlabs.com/scopeagent/errors"
1718
"go.undefinedlabs.com/scopeagent/instrumentation"
1819
)
1920

@@ -35,6 +36,9 @@ type Transport struct {
3536

3637
// Enable payload instrumentation
3738
PayloadInstrumentation bool
39+
40+
// Enable stacktrace
41+
Stacktrace bool
3842
}
3943

4044
type clientOptions struct {
@@ -178,6 +182,10 @@ func (t *Transport) doRoundTrip(req *http.Request) (*http.Response, error) {
178182

179183
tracer.start(req)
180184

185+
if t.Stacktrace {
186+
tracer.sp.SetTag("stacktrace", scopeerrors.GetCurrentStackTrace(2))
187+
}
188+
181189
ext.HTTPMethod.Set(tracer.sp, req.Method)
182190
ext.HTTPUrl.Set(tracer.sp, req.URL.String())
183191
tracer.opts.spanObserver(tracer.sp, req)

instrumentation/nethttp/nethttp_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
var r *tracer.InMemorySpanRecorder
1717

1818
func TestMain(m *testing.M) {
19-
PatchHttpDefaultClient(WithPayloadInstrumentation())
19+
PatchHttpDefaultClient(WithPayloadInstrumentation(), WithStacktrace())
2020

2121
// Test tracer
2222
r = tracer.NewInMemoryRecorder()

instrumentation/nethttp/patch.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ func WithPayloadInstrumentation() Option {
1717
}
1818
}
1919

20+
// Enables stacktrace
21+
func WithStacktrace() Option {
22+
return func(t *Transport) {
23+
t.Stacktrace = true
24+
}
25+
}
26+
2027
// Patches the default http client with the instrumented transport
2128
func PatchHttpDefaultClient(options ...Option) {
2229
once.Do(func() {
@@ -25,6 +32,7 @@ func PatchHttpDefaultClient(options ...Option) {
2532
option(transport)
2633
}
2734
transport.PayloadInstrumentation = transport.PayloadInstrumentation || env.ScopeInstrumentationHttpPayloads.Value
35+
transport.Stacktrace = transport.Stacktrace || env.ScopeInstrumentationHttpStacktrace.Value
2836
http.DefaultClient = &http.Client{Transport: transport}
2937
})
3038
}

instrumentation/sql/driver.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@ import (
55
"database/sql/driver"
66
"errors"
77
"fmt"
8+
"reflect"
9+
"strings"
10+
811
"github.com/opentracing/opentracing-go"
12+
913
"go.undefinedlabs.com/scopeagent/env"
14+
scopeerrors "go.undefinedlabs.com/scopeagent/errors"
1015
"go.undefinedlabs.com/scopeagent/instrumentation"
11-
"reflect"
12-
"strings"
1316
)
1417

1518
type (
@@ -22,6 +25,7 @@ type (
2225
driverConfiguration struct {
2326
t opentracing.Tracer
2427
statementValues bool
28+
stacktrace bool
2529
connString string
2630
componentName string
2731
peerService string
@@ -41,6 +45,13 @@ func WithStatementValues() Option {
4145
}
4246
}
4347

48+
// Enable span stacktrace
49+
func WithStacktrace() Option {
50+
return func(d *instrumentedDriver) {
51+
d.configuration.stacktrace = true
52+
}
53+
}
54+
4455
// Wraps the current sql driver to add instrumentation
4556
func WrapDriver(d driver.Driver, options ...Option) driver.Driver {
4657
wrapper := &instrumentedDriver{
@@ -54,6 +65,7 @@ func WrapDriver(d driver.Driver, options ...Option) driver.Driver {
5465
option(wrapper)
5566
}
5667
wrapper.configuration.statementValues = wrapper.configuration.statementValues || env.ScopeInstrumentationDbStatementValues.Value
68+
wrapper.configuration.stacktrace = wrapper.configuration.stacktrace || env.ScopeInstrumentationDbStacktrace.Value
5769
return wrapper
5870
}
5971

@@ -106,6 +118,11 @@ func (t *driverConfiguration) newSpan(operationName string, query string, args [
106118
"db.instance": c.instance,
107119
"peer.hostname": c.host,
108120
})
121+
if t.stacktrace {
122+
opts = append(opts, opentracing.Tags{
123+
"stacktrace": scopeerrors.GetCurrentStackTrace(2),
124+
})
125+
}
109126
if query != "" {
110127
stIndex := strings.IndexRune(query, ' ')
111128
var method string

0 commit comments

Comments
 (0)