Skip to content

Commit

Permalink
Always Link Transaction IDs to Traces
Browse files Browse the repository at this point in the history
  • Loading branch information
mirackara committed Nov 17, 2023
1 parent c74d62c commit 57cdb6e
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 19 deletions.
1 change: 1 addition & 0 deletions v3/internal/expect.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type WantError struct {
TxnName string
Msg string
Klass string
GUID string
UserAttributes map[string]interface{}
AgentAttributes map[string]interface{}
}
Expand Down
2 changes: 2 additions & 0 deletions v3/newrelic/errors_from_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ func (h *tracedError) WriteJSON(buf *bytes.Buffer) {
h.Stack.WriteJSON(buf)
}
buf.WriteByte('}')
buf.WriteByte(',')
jsonx.AppendString(buf, h.txnEvent.TxnID)

buf.WriteByte(']')
}
Expand Down
85 changes: 71 additions & 14 deletions v3/newrelic/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,48 @@ func testExpectedJSON(t testing.TB, expect string, actual string) {
}
}

func TestErrorNoCAT(t *testing.T) {
he := &tracedError{
errorData: errorData{
When: time.Date(2014, time.November, 28, 1, 1, 0, 0, time.UTC),
Stack: emptyStackTrace,
Msg: "my_msg",
Klass: "my_class",
},
txnEvent: txnEvent{
FinalName: "my_txn_name",
Attrs: nil,
TxnID: "txn-guid-id",
BetterCAT: betterCAT{
Enabled: false,
},
TotalTime: 2 * time.Second,
},
}
js, err := json.Marshal(he)
if nil != err {
t.Error(err)
}

expect := `
[
1.41713646e+12,
"my_txn_name",
"my_msg",
"my_class",
{
"agentAttributes":{},
"userAttributes":{},
"intrinsics":{
"totalTime":2
},
"stack_trace":[]
},
"txn-guid-id"
]`
testExpectedJSON(t, expect, string(js))
}

func TestErrorTraceMarshal(t *testing.T) {
he := &tracedError{
errorData: errorData{
Expand All @@ -38,6 +80,7 @@ func TestErrorTraceMarshal(t *testing.T) {
txnEvent: txnEvent{
FinalName: "my_txn_name",
Attrs: nil,
TxnID: "txn-guid-id",
BetterCAT: betterCAT{
Enabled: true,
TxnID: "txn-id",
Expand Down Expand Up @@ -69,7 +112,8 @@ func TestErrorTraceMarshal(t *testing.T) {
"sampled":false
},
"stack_trace":[]
}
},
"txn-guid-id"
]`
testExpectedJSON(t, expect, string(js))
}
Expand All @@ -89,6 +133,7 @@ func TestErrorTraceMarshalOldCAT(t *testing.T) {
Enabled: false,
},
TotalTime: 2 * time.Second,
TxnID: "txn-guid-id",
},
}
js, err := json.Marshal(he)
Expand All @@ -109,7 +154,8 @@ func TestErrorTraceMarshalOldCAT(t *testing.T) {
"totalTime":2
},
"stack_trace":[]
}
},
"txn-guid-id"
]`
testExpectedJSON(t, expect, string(js))
}
Expand All @@ -135,11 +181,13 @@ func TestErrorTraceAttributes(t *testing.T) {
txnEvent: txnEvent{
FinalName: "my_txn_name",
Attrs: attr,
TxnID: "txn-id",

BetterCAT: betterCAT{
Enabled: true,
TxnID: "txn-id",
Priority: 0.5,
TraceID: "trace-id",
TxnID: "txn-id",
},
TotalTime: 2 * time.Second,
},
Expand All @@ -164,7 +212,8 @@ func TestErrorTraceAttributes(t *testing.T) {
"priority":0.500000,
"sampled":false
}
}
},
"txn-id"
]`
testExpectedJSON(t, expect, string(js))
}
Expand All @@ -188,6 +237,7 @@ func TestErrorTraceAttributesOldCAT(t *testing.T) {
Klass: "my_class",
},
txnEvent: txnEvent{
TxnID: "txn-guid-id",
FinalName: "my_txn_name",
Attrs: attr,
BetterCAT: betterCAT{
Expand All @@ -212,7 +262,8 @@ func TestErrorTraceAttributesOldCAT(t *testing.T) {
"intrinsics":{
"totalTime":2
}
}
},
"txn-guid-id"
]`
testExpectedJSON(t, expect, string(js))
}
Expand All @@ -231,6 +282,8 @@ func TestErrorsLifecycle(t *testing.T) {
mergeTxnErrors(&he, ers, txnEvent{
FinalName: "txnName",
Attrs: nil,
TxnID: "txn-id",

BetterCAT: betterCAT{
Enabled: true,
TxnID: "txn-id",
Expand All @@ -257,12 +310,13 @@ func TestErrorsLifecycle(t *testing.T) {
"userAttributes":{},
"intrinsics":{
"totalTime":2,
"guid":"txn-id",
"guid":"txn-id",
"traceId":"trace-id",
"priority":0.500000,
"sampled":false
}
}
},
"txn-id"
],
[
1.41713646e+12,
Expand All @@ -274,12 +328,13 @@ func TestErrorsLifecycle(t *testing.T) {
"userAttributes":{},
"intrinsics":{
"totalTime":2,
"guid":"txn-id",
"guid":"txn-id",
"traceId":"trace-id",
"priority":0.500000,
"sampled":false
}
}
},
"txn-id"
],
[
1.41713646e+12,
Expand All @@ -291,12 +346,13 @@ func TestErrorsLifecycle(t *testing.T) {
"userAttributes":{},
"intrinsics":{
"totalTime":2,
"guid":"txn-id",
"guid":"txn-id",
"traceId":"trace-id",
"priority":0.500000,
"sampled":false
}
}
},
"txn-id"
],
[
1.41713646e+12,
Expand All @@ -308,17 +364,18 @@ func TestErrorsLifecycle(t *testing.T) {
"userAttributes":{},
"intrinsics":{
"totalTime":2,
"guid":"txn-id",
"guid":"txn-id",
"traceId":"trace-id",
"priority":0.500000,
"sampled":false
}
}
},
"txn-id"
]
]
]`)
if string(js) != expect {
t.Error(string(js), expect)
t.Error(string(js), "expect: ", expect)
}
}

Expand Down
3 changes: 2 additions & 1 deletion v3/newrelic/harvest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ func TestHarvestErrorEventsReady(t *testing.T) {
})
h.ErrorEvents.Add(&errorEvent{
errorData: errorData{Klass: "klass", Msg: "msg", When: time.Now()},
txnEvent: txnEvent{FinalName: "finalName", Duration: 1 * time.Second},
txnEvent: txnEvent{FinalName: "finalName", Duration: 1 * time.Second, TxnID: "txn-guid-id"},
}, 0)
ready := h.Ready(now.Add(10 * time.Second))
payloads := ready.Payloads(true)
Expand Down Expand Up @@ -544,6 +544,7 @@ func TestHarvestMetricsTracesReady(t *testing.T) {
TxnName: "finalName",
Msg: "msg",
Klass: "klass",
GUID: "error-guid-id",
}})
expectErrors(t, h.ErrorTraces, []internal.WantError{})

Expand Down
10 changes: 6 additions & 4 deletions v3/newrelic/internal_txn.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,13 @@ func newTxn(app *app, run *appRun, name string, opts ...TraceOption) *thread {
if !txnOpts.SuppressCLM && run.Config.CodeLevelMetrics.Enabled && (txnOpts.DemandCLM || run.Config.CodeLevelMetrics.Scope == 0 || (run.Config.CodeLevelMetrics.Scope&TransactionCLM) != 0) {
reportCodeLevelMetrics(txnOpts, run, txn.Attrs.Agent.Add)
}
txn.TraceIDGenerator = run.Reply.TraceIDGenerator
traceID := txn.TraceIDGenerator.GenerateTraceID()
txn.SetTransactionID(traceID)

if run.Config.DistributedTracer.Enabled {
txn.BetterCAT.Enabled = true
txn.TraceIDGenerator = run.Reply.TraceIDGenerator
txn.BetterCAT.SetTraceAndTxnIDs(txn.TraceIDGenerator.GenerateTraceID())
txn.BetterCAT.SetTraceAndTxnIDs(traceID)
txn.BetterCAT.Priority = newPriorityFromRandom(txn.TraceIDGenerator.Float32)
txn.ShouldCollectSpanEvents = txn.shouldCollectSpanEvents
txn.ShouldCreateSpanGUID = txn.shouldCreateSpanGUID
Expand Down Expand Up @@ -523,7 +525,7 @@ func (thd *thread) End(recovered interface{}) error {
// segments occur.
for _, evt := range txn.SpanEvents {
evt.TraceID = txn.BetterCAT.TraceID
evt.TransactionID = txn.BetterCAT.TxnID
evt.TransactionID = txn.TxnID
evt.Sampled = txn.BetterCAT.Sampled
evt.Priority = txn.BetterCAT.Priority
}
Expand Down Expand Up @@ -1144,7 +1146,7 @@ func (thd *thread) CreateDistributedTracePayload(hdrs http.Header) {
p.Priority = txn.BetterCAT.Priority
p.Timestamp.Set(txn.Reply.DistributedTraceTimestampGenerator())
p.TrustedAccountKey = txn.Reply.TrustedAccountKey
p.TransactionID = txn.BetterCAT.TxnID // Set the transaction ID to the transaction guid.
p.TransactionID = txn.TxnID // Set the transaction ID to the transaction guid.
if nil != txn.BetterCAT.Inbound {
p.NonTrustedTraceState = txn.BetterCAT.Inbound.NonTrustedTraceState
p.OriginalTraceState = txn.BetterCAT.Inbound.OriginalTraceState
Expand Down
1 change: 1 addition & 0 deletions v3/newrelic/slow_queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ func TestSlowQueriesBetterCAT(t *testing.T) {
FinalName: "WebTransaction/Go/hello",
Duration: 3 * time.Second,
Attrs: attr,
TxnID: "my-txn-id",
BetterCAT: betterCAT{
Enabled: true,
TxnID: "txn-id",
Expand Down
11 changes: 11 additions & 0 deletions v3/newrelic/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type txnEvent struct {
datastoreCallCount uint64
datastoreDuration time.Duration
errGroupCallback ErrorGroupCallback
TxnID string
}

// betterCAT stores the transaction's priority and all fields related
Expand All @@ -62,6 +63,16 @@ func (bc *betterCAT) SetTraceAndTxnIDs(traceID string) {
}
}

func (e *txnEvent) SetTransactionID(transactionID string) {
txnLength := 16
if len(transactionID) <= txnLength {
e.TxnID = transactionID
} else {
e.TxnID = transactionID[:txnLength]
}

}

// txnData contains the recorded data of a transaction.
type txnData struct {
IsWeb bool
Expand Down
3 changes: 3 additions & 0 deletions v3/newrelic/txn_trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ func (trace *harvestTrace) writeJSON(buf *bytes.Buffer) {
jsonx.AppendString(buf, trace.CrossProcess.GUID)
} else if trace.BetterCAT.Enabled {
jsonx.AppendString(buf, trace.BetterCAT.TraceID)
} else if !trace.BetterCAT.Enabled && trace.CrossProcess.GUID != "" {
jsonx.AppendString(buf, trace.txnEvent.TxnID)

} else {
buf.WriteString(`""`)
}
Expand Down

0 comments on commit 57cdb6e

Please sign in to comment.