From 5d0ebcd216cb60b3a488b2b5f7c20f71f8d5bbeb Mon Sep 17 00:00:00 2001 From: Svetlana Brennan <50715937+svetlanabrennan@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:23:52 -0600 Subject: [PATCH] feat: Added transaction ID to ErrorTrace event (#1954) --- lib/errors/index.js | 5 +- test/unit/api/api-set-user-id.test.js | 2 +- test/unit/errors/error-collector.test.js | 147 ++++++++++++++++-- test/unit/protocols.test.js | 2 +- test/versioned/connect/error-intercept.tap.js | 2 +- 5 files changed, 144 insertions(+), 14 deletions(-) diff --git a/lib/errors/index.js b/lib/errors/index.js index 924e9ebc8f..09471f6bc9 100644 --- a/lib/errors/index.js +++ b/lib/errors/index.js @@ -67,7 +67,8 @@ class Exception { * [1] -> name extracted from error info, * [2] -> extracted error message, * [3] -> extracted error type, - * [4] -> attributes + * [4] -> attributes, + * [5] -> transaction id */ function createError(transaction, exception, config) { const error = exception.error @@ -111,7 +112,7 @@ function createError(transaction, exception, config) { maybeAddAgentAttributes(params, exception) - return [0, name, message, type, params] + return [0, name, message, type, params, transaction?.id] } function isValidErrorGroupOutput(output) { diff --git a/test/unit/api/api-set-user-id.test.js b/test/unit/api/api-set-user-id.test.js index 1269fe07d7..9bc603573b 100644 --- a/test/unit/api/api-set-user-id.test.js +++ b/test/unit/api/api-set-user-id.test.js @@ -63,7 +63,7 @@ tap.test('Agent API = set user id', (t) => { api.setUserID(id) const exception = new Exception(new Error('Test error.')) const [...data] = createError(tx, exception, agent.config) - const params = data.pop() + const params = data.at(-2) t.equal(params.agentAttributes['enduser.id'], id, 'should set enduser.id attribute on error') t.end() }) diff --git a/test/unit/errors/error-collector.test.js b/test/unit/errors/error-collector.test.js index dae4dd3ff1..f4e18552f9 100644 --- a/test/unit/errors/error-collector.test.js +++ b/test/unit/errors/error-collector.test.js @@ -199,6 +199,82 @@ tap.test('Errors', (t) => { }) }) + t.test('transaction id with distributed tracing enabled', (t) => { + t.autoend() + let errorJSON + let transaction + let error + + t.beforeEach(() => { + agent.config.distributed_tracing.enabled = true + error = new Error('this is an error') + }) + + t.test('should have a transaction id when there is a transaction', (t) => { + transaction = new Transaction(agent) + + agent.errors.add(transaction, error) + agent.errors.onTransactionFinished(transaction) + + const errorTraces = getErrorTraces(agent.errors) + errorJSON = errorTraces[0] + + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + transaction.end() + t.end() + }) + + t.test('should not have a transaction id when there is no transaction', (t) => { + agent.errors.add(null, error) + + const errorTraces = getErrorTraces(agent.errors) + errorJSON = errorTraces[0] + + const transactionId = errorJSON[5] + t.notOk(transactionId) + t.end() + }) + }) + + t.test('transaction id with distributed tracing disabled', (t) => { + t.autoend() + let errorJSON + let transaction + let error + + t.beforeEach(() => { + agent.config.distributed_tracing.enabled = false + error = new Error('this is an error') + }) + + t.test('should have a transaction id when there is a transaction', (t) => { + transaction = new Transaction(agent) + + agent.errors.add(transaction, error) + agent.errors.onTransactionFinished(transaction) + + const errorTraces = getErrorTraces(agent.errors) + errorJSON = errorTraces[0] + + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + transaction.end() + t.end() + }) + + t.test('should not have a transaction id when there is no transaction', (t) => { + agent.errors.add(null, error) + + const errorTraces = getErrorTraces(agent.errors) + errorJSON = errorTraces[0] + + const transactionId = errorJSON[5] + t.notOk(transactionId) + t.end() + }) + }) + t.test('display name', (t) => { t.autoend() const PARAMS = 4 @@ -285,7 +361,7 @@ tap.test('Errors', (t) => { const errorTraces = getErrorTraces(agent.errors) const error = errorTraces[0] - t.equal(error[error.length - 2], testError.name) + t.equal(error[error.length - 3], testError.name) t.end() }) @@ -622,11 +698,12 @@ tap.test('Errors', (t) => { t.autoend() let noErrorStatusTracer let errorJSON + let transaction t.beforeEach(() => { noErrorStatusTracer = agent.errors - const transaction = new Transaction(agent) + transaction = new Transaction(agent) transaction.statusCode = 503 // PDX wut wut noErrorStatusTracer.add(transaction, null) @@ -667,14 +744,26 @@ tap.test('Errors', (t) => { t.notHas(params, 'stack_trace') t.end() }) + + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) + + t.test('should have 6 elements in errorJson', (t) => { + t.equal(errorJSON.length, 6) + t.end() + }) }) t.test('with transaction agent attrs, status code, and no error', (t) => { let errorJSON = null let params = null + let transaction t.beforeEach(() => { - const transaction = new Transaction(agent) + transaction = new Transaction(agent) transaction.statusCode = 501 transaction.url = '/' transaction.trace.attributes.addAttributes(DESTS.TRANS_SCOPE, { @@ -721,6 +810,12 @@ tap.test('Errors', (t) => { t.end() }) + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) + t.test('should not have a request URL', (t) => { t.notOk(params['request.uri']) t.end() @@ -826,17 +921,24 @@ tap.test('Errors', (t) => { t.equal(params.stack_trace[0], 'Error: Dare to be the same!') t.end() }) + + t.test('should not have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.notOk(transactionId) + t.end() + }) }) t.test('with a thrown TypeError and a transaction with no params', (t) => { t.autoend() let typeErrorTracer let errorJSON + let transaction t.beforeEach(() => { typeErrorTracer = agent.errors - const transaction = new Transaction(agent) + transaction = new Transaction(agent) const exception = new TypeError('Dare to be different!') typeErrorTracer.add(transaction, exception) @@ -878,15 +980,22 @@ tap.test('Errors', (t) => { t.equal(params.stack_trace[0], 'TypeError: Dare to be different!') t.end() }) + + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) }) t.test('with a thrown `TypeError` and a transaction with agent attrs', (t) => { t.autoend() let errorJSON = null let params = null + let transaction t.beforeEach(() => { - const transaction = new Transaction(agent) + transaction = new Transaction(agent) const exception = new TypeError('wanted JSON, got XML') transaction.trace.attributes.addAttributes(DESTS.TRANS_SCOPE, { @@ -935,6 +1044,12 @@ tap.test('Errors', (t) => { t.end() }) + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) + t.test('should not have a request URL', (t) => { t.notOk(params['request.uri']) t.end() @@ -955,11 +1070,12 @@ tap.test('Errors', (t) => { t.autoend() let thrownTracer let errorJSON + let transaction t.beforeEach(() => { thrownTracer = agent.errors - const transaction = new Transaction(agent) + transaction = new Transaction(agent) const exception = 'Dare to be different!' thrownTracer.add(transaction, exception) @@ -999,15 +1115,22 @@ tap.test('Errors', (t) => { t.notHas(errorJSON[4], 'stack_trace') t.end() }) + + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) }) t.test('with a thrown string and a transaction with agent parameters', (t) => { t.autoend() let errorJSON = null let params = null + let transaction t.beforeEach(() => { - const transaction = new Transaction(agent) + transaction = new Transaction(agent) const exception = 'wanted JSON, got XML' transaction.trace.attributes.addAttributes(DESTS.TRANS_SCOPE, { @@ -1056,6 +1179,12 @@ tap.test('Errors', (t) => { t.end() }) + t.test('should have a transaction id', (t) => { + const transactionId = errorJSON[5] + t.equal(transactionId, transaction.id) + t.end() + }) + t.test('should not have a request URL', (t) => { t.notOk(params['request.uri']) t.end() @@ -2058,9 +2187,9 @@ test('When using the async listener', (t) => { }) }) - t.test('should have 5 elements in the trace', (t) => { + t.test('should have 6 elements in the trace', (t) => { executeThrowingTransaction(() => { - t.equal(json.length, 5) + t.equal(json.length, 6) t.end() }) }) diff --git a/test/unit/protocols.test.js b/test/unit/protocols.test.js index ec570b901d..809b14c3c3 100644 --- a/test/unit/protocols.test.js +++ b/test/unit/protocols.test.js @@ -36,7 +36,7 @@ tap.test('errors', (t) => { t.same( errors, '[1,[[0,"Unknown","test","Error",{"userAttributes":{},"agentAttributes":{},' + - '"intrinsics":{"error.expected":false},"stack_trace":["test stack"]}]]]' + '"intrinsics":{"error.expected":false},"stack_trace":["test stack"]},null]]]' ) t.end() }) diff --git a/test/versioned/connect/error-intercept.tap.js b/test/versioned/connect/error-intercept.tap.js index 96aad70e78..680da385e5 100644 --- a/test/versioned/connect/error-intercept.tap.js +++ b/test/versioned/connect/error-intercept.tap.js @@ -74,7 +74,7 @@ test('intercepting errors with connect 2', function (t) { t.equal(errors.length, 1, 'the error got traced') const error = errors[0] - t.equal(error.length, 5, 'format for traced error is correct') + t.equal(error.length, 6, 'format for traced error is correct') t.equal(error[3], 'TypeError', 'got the correct class for the error') server.close()