diff --git a/packages/collector/test/tracing/database/db2/app.js b/packages/collector/test/tracing/database/db2/app.js index 21585d27e2..75e5b126fa 100644 --- a/packages/collector/test/tracing/database/db2/app.js +++ b/packages/collector/test/tracing/database/db2/app.js @@ -6,19 +6,22 @@ require('../../../..')(); -/* eslint-disable no-console */ +const { promisify } = require('util'); const bodyParser = require('body-parser'); const express = require('express'); const fs = require('fs'); const morgan = require('morgan'); const ibmdb = require('ibm_db'); -const { isCI } = require('@instana/core/test/test_util'); +const { delay } = require('@instana/core/test/test_util'); const app = express(); const port = require('../../../test_util/app-port')(); const logPrefix = `DB2 App (${process.pid}):\t`; -const DB2_NAME = process.env.DB2_NAME; -let connStr = 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; + +const DB2_DATABASE_NAME = process.env.DB2_DATABASE_NAME; +const connStr1 = process.env.DB2_CONN_STR || 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; +const connStr2 = + process.env.DB2_CONN_STR_ALTERNATIVE || 'HOSTNAME=127.0.0.1;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; /** * We are unable to start a DB2 container on circleci, because db2 needs privileged permissions. @@ -50,16 +53,8 @@ let connStr = 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP' * That's why we use random names for tables. */ -if (isCI()) { - connStr = process.env.DB2_CONNECTION_STR; - if (!connStr) { - throw new Error( - 'No connection string for IBM DB2, please make sure the environment variable DB2_CONNECTION_STR is set.' - ); - } -} - let connection; +let connection2; const DB2_TABLE_NAME_1 = process.env.DB2_TABLE_NAME_1; const DB2_TABLE_NAME_2 = process.env.DB2_TABLE_NAME_2; @@ -76,46 +71,49 @@ const MAX_TRIES = 10; const CONNECT_TIMEOUT_IN_MS = 500; let stmtObjectFromStart; -const connect = () => { - console.log(`trying to connect: ${tries}`); - - ibmdb.open(`${connStr};DATABASE=${DB2_NAME}`, function (err, conn) { - if (err) { - console.log(err); +const db2OpenPromisified = promisify(ibmdb.open); - if (tries > MAX_TRIES) { - throw err; - } +async function connect(connectionStr) { + /* eslint-disable no-console */ + console.log(`Trying to connect to DB2, attempt ${tries} of ${MAX_TRIES}`); - tries += 1; - return setTimeout(() => { - console.log('Trying again...'); - connect(); - }, CONNECT_TIMEOUT_IN_MS); + let conn; + try { + conn = await db2OpenPromisified(connectionStr); + } catch (err) { + console.log(err); + if (tries > MAX_TRIES) { + throw err; } - console.log('Successfully connected.'); - - conn.querySync(`drop table ${DB2_TABLE_NAME_1} if exists`); - - const result = conn.querySync( - `create table ${DB2_TABLE_NAME_1} (COLINT INTEGER, COLDATETIME TIMESTAMP, COLTEXT VARCHAR(255))` - ); + tries += 1; + console.log(`Trying to connect to DB2 again in ${CONNECT_TIMEOUT_IN_MS} milliseconds.`); + await delay(CONNECT_TIMEOUT_IN_MS); + return connect(connectionStr); + } + console.log('A client has successfully connected.'); + return conn; + /* eslint-enable no-console */ +} - if (!(result instanceof Array)) { - throw new Error(result); - } +(async function openConnections() { + /* eslint-disable no-console */ + connection = await connect(`${connStr1};DATABASE=${DB2_DATABASE_NAME}`); - conn.prepare(`SELECT * FROM ${DB2_TABLE_NAME_1}`, (prepareErr, stmtObject) => { - if (prepareErr) throw prepareErr; + connection.querySync(`drop table ${DB2_TABLE_NAME_1} if exists`); + const result = connection.querySync( + `create table ${DB2_TABLE_NAME_1} (COLINT INTEGER, COLDATETIME TIMESTAMP, COLTEXT VARCHAR(255))` + ); + if (!(result instanceof Array)) { + throw new Error(result); + } + stmtObjectFromStart = connection.prepareSync(`SELECT * FROM ${DB2_TABLE_NAME_1}`); - stmtObjectFromStart = stmtObject; - connection = conn; - }); - }); -}; + connection2 = await connect(`${connStr2};DATABASE=${DB2_DATABASE_NAME}`); -connect(); + console.log('Both clients have successfully connected.'); + /* eslint-enable no-console */ +})(); if (process.env.WITH_STDOUT) { app.use(morgan(`${logPrefix}:method :url :status`)); @@ -124,7 +122,7 @@ if (process.env.WITH_STDOUT) { app.use(bodyParser.json()); app.get('/', (req, res) => { - if (!connection) { + if (!connection || !connection2) { res.sendStatus(500); } else { res.sendStatus(200); @@ -132,20 +130,27 @@ app.get('/', (req, res) => { }); app.delete('/conn', (req, res) => { + /* eslint-disable no-console */ console.log('deleting conn'); - if (!connection) { - return res.sendStatus(200); + if (connection) { + connection.closeSync(); + connection = null; + console.log('connection 1 has been closed'); } - connection.closeSync(); - connection = null; - console.log('deleted conn'); + if (connection2) { + connection2.closeSync(); + connection2 = null; + console.log('connection 2 has been closed'); + } res.sendStatus(200); + /* eslint-enable no-console */ }); app.delete('/tables', (req, res) => { + /* eslint-disable no-console */ console.log('deleting tables...'); if (!connection) { @@ -159,6 +164,7 @@ app.delete('/tables', (req, res) => { console.log('deleted tables'); res.sendStatus(200); + /* eslint-enable no-console */ }); app.get('/query-promise', (req, res) => { @@ -734,6 +740,32 @@ app.get('/query-stream', (req, res) => { }); }); +app.get('/two-different-target-hosts', async (req, res) => { + if (!connection) { + log('Client 1 is not connected.'); + return res.sendStatus(500); + } + if (!connection2) { + log('Client 2 is not connected.'); + return res.sendStatus(500); + } + + const response = {}; + try { + response.data1 = await connection.query('select 1 from sysibm.sysdummy1'); + } catch (e) { + log('The first DB2 query failed.', e); + return res.sendStatus(500); + } + try { + response.data2 = await connection2.query("select 'a' from sysibm.sysdummy1"); + } catch (e) { + log('The second DB2 query failed.', e); + return res.sendStatus(500); + } + res.json(response); +}); + app.listen(port, () => { log(`Listening on port: ${port}`); }); diff --git a/packages/collector/test/tracing/database/db2/app.mjs b/packages/collector/test/tracing/database/db2/app.mjs index fc1398d8b1..c1b5b86c60 100644 --- a/packages/collector/test/tracing/database/db2/app.mjs +++ b/packages/collector/test/tracing/database/db2/app.mjs @@ -2,9 +2,11 @@ * (c) Copyright IBM Corp. 2022 */ +/* eslint-disable no-console */ + 'use strict'; -/* eslint-disable no-console */ +import { promisify } from 'util'; import bodyParser from 'body-parser'; import express from 'express'; import fs from 'fs'; @@ -21,8 +23,12 @@ const __dirname = dirname(__filename); const app = express(); const port = getAppPort(); const logPrefix = `DB2 App (${process.pid}):\t`; -const DB2_NAME = process.env.DB2_NAME; -let connStr = 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; +const delay = testUtil.delay; + +const DB2_DATABASE_NAME = process.env.DB2_DATABASE_NAME; +const connStr1 = process.env.DB2_CONN_STR || 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; +const connStr2 = + process.env.DB2_CONN_STR_ALTERNATIVE || 'HOSTNAME=127.0.0.1;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; /** * We are unable to start a DB2 container on circleci, because db2 needs privileged permissions. @@ -54,16 +60,8 @@ let connStr = 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP' * That's why we use random names for tables. */ -if (testUtil.isCI()) { - connStr = process.env.DB2_CONNECTION_STR; - if (!connStr) { - throw new Error( - 'No connection string for IBM DB2, please make sure the environment variable DB2_CONNECTION_STR is set.' - ); - } -} - let connection; +let connection2; const DB2_TABLE_NAME_1 = process.env.DB2_TABLE_NAME_1; const DB2_TABLE_NAME_2 = process.env.DB2_TABLE_NAME_2; @@ -80,46 +78,45 @@ const MAX_TRIES = 10; const CONNECT_TIMEOUT_IN_MS = 500; let stmtObjectFromStart; -const connect = () => { - console.log(`trying to connect: ${tries}`); +const db2OpenPromisified = promisify(ibmdb.open); - ibmdb.open(`${connStr};DATABASE=${DB2_NAME}`, function (err, conn) { - if (err) { - console.log(err); - - if (tries > MAX_TRIES) { - throw err; - } +async function connect(connectionStr) { + console.log(`Trying to connect to DB2, attempt ${tries} of ${MAX_TRIES}`); - tries += 1; - return setTimeout(() => { - console.log('Trying again...'); - connect(); - }, CONNECT_TIMEOUT_IN_MS); + let conn; + try { + conn = await db2OpenPromisified(connectionStr); + } catch (err) { + console.log(err); + if (tries > MAX_TRIES) { + throw err; } - console.log('Successfully connected.'); - - conn.querySync(`drop table ${DB2_TABLE_NAME_1} if exists`); + tries += 1; + console.log(`Trying to connect to DB2 again in ${CONNECT_TIMEOUT_IN_MS} milliseconds.`); + await delay(CONNECT_TIMEOUT_IN_MS); + return connect(connectionStr); + } + console.log('A client has successfully connected.'); + return conn; +} - const result = conn.querySync( - `create table ${DB2_TABLE_NAME_1} (COLINT INTEGER, COLDATETIME TIMESTAMP, COLTEXT VARCHAR(255))` - ); +(async function openConnections() { + connection = await connect(`${connStr1};DATABASE=${DB2_DATABASE_NAME}`); - if (!(result instanceof Array)) { - throw new Error(result); - } + connection.querySync(`drop table ${DB2_TABLE_NAME_1} if exists`); + const result = connection.querySync( + `create table ${DB2_TABLE_NAME_1} (COLINT INTEGER, COLDATETIME TIMESTAMP, COLTEXT VARCHAR(255))` + ); + if (!(result instanceof Array)) { + throw new Error(result); + } + stmtObjectFromStart = connection.prepareSync(`SELECT * FROM ${DB2_TABLE_NAME_1}`); - conn.prepare(`SELECT * FROM ${DB2_TABLE_NAME_1}`, (prepareErr, stmtObject) => { - if (prepareErr) throw prepareErr; + connection2 = await connect(`${connStr2};DATABASE=${DB2_DATABASE_NAME}`); - stmtObjectFromStart = stmtObject; - connection = conn; - }); - }); -}; - -connect(); + console.log('Both clients have successfully connected.'); +})(); if (process.env.WITH_STDOUT) { app.use(morgan(`${logPrefix}:method :url :status`)); @@ -128,7 +125,7 @@ if (process.env.WITH_STDOUT) { app.use(bodyParser.json()); app.get('/', (req, res) => { - if (!connection) { + if (!connection || !connection2) { res.sendStatus(500); } else { res.sendStatus(200); @@ -138,13 +135,17 @@ app.get('/', (req, res) => { app.delete('/conn', (req, res) => { console.log('deleting conn'); - if (!connection) { - return res.sendStatus(200); + if (connection) { + connection.closeSync(); + connection = null; + console.log('connection 1 has been closed'); } - connection.closeSync(); - connection = null; - console.log('deleted conn'); + if (connection2) { + connection2.closeSync(); + connection2 = null; + console.log('connection 2 has been closed'); + } res.sendStatus(200); }); @@ -738,6 +739,34 @@ app.get('/query-stream', (req, res) => { }); }); +app.get('/two-different-target-hosts', async (req, res) => { + if (!connection) { + log('Client 1 is not connected.'); + return res.sendStatus(500); + } + if (!connection2) { + log('Client 2 is not connected.'); + return res.sendStatus(500); + } + + const response = {}; + try { + response.data1 = await connection.query('select 1 from sysibm.sysdummy1'); + console.log('data1', response.data1); + } catch (e) { + log('The first DB2 query failed.', e); + return res.sendStatus(500); + } + try { + response.data2 = await connection2.query("select 'a' from sysibm.sysdummy1"); + console.log('data2', response.data2); + } catch (e) { + log('The second DB2 query failed.', e); + return res.sendStatus(500); + } + res.json(response); +}); + app.listen(port, () => { log(`Listening on port: ${port}`); }); diff --git a/packages/collector/test/tracing/database/db2/test.js b/packages/collector/test/tracing/database/db2/test.js index 9d6aba5fcc..f6edce87a4 100644 --- a/packages/collector/test/tracing/database/db2/test.js +++ b/packages/collector/test/tracing/database/db2/test.js @@ -4,6 +4,7 @@ 'use strict'; +const dns = require('dns').promises; const expect = require('chai').expect; const semver = require('semver'); @@ -14,13 +15,22 @@ const ProcessControls = require('../../../test_util/ProcessControls'); const globalAgent = require('../../../globalAgent'); const mochaSuiteFn = supportedVersion(process.versions.node) ? describe : describe.skip; -const DB_LOCAL_CONN_STR = 'HOSTNAME=localhost;UID=node;PWD=;PORT=58885;PROTOCOL=TCPIP'; -const DB_REMOTE_CONN_STR = testUtils.isCI() - ? process.env.DB2_CONNECTION_STR.replace(/PWD=.*?(?=;)/, 'PWD=') - : null; -const CONN_STR = DB_REMOTE_CONN_STR || DB_LOCAL_CONN_STR; -let DB2_NAME; +if (testUtils.isCI() && !process.env.DB2_CONNECTION_STR) { + throw new Error( + 'No connection string for IBM DB2, please make sure the environment variable DB2_CONNECTION_STR is set.' + ); +} + +const DB2_CONN_STR = + process.env.DB2_CONNECTION_STR || 'HOSTNAME=localhost;UID=node;PWD=nodepw;PORT=58885;PROTOCOL=TCPIP'; +let DB2_CONN_STR_ALTERNATIVE; +let EXPECTED_DB2_CONN_STR; +let EXPECTED_DB2_CONN_STR_ALTERNATIVE; +const DB2_HOSTNAME = /HOSTNAME=([^;]+)/.exec(DB2_CONN_STR)[1]; + +// NOTE: DB2 has a limitation of 8 chars +const DB2_DATABASE_NAME = 'nodedb'; let TABLE_NAME_1; let TABLE_NAME_2; let TABLE_NAME_3; @@ -28,8 +38,8 @@ const DELAY_TIMEOUT_IN_MS = 500; const DB2_CLOSE_TIMEOUT_IN_MS = 1000; -// NOTE: DB2 has a limitation of 8 chars -const getDatabaseName = () => 'nodedb'; +const testTimeout = Math.max(20000, config.getTestTimeout()); +const retryTime = testTimeout / 2; const generateTableName = () => { const randomStr = Array(8) @@ -72,7 +82,7 @@ const verifySpans = (agentControls, controls, options = {}) => span => expect(span.f.e).to.equal(String(controls.getPid())), span => expect(span.f.h).to.equal('agent-stub-uuid'), span => expect(span.data.db2.stmt).to.equal(options.stmt || 'select 1 from sysibm.sysdummy1'), - span => expect(span.data.db2.dsn).to.equal(`${CONN_STR};DATABASE=${DB2_NAME}`), + span => expect(span.data.db2.dsn).to.equal(`${EXPECTED_DB2_CONN_STR};DATABASE=${DB2_DATABASE_NAME}`), span => expect(span.async).to.not.exist, span => options.error @@ -85,7 +95,22 @@ const verifySpans = (agentControls, controls, options = {}) => // The db2 docker container needs a longer time to bootstrap. Please check the docker logs if // the container is up. mochaSuiteFn('tracing/db2', function () { - this.timeout(config.getTestTimeout()); + this.timeout(testTimeout); + + before(async () => { + // We need a second connection string pointing to the same DB2 instance, for the test "call two different hosts". We + // produce one by resolving the host name in the original connection string to an IP. + const dnsLookupResult = await dns.lookup(DB2_HOSTNAME, { family: 4 }); + if (dnsLookupResult && dnsLookupResult.address) { + DB2_CONN_STR_ALTERNATIVE = DB2_CONN_STR.replace(DB2_HOSTNAME, dnsLookupResult.address); + } else { + DB2_CONN_STR_ALTERNATIVE = DB2_CONN_STR.replace('localhost', dnsLookupResult.address); + } + + // The EXPECTED_... variables are what the tracer will capture (with the password redacted). + EXPECTED_DB2_CONN_STR = DB2_CONN_STR.replace(/PWD=.*?(?=;)/, 'PWD='); + EXPECTED_DB2_CONN_STR_ALTERNATIVE = DB2_CONN_STR_ALTERNATIVE.replace(/PWD=.*?(?=;)/, 'PWD='); + }); globalAgent.setUpCleanUpHooks(); const agentControls = globalAgent.instance; @@ -93,7 +118,6 @@ mochaSuiteFn('tracing/db2', function () { describe('tracing is active', function () { before(async () => { - DB2_NAME = getDatabaseName(); TABLE_NAME_1 = generateTableName(); TABLE_NAME_2 = generateTableName(); TABLE_NAME_3 = generateTableName(); @@ -102,7 +126,9 @@ mochaSuiteFn('tracing/db2', function () { dirname: __dirname, useGlobalAgent: true, env: { - DB2_NAME, + DB2_CONN_STR, + DB2_CONN_STR_ALTERNATIVE, + DB2_DATABASE_NAME, DB2_TABLE_NAME_1: TABLE_NAME_1, DB2_TABLE_NAME_2: TABLE_NAME_2, DB2_TABLE_NAME_3: TABLE_NAME_3, @@ -111,7 +137,7 @@ mochaSuiteFn('tracing/db2', function () { }); ProcessControls.setUpTestCaseCleanUpHooks(controls); - await controls.startAndWaitForAgentConnection(); + await controls.startAndWaitForAgentConnection(retryTime); }); after(async () => { @@ -408,7 +434,7 @@ mochaSuiteFn('tracing/db2', function () { span => expect(span.f.e).to.equal(String(controls.getPid())), span => expect(span.f.h).to.equal('agent-stub-uuid'), span => expect(span.data.db2.stmt).to.equal(`SELECT * FROM ${TABLE_NAME_1}`), - span => expect(span.data.db2.dsn).to.equal(`${CONN_STR};DATABASE=${DB2_NAME}`), + span => expect(span.data.db2.dsn).to.equal(`${EXPECTED_DB2_CONN_STR};DATABASE=${DB2_DATABASE_NAME}`), span => expect(span.async).to.not.exist, span => expect(span.data.db2.error).to.eql( @@ -512,7 +538,7 @@ mochaSuiteFn('tracing/db2', function () { expect(span.data.db2.stmt).to.equal( `insert into ${TABLE_NAME_1} (COLINT, COLDATETIME, COLTEXT) VALUES (?, ?, ?)` ), - span => expect(span.data.db2.dsn).to.equal(`${CONN_STR};DATABASE=${DB2_NAME}`), + span => expect(span.data.db2.dsn).to.equal(`${EXPECTED_DB2_CONN_STR};DATABASE=${DB2_DATABASE_NAME}`), span => expect(span.async).to.not.exist, span => expect(span.data.db2.error).to.not.exist, span => expect(span.ec).to.equal(0) @@ -544,7 +570,7 @@ mochaSuiteFn('tracing/db2', function () { span => expect(span.f.h).to.equal('agent-stub-uuid'), span => expect(span.data.db2.stmt).to.equal(`insert into ${TABLE_NAME_1} values (3, null, 'something')`), - span => expect(span.data.db2.dsn).to.equal(`${CONN_STR};DATABASE=${DB2_NAME}`), + span => expect(span.data.db2.dsn).to.equal(`${EXPECTED_DB2_CONN_STR};DATABASE=${DB2_DATABASE_NAME}`), span => expect(span.async).to.not.exist, span => expect(span.data.db2.error).to.not.exist, span => expect(span.ec).to.equal(0) @@ -1055,11 +1081,41 @@ mochaSuiteFn('tracing/db2', function () { ) ); }); + + it('call two different hosts', async () => { + const response = await controls.sendRequest({ + method: 'GET', + path: '/two-different-target-hosts' + }); + + expect(response.data1).to.deep.equal([{ 1: 1 }]); + expect(response.data2).to.deep.equal([{ 1: 'a' }]); + await testUtils.retry(async () => { + const spans = await agentControls.getSpans(); + const entrySpan = testUtils.expectAtLeastOneMatching(spans, [ + span => expect(span.n).to.equal('node.http.server'), + span => expect(span.data.http.method).to.equal('GET') + ]); + testUtils.expectExactlyOneMatching(spans, [ + span => expect(span.t).to.equal(entrySpan.t), + span => expect(span.p).to.equal(entrySpan.s), + span => expect(span.n).to.equal('db2'), + span => expect(span.data.db2.stmt).to.equal('select 1 from sysibm.sysdummy1'), + span => expect(span.data.db2.dsn).to.contain(EXPECTED_DB2_CONN_STR) + ]); + testUtils.expectExactlyOneMatching(spans, [ + span => expect(span.t).to.equal(entrySpan.t), + span => expect(span.p).to.equal(entrySpan.s), + span => expect(span.n).to.equal('db2'), + span => expect(span.data.db2.stmt).to.equal("select 'a' from sysibm.sysdummy1"), + span => expect(span.data.db2.dsn).to.contain(EXPECTED_DB2_CONN_STR_ALTERNATIVE) + ]); + }); + }); }); describe('tracing is active, but suppressed', function () { before(async () => { - DB2_NAME = getDatabaseName(); TABLE_NAME_1 = generateTableName(); TABLE_NAME_2 = generateTableName(); TABLE_NAME_3 = generateTableName(); @@ -1069,7 +1125,9 @@ mochaSuiteFn('tracing/db2', function () { useGlobalAgent: true, tracingEnabled: false, env: { - DB2_NAME, + DB2_CONN_STR, + DB2_CONN_STR_ALTERNATIVE, + DB2_DATABASE_NAME, DB2_TABLE_NAME_1: TABLE_NAME_1, DB2_TABLE_NAME_2: TABLE_NAME_2, DB2_TABLE_NAME_3: TABLE_NAME_3, @@ -1078,7 +1136,7 @@ mochaSuiteFn('tracing/db2', function () { }); ProcessControls.setUpTestCaseCleanUpHooks(controls); - await controls.startAndWaitForAgentConnection(); + await controls.startAndWaitForAgentConnection(retryTime); }); after(async () => { @@ -1172,7 +1230,6 @@ mochaSuiteFn('tracing/db2', function () { describe('tracing is disabled', function () { before(async () => { - DB2_NAME = getDatabaseName(); TABLE_NAME_1 = generateTableName(); TABLE_NAME_2 = generateTableName(); TABLE_NAME_3 = generateTableName(); @@ -1182,7 +1239,9 @@ mochaSuiteFn('tracing/db2', function () { useGlobalAgent: true, tracingEnabled: false, env: { - DB2_NAME, + DB2_CONN_STR, + DB2_CONN_STR_ALTERNATIVE, + DB2_DATABASE_NAME, DB2_TABLE_NAME_1: TABLE_NAME_1, DB2_TABLE_NAME_2: TABLE_NAME_2, DB2_TABLE_NAME_3: TABLE_NAME_3, @@ -1191,7 +1250,7 @@ mochaSuiteFn('tracing/db2', function () { }); ProcessControls.setUpTestCaseCleanUpHooks(controls); - await controls.startAndWaitForAgentConnection(); + await controls.startAndWaitForAgentConnection(retryTime); }); after(async () => { diff --git a/packages/core/src/tracing/instrumentation/database/db2.js b/packages/core/src/tracing/instrumentation/database/db2.js index d0912cbb1f..3e95a41055 100644 --- a/packages/core/src/tracing/instrumentation/database/db2.js +++ b/packages/core/src/tracing/instrumentation/database/db2.js @@ -12,7 +12,6 @@ const constants = require('../../constants'); const cls = require('../../cls'); let isActive = false; -let connectionStr; const CLOSE_TIMEOUT_IN_MS = process.env.DB2_CLOSE_TIMEOUT_IN_MS || 1000 * 30; @@ -62,7 +61,7 @@ function instrumentOpen(originalFunction) { // NOTE: connection.open(fn) will throw an error in the library // we can rely on arguments[0] being the connection string. // There is no other format to pass in the connection. - connectionStr = arguments[0]; + this._instanaConnectionString = arguments[0]; return originalFunction.apply(this, arguments); }; } @@ -247,7 +246,7 @@ function instrumentQueryHelper(ctx, originalArgs, originalFunction, stmt, isAsyn } return cls.ns.runAndReturn(() => { - const span = createSpan(stmt, instrumentQueryHelper); + const span = createSpan(stmt, instrumentQueryHelper, ctx._instanaConnectionString); // CASE: querySync if (!isAsync) { @@ -356,7 +355,7 @@ function instrumentExecuteHelper(ctx, originalArgs, stmtObject, prepareCallParen return originalExecuteNonQuerySync.apply(this, arguments); } - const span = createSpan(originalArgs[0], instrumentExecuteHelper); + const span = createSpan(originalArgs[0], instrumentExecuteHelper, ctx._instanaConnectionString); // NOTE: returns row count try { @@ -380,7 +379,7 @@ function instrumentExecuteHelper(ctx, originalArgs, stmtObject, prepareCallParen } // NOTE: start one span per execute! - const span = createSpan(originalArgs[0], instrumentExecuteHelper); + const span = createSpan(originalArgs[0], instrumentExecuteHelper, ctx._instanaConnectionString); const result = originalExecuteSync.apply(this, arguments); finishSpan(ctx, result, span); @@ -397,7 +396,7 @@ function instrumentExecuteHelper(ctx, originalArgs, stmtObject, prepareCallParen } // NOTE: start one span per execute! - const span = createSpan(originalArgs[0], instrumentExecuteHelper); + const span = createSpan(originalArgs[0], instrumentExecuteHelper, ctx._instanaConnectionString); const args = arguments; const origCallbackIndex = @@ -432,7 +431,7 @@ function instrumentQueryResultHelper(ctx, originalArgs, originalFunction, stmt, } return cls.ns.runAndReturn(() => { - const span = createSpan(stmt, instrumentQueryResultHelper); + const span = createSpan(stmt, instrumentQueryResultHelper, ctx._instanaConnectionString); if (!isAsync) { try { @@ -473,7 +472,7 @@ function instrumentQueryResultHelper(ctx, originalArgs, originalFunction, stmt, }); } -function createSpan(stmt, fn) { +function createSpan(stmt, fn, connectionStr) { // eslint-disable-next-line max-len // https://github.ibm.com/instana/backend/blob/develop/forge/src/main/java/com/instana/forge/connection/database/ibmdb2/IbmDb2Span.java const span = cls.startSpan(exports.spanName, constants.EXIT);