Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const verifyCouchbaseSpan = (controls, entrySpan, options = {}) => [
span => expect(span.data.couchbase.sql).to.contain(options.sql || 'GET'),
span =>
options.error
? expect(span.data.couchbase.error).to.equal(options.error)
? expect(span.data.couchbase.error).to.contain(options.error)
: expect(span.data.couchbase.error).to.not.exist
];

Expand Down
51 changes: 51 additions & 0 deletions packages/collector/test/tracing/databases/mysql/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ app.post('/valuesAndCall', (req, res) => {
}
});

app.post('/error', (req, res) => {
if (driver === 'mysql2/promise') {
triggerErrorWithPromises(req, res);
} else {
triggerError(req, res);
}
});

app.listen(port, () => {
log(
`Listening on port: ${process.env.APP_PORT} (driver: ${driver}, access: ${accessFunction}, cluster: ${useCluster})`
Expand Down Expand Up @@ -305,6 +313,49 @@ function insertValuesWithPromisesAndCall(req, res) {
});
}

function triggerError(req, res) {
pool.getConnection((err, connection) => {
if (err) {
log('Failed to get connection', err);
res.sendStatus(500);
return;
}

connection[accessFunction]('SELECT * FROM non_existent_table', queryError => {
connection.release();

if (queryError) {
log('Expected error occurred', queryError);
res.sendStatus(500);
return;
}

res.sendStatus(200);
});
});
}

function triggerErrorWithPromises(req, res) {
pool
.getConnection()
.then(connection => {
wrapAccess(connection, 'SELECT * FROM non_existent_table', null, queryError => {
connection.release();

if (queryError) {
log('Expected error occurred', queryError);
res.sendStatus(500);
} else {
res.sendStatus(200);
}
});
})
.catch(err => {
log('Failed to get connection', err);
res.sendStatus(500);
});
}

function log() {
const args = Array.prototype.slice.call(arguments);
args[0] = logPrefix + args[0];
Expand Down
32 changes: 32 additions & 0 deletions packages/collector/test/tracing/databases/mysql/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,36 @@ function test(env, agentControls) {
})
);
}));

it('must replace stack trace with error stack when query fails', () =>
controls
.sendRequest({
method: 'POST',
path: '/error'
})
.then(() =>
testUtils.retry(() =>
agentControls.getSpans().then(spans => {
expect(spans.length).to.equal(2);
const entrySpan = testUtils.expectAtLeastOneMatching(spans, [
span => expect(span.n).to.equal('node.http.server'),
span => expect(span.f.e).to.equal(String(controls.getPid())),
span => expect(span.f.h).to.equal('agent-stub-uuid')
]);

const mysqlSpan = testUtils.expectAtLeastOneMatching(spans, [
span => expect(span.t).to.equal(entrySpan.t),
span => expect(span.p).to.equal(entrySpan.s),
span => expect(span.n).to.equal('mysql'),
span => expect(span.k).to.equal(constants.EXIT),
span => expect(span.f.e).to.equal(String(controls.getPid())),
span => expect(span.f.h).to.equal('agent-stub-uuid'),
span => expect(span.ec).to.equal(1),
span => expect(span.data.mysql.error).to.exist
]);

expect(mysqlSpan.stack).to.exist;
})
)
));
}
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ mochaSuiteFn('tracing/pg-native', function () {
return expectAtLeastOneMatching(spans, span => {
verifyPgExitBase(span, parent, statement);
expect(span.error).to.not.exist;
expect(span.stack).to.exist;
expect(span.ec).to.equal(1);
expect(span.data.pg.error).to.contain(errorMessage);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,10 @@ module.exports.run = function ({
span => expect(span.ec).to.equal(!withError ? 0 : 1),
span => (!withError ? expect(span.data.kafka.error).to.not.exist : ''),
span =>
withError === 'deliveryErrorSender' ? expect(span.data.kafka.error).to.equal('delivery fake error') : '',
withError === 'deliveryErrorSender' ? expect(span.data.kafka.error).to.contain('delivery fake error') : '',
span =>
withError === 'bufferErrorSender'
? expect(span.data.kafka.error).to.equal('Message must be a buffer or null')
? expect(span.data.kafka.error).to.contain('Message must be a buffer or null')
: ''
]);
}
Expand Down
1 change: 1 addition & 0 deletions packages/collector/test/tracing/misc/stack_trace/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const mochaSuiteFn = supportedVersion(process.versions.node) ? describe : descri
testUtils.expectAtLeastOneMatching(spans, [
span => expect(span.n).to.equal('node.http.client'),
span => expect(span.k).to.equal(constants.EXIT),
span => expect(span.data.http.status).to.equal(201),
span => expect(span.stack[2].m).to.equal('fetch'),
span => expect(span.stack[2].c).to.contains('node-fetch')
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ function registerTests(appUsesHttps) {
expect(span.data.http.error).to.match(/Invalid URL/);
},
span => expect(span.t).to.equal(entrySpan.t),
span => expect(span.p).to.equal(entrySpan.s)
span => expect(span.p).to.equal(entrySpan.s),
span => expect(span.stack).to.be.a('string')
]);
expectExactlyOneMatching(spans, span => {
expect(span.n).to.equal('node.http.client');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -853,12 +853,11 @@ function verifyHttpExit({
expectedClientError = `Failed to parse URL from http:127.0.0.1:${serverControls.port}malformed-url`;
}
expectations.push(span => expect(span.data.http.status).to.not.exist);
expectations.push(span => expect(span.data.http.error).to.equal(expectedClientError));
expectations.push(span => expect(span.data.http.error).to.contain(expectedClientError));
} else if (withTimeout) {
expectations.push(span => expect(span.data.http.status).to.not.exist);
// Early v18.x Node.js versions had "The operation was aborted", the message later changed to
// "The operation was aborted due to timeout".
expectations.push(span => expect(span.data.http.error).to.match(/^The operation was aborted(?: due to timeout)?/));
expectations.push(span => expect(span.data.http.error).to.contain('The operation was aborted due to timeout'));
} else {
expectations.push(span => expect(span.data.http.status).to.equal(status));
expectations.push(span => expect(span.data.http.error).to.not.exist);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ function finishSpan(err, data, span) {
function addErrorToSpan(err, span) {
if (err) {
span.ec = 1;
span.data.sqs.error = err.message || err.code || JSON.stringify(err);
tracingUtil.setErrorDetails(span, err, 'sqs');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ class InstanaAWSProduct {
addErrorToSpan(err, span) {
if (err) {
span.ec = 1;
const spanData = span.data && span.data[this.spanName];
if (spanData) {
spanData.error = err.message || err.code || JSON.stringify(err);
if (span.data?.[this.spanName]) {
span.data[this.spanName].error = err.message || err.code || JSON.stringify(err);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
const shimmer = require('../../../../shimmer');
const hook = require('../../../../../util/hook');
const cls = require('../../../../cls');
const tracingUtil = require('../../../../tracingUtil');

function init() {
hook.onModuleLoad('sqs-consumer', instrument);
Expand All @@ -30,7 +31,7 @@ function instrument(SQSConsumer) {
})
.catch(err => {
span.ec = 1;
span.data.sqs.error = err.message || err.code || JSON.stringify(err);
tracingUtil.setErrorDetails(span, err, 'sqs');
span.d = Date.now() - span.ts;
span.transmitManual();
});
Expand Down Expand Up @@ -62,7 +63,7 @@ function instrument(SQSConsumer) {
})
.catch(err => {
span.ec = 1;
span.data.sqs.error = err.message || err.code || JSON.stringify(err);
tracingUtil.setErrorDetails(span, err, 'sqs');
span.d = Date.now() - span.ts;
span.transmitManual();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function instrumentingOperation({
function finishSpan(error, span) {
if (error) {
span.ec = 1;
span.data.azstorage.error = tracingUtil.getErrorDetails(error);
tracingUtil.setErrorDetails(span, error, 'azstorage');
}
span.d = Date.now() - span.ts;
span.transmit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,7 @@ function finishSpan(err, messageId, span) {
function addErrorToSpan(err, span) {
if (err) {
span.ec = 1;
if (err.message) {
span.data.gcps.error = err.message;
} else if (typeof err === 'string') {
span.data.gcps.error = err;
}
tracingUtil.setErrorDetails(span, err, 'gcps');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ function instrumentedCreateStream(operation, bindEvent, finalEvent, ctx, origina
function finishSpan(error, result, span, extractorPost) {
if (error) {
span.ec = 1;
span.data.gcs.error = tracingUtil.getErrorDetails(error);
tracingUtil.setErrorDetails(span, error, 'gcs');
}

if (extractorPost) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ function instrumentTransactions(cluster, connectionStr) {
result
.catch(err => {
span.ec = 1;
span.data.couchbase.error = tracingUtil.getErrorDetails(err);
tracingUtil.setErrorDetails(span, err, 'couchbase');
})
.finally(() => {
span.d = Date.now() - span.ts;
Expand Down Expand Up @@ -497,7 +497,7 @@ function instrumentOperation({ connectionStr, bucketName, getBucketTypeFn, sql,
})
.catch(err => {
span.ec = 1;
span.data.couchbase.error = tracingUtil.getErrorDetails(err);
tracingUtil.setErrorDetails(span, err, 'couchbase');
})
.finally(() => {
span.d = Date.now() - span.ts;
Expand All @@ -510,7 +510,7 @@ function instrumentOperation({ connectionStr, bucketName, getBucketTypeFn, sql,
originalArgs[callbackIndex] = cls.ns.bind(function instanaCallback(err, result) {
if (err) {
span.ec = 1;
span.data.couchbase.error = tracingUtil.getErrorDetails(err);
tracingUtil.setErrorDetails(span, err, 'couchbase');
}

if (resultHandler) {
Expand Down
Loading