diff --git a/test/lib/custom-assertions.js b/test/lib/custom-assertions.js index 2b1b10515c..522cff3b26 100644 --- a/test/lib/custom-assertions.js +++ b/test/lib/custom-assertions.js @@ -5,6 +5,7 @@ 'use strict' const assert = require('node:assert') +const { isSimpleObject } = require('../../lib/util/objects') function assertExactClmAttrs(segmentStub, expectedAttrs) { const attrs = segmentStub.addAttribute.args @@ -232,9 +233,101 @@ function match(actual, expected) { return true } +/** + * @param {Metrics} metrics metrics under test + * @param {Array} expected Array of metric data where metric data is in this form: + * [ + * { + * “name”:”name of metric”, + * “scope”:”scope of metric”, + * }, + * [count, + * total time, + * exclusive time, + * min time, + * max time, + * sum of squares] + * ] + * @param {boolean} exclusive When true, found and expected metric lengths should match + * @param {boolean} assertValues When true, metric values must match expected + */ +function assertMetrics(metrics, expected, exclusive, assertValues) { + // Assertions about arguments because maybe something returned undefined + // unexpectedly and is passed in, or a return type changed. This will + // hopefully help catch that and make it obvious. + assert.ok(isSimpleObject(metrics), 'first argument required to be an Metrics object') + assert.ok(Array.isArray(expected), 'second argument required to be an array of metrics') + assert.ok(typeof exclusive === 'boolean', 'third argument required to be a boolean if provided') + + if (assertValues === undefined) { + assertValues = true + } + + for (let i = 0, len = expected.length; i < len; i++) { + const expectedMetric = expected[i] + const metric = metrics.getMetric(expectedMetric[0].name, expectedMetric[0].scope) + assert.ok(metric, `should find ${expectedMetric[0].name}`) + if (assertValues) { + assert.deepEqual(metric.toJSON(), expectedMetric[1]) + } + } + + if (exclusive) { + const metricsList = metrics.toJSON() + assert.equal(metricsList.length, expected.length) + } +} + +/** + * @param {Transaction} transaction Nodejs agent transaction + * @param {Array} expected Array of metric data where metric data is in this form: + * [ + * { + * “name”:”name of metric”, + * “scope”:”scope of metric”, + * }, + * [count, + * total time, + * exclusive time, + * min time, + * max time, + * sum of squares] + * ] + * @param {boolean} exact When true, found and expected metric lengths should match + */ +function assertMetricValues(transaction, expected, exact) { + const metrics = transaction.metrics + + for (let i = 0; i < expected.length; ++i) { + let expectedMetric = Object.assign({}, expected[i]) + let name = null + let scope = null + + if (typeof expectedMetric === 'string') { + name = expectedMetric + expectedMetric = {} + } else { + name = expectedMetric[0].name + scope = expectedMetric[0].scope + } + + const metric = metrics.getMetric(name, scope) + assert.ok(metric, 'should have expected metric name') + + assert.deepStrictEqual(metric.toJSON(), expectedMetric[1], 'metric values should match') + } + + if (exact) { + const metricsJSON = metrics.toJSON() + assert.equal(metricsJSON.length, expected.length, 'metrics length should match') + } +} + module.exports = { assertCLMAttrs, assertExactClmAttrs, + assertMetrics, + assertMetricValues, assertSegments, compareSegments, isNonWritable, diff --git a/test/unit/metric/datastore-instance.test.js b/test/unit/metric/datastore-instance.test.js index 2f4d91f0ce..243527b194 100644 --- a/test/unit/metric/datastore-instance.test.js +++ b/test/unit/metric/datastore-instance.test.js @@ -5,29 +5,29 @@ 'use strict' -const tap = require('tap') - +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') const DatastoreShim = require('../../../lib/shim/datastore-shim') const tests = require('../../lib/cross_agent_tests/datastores/datastore_instances') const DatastoreParameters = require('../../../lib/shim/specs/params/datastore') -tap.test('Datastore instance metrics collected via the datastore shim', function (t) { - t.autoend() - t.beforeEach(function (t) { - t.context.agent = helper.loadMockedAgent() +test('Datastore instance metrics collected via the datastore shim', async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} + ctx.nr.agent = helper.loadMockedAgent() }) - t.afterEach(function (t) { - const { agent } = t.context + t.afterEach(function (ctx) { + const { agent } = ctx.nr if (agent) { helper.unloadAgent(agent) } }) - tests.forEach(function (test) { - t.test(test.name, function (t) { - const { agent } = t.context + for (const test of tests) { + await t.test(test.name, function (t, end) { + const { agent } = t.nr agent.config.getHostnameSafe = function () { return test.system_hostname } @@ -65,11 +65,11 @@ tap.test('Datastore instance metrics collected via the datastore shim', function testInstrumented.query() tx.end() - t.ok(getMetrics(agent).unscoped[test.expected_instance_metric]) - t.end() + assert.ok(getMetrics(agent).unscoped[test.expected_instance_metric]) + end() }) }) - }) + } }) function getMetrics(agent) { diff --git a/test/unit/metric/metric-aggregator.test.js b/test/unit/metric/metric-aggregator.test.js index 67ad0414c8..d32d5dd036 100644 --- a/test/unit/metric/metric-aggregator.test.js +++ b/test/unit/metric/metric-aggregator.test.js @@ -4,7 +4,8 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const sinon = require('sinon') const MetricAggregator = require('../../../lib/metrics/metric-aggregator') const MetricMapper = require('../../../lib/metrics/mapper') @@ -17,54 +18,53 @@ const EXPECTED_APDEX_T = 0.1 const EXPECTED_START_SECONDS = 10 const MEGABYTE = 1024 * 1024 -tap.test('Metric Aggregator', (t) => { - t.beforeEach((t) => { - t.context.testClock = sinon.useFakeTimers({ now: EXPECTED_START_SECONDS * 1000 }) +test('Metric Aggregator', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + ctx.nr.testClock = sinon.useFakeTimers({ now: EXPECTED_START_SECONDS * 1000 }) const fakeCollectorApi = { send: sinon.stub() } const fakeHarvester = { add: sinon.stub() } - t.context.mapper = new MetricMapper() - t.context.normalizer = new MetricNormalizer({}, 'metric name') + ctx.nr.mapper = new MetricMapper() + ctx.nr.normalizer = new MetricNormalizer({}, 'metric name') - t.context.metricAggregator = new MetricAggregator( + ctx.nr.metricAggregator = new MetricAggregator( { runId: RUN_ID, apdexT: EXPECTED_APDEX_T, - mapper: t.context.mapper, - normalizer: t.context.normalizer + mapper: ctx.nr.mapper, + normalizer: ctx.nr.normalizer }, fakeCollectorApi, fakeHarvester ) }) - t.afterEach((t) => { - const { testClock } = t.context + t.afterEach((ctx) => { + const { testClock } = ctx.nr testClock.restore() }) - t.test('should set the correct default method', (t) => { - const { metricAggregator } = t.context + await t.test('should set the correct default method', (t) => { + const { metricAggregator } = t.nr const method = metricAggregator.method - t.equal(method, EXPECTED_METHOD) - t.end() + assert.equal(method, EXPECTED_METHOD) }) - t.test('should update runId on reconfigure', (t) => { - const { metricAggregator } = t.context + await t.test('should update runId on reconfigure', (t) => { + const { metricAggregator } = t.nr const expectedRunId = 'new run id' const fakeConfig = { run_id: expectedRunId } metricAggregator.reconfigure(fakeConfig) - t.equal(metricAggregator.runId, expectedRunId) - t.end() + assert.equal(metricAggregator.runId, expectedRunId) }) - t.test('should update apdexT on reconfigure', (t) => { - const { metricAggregator } = t.context + await t.test('should update apdexT on reconfigure', (t) => { + const { metricAggregator } = t.nr const expectedApdexT = 2000 const fakeConfig = { apdex_t: expectedApdexT @@ -72,51 +72,46 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.reconfigure(fakeConfig) - t.equal(metricAggregator._apdexT, expectedApdexT) - t.equal(metricAggregator._metrics.apdexT, expectedApdexT) - t.end() + assert.equal(metricAggregator._apdexT, expectedApdexT) + assert.equal(metricAggregator._metrics.apdexT, expectedApdexT) }) - t.test('should be true when no metrics added', (t) => { - const { metricAggregator } = t.context - t.equal(metricAggregator.empty, true) - t.end() + await t.test('should be true when no metrics added', (t) => { + const { metricAggregator } = t.nr + assert.equal(metricAggregator.empty, true) }) - t.test('should be false when metrics added', (t) => { - const { metricAggregator } = t.context + await t.test('should be false when metrics added', (t) => { + const { metricAggregator } = t.nr metricAggregator.getOrCreateMetric('myMetric') - t.equal(metricAggregator.empty, false) - t.end() + assert.equal(metricAggregator.empty, false) }) - t.test('should reflect when new metric collection started', (t) => { - const { metricAggregator } = t.context - t.equal(metricAggregator.started, metricAggregator._metrics.started) - t.end() + await t.test('should reflect when new metric collection started', (t) => { + const { metricAggregator } = t.nr + assert.equal(metricAggregator.started, metricAggregator._metrics.started) }) - t.test('_getMergeData() should return mergable metric collection', (t) => { - const { metricAggregator } = t.context + await t.test('_getMergeData() should return mergable metric collection', (t) => { + const { metricAggregator } = t.nr metricAggregator.getOrCreateMetric('metric1', 'scope1') metricAggregator.getOrCreateMetric('metric2') const data = metricAggregator._getMergeData() - t.ok(data.started) - t.equal(data.empty, false) + assert.ok(data.started) + assert.equal(data.empty, false) const unscoped = data.unscoped - t.ok(unscoped.metric2) + assert.ok(unscoped.metric2) const scoped = data.scoped - t.ok(scoped.scope1) + assert.ok(scoped.scope1) - t.ok(scoped.scope1.metric1) - t.end() + assert.ok(scoped.scope1.metric1) }) - t.test('_toPayloadSync() should return json format of data', (t) => { - const { metricAggregator, testClock } = t.context + await t.test('_toPayloadSync() should return json format of data', (t) => { + const { metricAggregator, testClock } = t.nr const secondsToElapse = 5 const expectedMetricName = 'myMetric' @@ -130,29 +125,28 @@ tap.test('Metric Aggregator', (t) => { const payload = metricAggregator._toPayloadSync() - t.equal(payload.length, 4) + assert.equal(payload.length, 4) const [runId, startTime, endTime, metricData] = payload - t.equal(runId, RUN_ID) - t.equal(startTime, EXPECTED_START_SECONDS) - t.equal(endTime, expectedEndSeconds) + assert.equal(runId, RUN_ID) + assert.equal(startTime, EXPECTED_START_SECONDS) + assert.equal(endTime, expectedEndSeconds) const firstMetric = metricData[0] - t.equal(firstMetric.length, 2) + assert.equal(firstMetric.length, 2) const [metricName, metricStats] = firstMetric - t.equal(metricName.name, expectedMetricName) - t.equal(metricName.scope, expectedMetricScope) + assert.equal(metricName.name, expectedMetricName) + assert.equal(metricName.scope, expectedMetricScope) // Before sending, we rely on the Stats toJSON to put in the right format - t.same(metricStats.toJSON(), [1, 22, 21, 22, 22, 484]) - t.end() + assert.deepEqual(metricStats.toJSON(), [1, 22, 21, 22, 22, 484]) }) - t.test('_toPayload() should return json format of data', (t) => { - const { metricAggregator, testClock } = t.context + await t.test('_toPayload() should return json format of data', (t, end) => { + const { metricAggregator, testClock } = t.nr const secondsToElapse = 5 const expectedMetricName = 'myMetric' @@ -165,30 +159,30 @@ tap.test('Metric Aggregator', (t) => { const expectedEndSeconds = EXPECTED_START_SECONDS + secondsToElapse metricAggregator._toPayload((err, payload) => { - t.equal(payload.length, 4) + assert.equal(payload.length, 4) const [runId, startTime, endTime, metricData] = payload - t.equal(runId, RUN_ID) - t.equal(startTime, EXPECTED_START_SECONDS) - t.equal(endTime, expectedEndSeconds) + assert.equal(runId, RUN_ID) + assert.equal(startTime, EXPECTED_START_SECONDS) + assert.equal(endTime, expectedEndSeconds) const firstMetric = metricData[0] - t.equal(firstMetric.length, 2) + assert.equal(firstMetric.length, 2) const [metricName, metricStats] = firstMetric - t.equal(metricName.name, expectedMetricName) - t.equal(metricName.scope, expectedMetricScope) + assert.equal(metricName.name, expectedMetricName) + assert.equal(metricName.scope, expectedMetricScope) // Before sending, we rely on the Stats toJSON to put in the right format - t.same(metricStats.toJSON(), [1, 22, 21, 22, 22, 484]) - t.end() + assert.deepEqual(metricStats.toJSON(), [1, 22, 21, 22, 22, 484]) + end() }) }) - t.test('_merge() should merge passed in metrics', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('_merge() should merge passed in metrics', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr const expectedMetricName = 'myMetric' const expectedMetricScope = 'myScope' @@ -201,24 +195,23 @@ tap.test('Metric Aggregator', (t) => { metricAggregator._merge(mergeData) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) const newUnscopedMetric = metricAggregator.getMetric('newMetric') - t.equal(newUnscopedMetric.callCount, 1) + assert.equal(newUnscopedMetric.callCount, 1) const mergedScopedMetric = metricAggregator.getMetric(expectedMetricName, expectedMetricScope) - t.equal(mergedScopedMetric.callCount, 2) - t.equal(mergedScopedMetric.min, 2) - t.equal(mergedScopedMetric.max, 4) - t.equal(mergedScopedMetric.total, 6) - t.equal(mergedScopedMetric.totalExclusive, 3) - t.equal(mergedScopedMetric.sumOfSquares, 20) - t.end() + assert.equal(mergedScopedMetric.callCount, 2) + assert.equal(mergedScopedMetric.min, 2) + assert.equal(mergedScopedMetric.max, 4) + assert.equal(mergedScopedMetric.total, 6) + assert.equal(mergedScopedMetric.totalExclusive, 3) + assert.equal(mergedScopedMetric.sumOfSquares, 20) }) - t.test('_merge() should choose the lowest started', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('_merge() should choose the lowest started', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr metricAggregator.getOrCreateMetric('metric1').incrementCallCount() const mergeData = new Metrics(EXPECTED_APDEX_T, mapper, normalizer) @@ -229,33 +222,31 @@ tap.test('Metric Aggregator', (t) => { metricAggregator._merge(mergeData) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) - t.equal(metricAggregator.started, mergeData.started) - t.end() + assert.equal(metricAggregator.started, mergeData.started) }) - t.test('clear() should clear metrics', (t) => { - const { metricAggregator } = t.context + await t.test('clear() should clear metrics', (t) => { + const { metricAggregator } = t.nr metricAggregator.getOrCreateMetric('metric1', 'scope1').incrementCallCount() metricAggregator.getOrCreateMetric('metric2').incrementCallCount() - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) metricAggregator.clear() - t.equal(metricAggregator.empty, true) + assert.equal(metricAggregator.empty, true) const metric1 = metricAggregator.getMetric('metric1', 'scope1') - t.notOk(metric1) + assert.ok(!metric1) const metric2 = metricAggregator.getMetric('metric2') - t.notOk(metric2) - t.end() + assert.ok(!metric2) }) - t.test('clear() should reset started', (t) => { - const { metricAggregator, testClock } = t.context + await t.test('clear() should reset started', (t) => { + const { metricAggregator, testClock } = t.nr const msToElapse = 5000 const originalStarted = metricAggregator.started @@ -263,7 +254,7 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.getOrCreateMetric('metric1', 'scope1').incrementCallCount() metricAggregator.getOrCreateMetric('metric2').incrementCallCount() - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) testClock.tick(msToElapse) @@ -271,15 +262,14 @@ tap.test('Metric Aggregator', (t) => { const newStarted = metricAggregator.started - t.ok(newStarted > originalStarted) + assert.ok(newStarted > originalStarted) const expectedNewStarted = originalStarted + msToElapse - t.equal(newStarted, expectedNewStarted) - t.end() + assert.equal(newStarted, expectedNewStarted) }) - t.test('merge() should merge passed in metrics', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('merge() should merge passed in metrics', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr const expectedMetricName = 'myMetric' const expectedMetricScope = 'myScope' @@ -292,24 +282,23 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.merge(mergeData) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) const newUnscopedMetric = metricAggregator.getMetric('newMetric') - t.equal(newUnscopedMetric.callCount, 1) + assert.equal(newUnscopedMetric.callCount, 1) const mergedScopedMetric = metricAggregator.getMetric(expectedMetricName, expectedMetricScope) - t.equal(mergedScopedMetric.callCount, 2) - t.equal(mergedScopedMetric.min, 2) - t.equal(mergedScopedMetric.max, 4) - t.equal(mergedScopedMetric.total, 6) - t.equal(mergedScopedMetric.totalExclusive, 3) - t.equal(mergedScopedMetric.sumOfSquares, 20) - t.end() + assert.equal(mergedScopedMetric.callCount, 2) + assert.equal(mergedScopedMetric.min, 2) + assert.equal(mergedScopedMetric.max, 4) + assert.equal(mergedScopedMetric.total, 6) + assert.equal(mergedScopedMetric.totalExclusive, 3) + assert.equal(mergedScopedMetric.sumOfSquares, 20) }) - t.test('merge() should not adjust start time when not passed', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('merge() should not adjust start time when not passed', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr const originalStarted = metricAggregator.started metricAggregator.getOrCreateMetric('metric1').incrementCallCount() @@ -322,14 +311,13 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.merge(mergeData) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) - t.equal(metricAggregator.started, originalStarted) - t.end() + assert.equal(metricAggregator.started, originalStarted) }) - t.test('merge() should not adjust start time when adjustStartTime false', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('merge() should not adjust start time when adjustStartTime false', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr const originalStarted = metricAggregator.started metricAggregator.getOrCreateMetric('metric1').incrementCallCount() @@ -342,14 +330,13 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.merge(mergeData, false) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) - t.equal(metricAggregator.started, originalStarted) - t.end() + assert.equal(metricAggregator.started, originalStarted) }) - t.test('merge() should choose lowest started when adjustStartTime true', (t) => { - const { metricAggregator, mapper, normalizer } = t.context + await t.test('merge() should choose lowest started when adjustStartTime true', (t) => { + const { metricAggregator, mapper, normalizer } = t.nr metricAggregator.getOrCreateMetric('metric1').incrementCallCount() const mergeData = new Metrics(EXPECTED_APDEX_T, mapper, normalizer) @@ -360,83 +347,77 @@ tap.test('Metric Aggregator', (t) => { metricAggregator.merge(mergeData, true) - t.equal(metricAggregator.empty, false) + assert.equal(metricAggregator.empty, false) - t.equal(metricAggregator.started, mergeData.started) - t.end() + assert.equal(metricAggregator.started, mergeData.started) }) - t.test('getOrCreateMetric() should return value from metrics collection', (t) => { - const { metricAggregator } = t.context + await t.test('getOrCreateMetric() should return value from metrics collection', (t) => { + const { metricAggregator } = t.nr const spy = sinon.spy(metricAggregator._metrics, 'getOrCreateMetric') const metric = metricAggregator.getOrCreateMetric('newMetric') metric.incrementCallCount() - t.equal(metric.callCount, 1) + assert.equal(metric.callCount, 1) - t.equal(spy.calledOnce, true) - t.end() + assert.equal(spy.calledOnce, true) }) - t.test('measureMilliseconds should return value from metrics collection', (t) => { - const { metricAggregator } = t.context + await t.test('measureMilliseconds should return value from metrics collection', (t) => { + const { metricAggregator } = t.nr const spy = sinon.spy(metricAggregator._metrics, 'measureMilliseconds') const metric = metricAggregator.measureMilliseconds('metric', 'scope', 2000, 1000) - t.ok(metric) + assert.ok(metric) - t.equal(metric.callCount, 1) - t.equal(metric.total, 2) - t.equal(metric.totalExclusive, 1) + assert.equal(metric.callCount, 1) + assert.equal(metric.total, 2) + assert.equal(metric.totalExclusive, 1) - t.equal(spy.calledOnce, true) - t.end() + assert.equal(spy.calledOnce, true) }) - t.test('measureBytes should return value from metrics collection', (t) => { - const { metricAggregator } = t.context + await t.test('measureBytes should return value from metrics collection', (t) => { + const { metricAggregator } = t.nr const spy = sinon.spy(metricAggregator._metrics, 'measureBytes') const metric = metricAggregator.measureBytes('metric', MEGABYTE) - t.ok(metric) + assert.ok(metric) - t.equal(metric.callCount, 1) - t.equal(metric.total, 1) - t.equal(metric.totalExclusive, 1) + assert.equal(metric.callCount, 1) + assert.equal(metric.total, 1) + assert.equal(metric.totalExclusive, 1) - t.equal(spy.calledOnce, true) - t.end() + assert.equal(spy.calledOnce, true) }) - t.test('measureBytes should record exclusive bytes', (t) => { - const { metricAggregator } = t.context + await t.test('measureBytes should record exclusive bytes', (t) => { + const { metricAggregator } = t.nr const metric = metricAggregator.measureBytes('metric', MEGABYTE * 2, MEGABYTE) - t.ok(metric) + assert.ok(metric) - t.equal(metric.callCount, 1) - t.equal(metric.total, 2) - t.equal(metric.totalExclusive, 1) - t.end() + assert.equal(metric.callCount, 1) + assert.equal(metric.total, 2) + assert.equal(metric.totalExclusive, 1) }) - t.test('measureBytes should optionally not convert to megabytes', (t) => { - const { metricAggregator } = t.context + await t.test('measureBytes should optionally not convert to megabytes', (t) => { + const { metricAggregator } = t.nr const metric = metricAggregator.measureBytes('metric', 2, 1, true) - t.ok(metric) + assert.ok(metric) - t.equal(metric.callCount, 1) - t.equal(metric.total, 2) - t.equal(metric.totalExclusive, 1) - t.end() + assert.equal(metric.callCount, 1) + assert.equal(metric.total, 2) + assert.equal(metric.totalExclusive, 1) }) - t.test('getMetric() should return value from metrics collection', (t) => { - const { metricAggregator } = t.context + await t.test('getMetric() should return value from metrics collection', (t) => { + const { metricAggregator } = t.nr const expectedName = 'name1' const expectedScope = 'scope1' @@ -446,23 +427,20 @@ tap.test('Metric Aggregator', (t) => { const metric = metricAggregator.getMetric(expectedName, expectedScope) - t.ok(metric) - t.equal(metric.callCount, 1) + assert.ok(metric) + assert.equal(metric.callCount, 1) - t.equal(spy.calledOnce, true) - t.end() + assert.equal(spy.calledOnce, true) }) - t.test('getOrCreateApdexMetric() should return value from metrics collection', (t) => { - const { metricAggregator } = t.context + await t.test('getOrCreateApdexMetric() should return value from metrics collection', (t) => { + const { metricAggregator } = t.nr const spy = sinon.spy(metricAggregator._metrics, 'getOrCreateApdexMetric') const metric = metricAggregator.getOrCreateApdexMetric('metric1', 'scope1') - t.equal(metric.apdexT, EXPECTED_APDEX_T) + assert.equal(metric.apdexT, EXPECTED_APDEX_T) - t.equal(spy.calledOnce, true) - t.end() + assert.equal(spy.calledOnce, true) }) - t.end() }) diff --git a/test/unit/metric/metrics.test.js b/test/unit/metric/metrics.test.js index 8dd7c65d9a..6a07eccdd3 100644 --- a/test/unit/metric/metrics.test.js +++ b/test/unit/metric/metrics.test.js @@ -4,206 +4,219 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') const Metrics = require('../../../lib/metrics') const MetricMapper = require('../../../lib/metrics/mapper') const MetricNormalizer = require('../../../lib/metrics/normalizer') -function beforeEach(t) { +function beforeEach(ctx) { + ctx.nr = {} const agent = helper.loadMockedAgent() - t.context.metrics = new Metrics(agent.config.apdex_t, agent.mapper, agent.metricNameNormalizer) - t.context.agent = agent + ctx.nr.metrics = new Metrics(agent.config.apdex_t, agent.mapper, agent.metricNameNormalizer) + ctx.nr.agent = agent } -function afterEach(t) { - helper.unloadAgent(t.context.agent) +function afterEach(ctx) { + helper.unloadAgent(ctx.nr.agent) } -tap.test('Metrics', function (t) { - t.autoend() - t.test('when creating', function (t) { - t.autoend() +test('Metrics', async function (t) { + await t.test('when creating', async function (t) { t.beforeEach(beforeEach) t.afterEach(afterEach) - t.test('should throw if apdexT is not set', function (t) { - const { agent } = t.context - t.throws(function () { + await t.test('should throw if apdexT is not set', function (t, end) { + const { agent } = t.nr + assert.throws(function () { // eslint-disable-next-line no-new new Metrics(undefined, agent.mapper, agent.metricNameNormalizer) }) - t.end() + end() }) - t.test('should throw if no name -> ID mapper is provided', function (t) { - const { agent } = t.context - t.throws(function () { + await t.test('should throw if no name -> ID mapper is provided', function (t, end) { + const { agent } = t.nr + assert.throws(function () { // eslint-disable-next-line no-new new Metrics(agent.config.apdex_t, undefined, agent.metricNameNormalizer) }) - t.end() + end() }) - t.test('should throw if no metric name normalizer is provided', function (t) { - const { agent } = t.context - t.throws(function () { + await t.test('should throw if no metric name normalizer is provided', function (t, end) { + const { agent } = t.nr + assert.throws(function () { // eslint-disable-next-line no-new new Metrics(agent.config.apdex_t, agent.mapper, undefined) }) - t.end() + end() }) - t.test('should return apdex summaries with an apdexT same as config', function (t) { - const { metrics, agent } = t.context + await t.test('should return apdex summaries with an apdexT same as config', function (t, end) { + const { metrics, agent } = t.nr const metric = metrics.getOrCreateApdexMetric('Apdex/MetricsTest') - t.equal(metric.apdexT, agent.config.apdex_t) - t.end() + assert.equal(metric.apdexT, agent.config.apdex_t) + end() }) - t.test('should allow overriding apdex summaries with a custom apdexT', function (t) { - const { metrics } = t.context + await t.test('should allow overriding apdex summaries with a custom apdexT', function (t, end) { + const { metrics } = t.nr const metric = metrics.getOrCreateApdexMetric('Apdex/MetricsTest', null, 1) - t.equal(metric.apdexT, 0.001) - t.end() + assert.equal(metric.apdexT, 0.001) + end() }) - t.test('should require the overriding apdex to be greater than 0', function (t) { - const { metrics, agent } = t.context + await t.test('should require the overriding apdex to be greater than 0', function (t, end) { + const { metrics, agent } = t.nr const metric = metrics.getOrCreateApdexMetric('Apdex/MetricsTest', null, 0) - t.equal(metric.apdexT, agent.config.apdex_t) - t.end() + assert.equal(metric.apdexT, agent.config.apdex_t) + end() }) - t.test('should require the overriding apdex to not be negative', function (t) { - const { metrics, agent } = t.context + await t.test('should require the overriding apdex to not be negative', function (t, end) { + const { metrics, agent } = t.nr const metric = metrics.getOrCreateApdexMetric('Apdex/MetricsTest', null, -5000) - t.equal(metric.apdexT, agent.config.apdex_t) - t.end() - }) - - t.test('when creating individual apdex metrics should have apdex functions', function (t) { - const { metrics } = t.context - const metric = metrics.getOrCreateApdexMetric('Agent/ApdexTest') - t.ok(metric.incrementFrustrating) - t.end() - }) - - t.test('should measure an unscoped metric', function (t) { - const { metrics } = t.context + assert.equal(metric.apdexT, agent.config.apdex_t) + end() + }) + + await t.test( + 'when creating individual apdex metrics should have apdex functions', + function (t, end) { + const { metrics } = t.nr + const metric = metrics.getOrCreateApdexMetric('Agent/ApdexTest') + assert.ok(metric.incrementFrustrating) + end() + } + ) + + await t.test('should measure an unscoped metric', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('Test/Metric', null, 400, 200) - t.equal( + assert.equal( JSON.stringify(metrics.toJSON()), '[[{"name":"Test/Metric"},[1,0.4,0.2,0.4,0.4,0.16000000000000003]]]' ) - t.end() + end() }) - t.test('should measure a scoped metric', function (t) { - const { metrics } = t.context + await t.test('should measure a scoped metric', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('T/M', 'T', 400, 200) - t.equal( + assert.equal( JSON.stringify(metrics.toJSON()), '[[{"name":"T/M","scope":"T"},[1,0.4,0.2,0.4,0.4,0.16000000000000003]]]' ) - t.end() - }) - - t.test('should resolve the correctly scoped set of metrics when scope passed', function (t) { - const { metrics } = t.context - metrics.measureMilliseconds('Apdex/ScopedMetricsTest', 'TEST') - const scoped = metrics._resolve('TEST') - - t.ok(scoped['Apdex/ScopedMetricsTest']) - t.end() - }) - - t.test('should implicitly create a blank set of metrics when resolving new scope', (t) => { - const { metrics } = t.context - const scoped = metrics._resolve('NOEXISTBRO') - - t.ok(scoped) - t.equal(Object.keys(scoped).length, 0) - t.end() - }) - - t.test('should return a preëxisting unscoped metric when it is requested', function (t) { - const { metrics } = t.context + end() + }) + + await t.test( + 'should resolve the correctly scoped set of metrics when scope passed', + function (t, end) { + const { metrics } = t.nr + metrics.measureMilliseconds('Apdex/ScopedMetricsTest', 'TEST') + const scoped = metrics._resolve('TEST') + + assert.ok(scoped['Apdex/ScopedMetricsTest']) + end() + } + ) + + await t.test( + 'should implicitly create a blank set of metrics when resolving new scope', + (t, end) => { + const { metrics } = t.nr + const scoped = metrics._resolve('NOEXISTBRO') + + assert.ok(scoped) + assert.equal(Object.keys(scoped).length, 0) + end() + } + ) + + await t.test( + 'should return a preëxisting unscoped metric when it is requested', + function (t, end) { + const { metrics } = t.nr + metrics.measureMilliseconds('Test/UnscopedMetric', null, 400, 200) + assert.equal(metrics.getOrCreateMetric('Test/UnscopedMetric').callCount, 1) + end() + } + ) + + await t.test( + 'should return a preëxisting scoped metric when it is requested', + function (t, end) { + const { metrics } = t.nr + metrics.measureMilliseconds('Test/Metric', 'TEST', 400, 200) + assert.equal(metrics.getOrCreateMetric('Test/Metric', 'TEST').callCount, 1) + end() + } + ) + + await t.test('should return the unscoped metrics when scope not set', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('Test/UnscopedMetric', null, 400, 200) - t.equal(metrics.getOrCreateMetric('Test/UnscopedMetric').callCount, 1) - t.end() + assert.equal(Object.keys(metrics._resolve()).length, 1) + assert.equal(Object.keys(metrics.scoped).length, 0) + end() }) - t.test('should return a preëxisting scoped metric when it is requested', function (t) { - const { metrics } = t.context - metrics.measureMilliseconds('Test/Metric', 'TEST', 400, 200) - t.equal(metrics.getOrCreateMetric('Test/Metric', 'TEST').callCount, 1) - t.end() - }) - - t.test('should return the unscoped metrics when scope not set', function (t) { - const { metrics } = t.context - metrics.measureMilliseconds('Test/UnscopedMetric', null, 400, 200) - t.equal(Object.keys(metrics._resolve()).length, 1) - t.equal(Object.keys(metrics.scoped).length, 0) - t.end() - }) - - t.test('should measure bytes ok', function (t) { - const { metrics } = t.context + await t.test('should measure bytes ok', function (t, end) { + const { metrics } = t.nr const MEGABYTE = 1024 * 1024 const stat = metrics.measureBytes('Test/Bytes', MEGABYTE) - t.equal(stat.total, 1) - t.equal(stat.totalExclusive, 1) - t.end() + assert.equal(stat.total, 1) + assert.equal(stat.totalExclusive, 1) + end() }) - t.test('should measure exclusive bytes ok', function (t) { - const { metrics } = t.context + await t.test('should measure exclusive bytes ok', function (t, end) { + const { metrics } = t.nr const MEGABYTE = 1024 * 1024 const stat = metrics.measureBytes('Test/Bytes', MEGABYTE * 2, MEGABYTE) - t.equal(stat.total, 2) - t.equal(stat.totalExclusive, 1) - t.end() + assert.equal(stat.total, 2) + assert.equal(stat.totalExclusive, 1) + end() }) - t.test('should optionally not convert bytes to megabytes', function (t) { - const { metrics } = t.context + await t.test('should optionally not convert bytes to megabytes', function (t, end) { + const { metrics } = t.nr const MEGABYTE = 1024 * 1024 const stat = metrics.measureBytes('Test/Bytes', MEGABYTE * 2, MEGABYTE, true) - t.equal(stat.total, MEGABYTE * 2) - t.equal(stat.totalExclusive, MEGABYTE) - t.end() + assert.equal(stat.total, MEGABYTE * 2) + assert.equal(stat.totalExclusive, MEGABYTE) + end() }) }) - t.test('when creating individual metrics', function (t) { - t.autoend() + await t.test('when creating individual metrics', async function (t) { t.beforeEach(beforeEach) t.afterEach(afterEach) - t.test('should create a metric when a nonexistent name is requested', function (t) { - const { metrics } = t.context + await t.test('should create a metric when a nonexistent name is requested', function (t, end) { + const { metrics } = t.nr const metric = metrics.getOrCreateMetric('Test/Nonexistent', 'TEST') - t.equal(metric.callCount, 0) - t.end() + assert.equal(metric.callCount, 0) + end() }) - t.test('should have statistics available', function (t) { - const { metrics } = t.context + await t.test('should have statistics available', function (t, end) { + const { metrics } = t.nr const metric = metrics.getOrCreateMetric('Agent/Test') - t.equal(metric.callCount, 0) - t.end() + assert.equal(metric.callCount, 0) + end() }) - t.test('should have have regular functions', function (t) { - const { metrics } = t.context + await t.test('should have have regular functions', function (t, end) { + const { metrics } = t.nr const metric = metrics.getOrCreateMetric('Agent/StatsTest') - t.equal(metric.callCount, 0) - t.end() + assert.equal(metric.callCount, 0) + end() }) }) - t.test('when creating with parameters', function (t) { - t.autoend() + await t.test('when creating with parameters', async function (t) { const TEST_APDEX = 0.4 const TEST_MAPPER = new MetricMapper([[{ name: 'Renamed/333' }, 1337]]) const TEST_NORMALIZER = new MetricNormalizer({ enforce_backstop: true }, 'metric name') @@ -211,145 +224,145 @@ tap.test('Metrics', function (t) { t.beforeEach(function (t) { beforeEach(t) TEST_NORMALIZER.addSimple(/^Test\/RenameMe(.*)$/, 'Renamed/$1') - t.context.metrics = new Metrics(TEST_APDEX, TEST_MAPPER, TEST_NORMALIZER) + t.nr.metrics = new Metrics(TEST_APDEX, TEST_MAPPER, TEST_NORMALIZER) }) t.afterEach(afterEach) - t.test('should pass apdex through to ApdexStats', function (t) { - const { metrics } = t.context + await t.test('should pass apdex through to ApdexStats', function (t, end) { + const { metrics } = t.nr const apdex = metrics.getOrCreateApdexMetric('Test/RenameMe333') - t.equal(apdex.apdexT, TEST_APDEX) - t.end() + assert.equal(apdex.apdexT, TEST_APDEX) + end() }) - t.test('should pass metric mappings through for serialization', function (t) { - const { metrics } = t.context + await t.test('should pass metric mappings through for serialization', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('Test/RenameMe333', null, 400, 300) const summary = JSON.stringify(metrics.toJSON()) - t.equal(summary, '[[1337,[1,0.4,0.3,0.4,0.4,0.16000000000000003]]]') - t.end() + assert.equal(summary, '[[1337,[1,0.4,0.3,0.4,0.4,0.16000000000000003]]]') + end() }) }) - t.test('with ordinary statistics', function (t) { - t.autoend() + await t.test('with ordinary statistics', async function (t) { const NAME = 'Agent/Test384' t.beforeEach(function (t) { beforeEach(t) - const metric = t.context.metrics.getOrCreateMetric(NAME) + const metric = t.nr.metrics.getOrCreateMetric(NAME) const mapper = new MetricMapper([[{ name: NAME }, 1234]]) - t.context.metric = metric - t.context.mapper = mapper + t.nr.metric = metric + t.nr.mapper = mapper }) t.afterEach(afterEach) - t.test('should get the bare stats right', function (t) { - const { metrics } = t.context + await t.test('should get the bare stats right', function (t, end) { + const { metrics } = t.nr const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[{"name":"Agent/Test384"},[0,0,0,0,0,0]]') - t.end() + assert.equal(summary, '[{"name":"Agent/Test384"},[0,0,0,0,0,0]]') + end() }) - t.test('should correctly map metrics to IDs given a mapping', function (t) { - const { metrics, mapper } = t.context + await t.test('should correctly map metrics to IDs given a mapping', function (t, end) { + const { metrics, mapper } = t.nr metrics.mapper = mapper const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[1234,[0,0,0,0,0,0]]') - t.end() + assert.equal(summary, '[1234,[0,0,0,0,0,0]]') + end() }) - t.test('should correctly serialize statistics', function (t) { - const { metrics, metric } = t.context + await t.test('should correctly serialize statistics', function (t, end) { + const { metrics, metric } = t.nr metric.recordValue(0.3, 0.1) const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[{"name":"Agent/Test384"},[1,0.3,0.1,0.3,0.3,0.09]]') - t.end() + assert.equal(summary, '[{"name":"Agent/Test384"},[1,0.3,0.1,0.3,0.3,0.09]]') + end() }) }) - t.test('with apdex statistics', function (t) { - t.autoend() + await t.test('with apdex statistics', async function (t) { const NAME = 'Agent/Test385' t.beforeEach(function (t) { beforeEach(t) - const { agent } = t.context + const { agent } = t.nr const metrics = new Metrics(0.8, new MetricMapper(), agent.metricNameNormalizer) - t.context.metric = metrics.getOrCreateApdexMetric(NAME) - t.context.mapper = new MetricMapper([[{ name: NAME }, 1234]]) - t.context.metrics = metrics + t.nr.metric = metrics.getOrCreateApdexMetric(NAME) + t.nr.mapper = new MetricMapper([[{ name: NAME }, 1234]]) + t.nr.metrics = metrics }) t.afterEach(afterEach) - t.test('should get the bare stats right', function (t) { - const { metrics } = t.context + await t.test('should get the bare stats right', function (t, end) { + const { metrics } = t.nr const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[{"name":"Agent/Test385"},[0,0,0,0.8,0.8,0]]') - t.end() + assert.equal(summary, '[{"name":"Agent/Test385"},[0,0,0,0.8,0.8,0]]') + end() }) - t.test('should correctly map metrics to IDs given a mapping', function (t) { - const { metrics, mapper } = t.context + await t.test('should correctly map metrics to IDs given a mapping', function (t, end) { + const { metrics, mapper } = t.nr metrics.mapper = mapper const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[1234,[0,0,0,0.8,0.8,0]]') - t.end() + assert.equal(summary, '[1234,[0,0,0,0.8,0.8,0]]') + end() }) - t.test('should correctly serialize statistics', function (t) { - const { metric, metrics } = t.context + await t.test('should correctly serialize statistics', function (t, end) { + const { metric, metrics } = t.nr metric.recordValueInMillis(3220) const summary = JSON.stringify(metrics._getUnscopedData(NAME)) - t.equal(summary, '[{"name":"Agent/Test385"},[0,0,1,0.8,0.8,0]]') - t.end() + assert.equal(summary, '[{"name":"Agent/Test385"},[0,0,1,0.8,0.8,0]]') + end() }) }) - t.test('scoped metrics', function (t) { - t.autoend() + await t.test('scoped metrics', async function (t) { t.beforeEach(beforeEach) t.afterEach(afterEach) - t.test('when serializing unscoped metrics should get the basics right', function (t) { - const { metrics } = t.context - metrics.measureMilliseconds('Test/Metric', null, 400, 200) - metrics.measureMilliseconds('RenameMe333', null, 400, 300) - metrics.measureMilliseconds('Test/ScopedMetric', 'TEST', 400, 200) - - t.equal( - JSON.stringify(metrics._toUnscopedData()), - '[[{"name":"Test/Metric"},[1,0.4,0.2,0.4,0.4,0.16000000000000003]],' + - '[{"name":"RenameMe333"},[1,0.4,0.3,0.4,0.4,0.16000000000000003]]]' - ) - t.end() - }) - - t.test('should get the basics right', function (t) { - const { metrics } = t.context + await t.test( + 'when serializing unscoped metrics should get the basics right', + function (t, end) { + const { metrics } = t.nr + metrics.measureMilliseconds('Test/Metric', null, 400, 200) + metrics.measureMilliseconds('RenameMe333', null, 400, 300) + metrics.measureMilliseconds('Test/ScopedMetric', 'TEST', 400, 200) + + assert.equal( + JSON.stringify(metrics._toUnscopedData()), + '[[{"name":"Test/Metric"},[1,0.4,0.2,0.4,0.4,0.16000000000000003]],' + + '[{"name":"RenameMe333"},[1,0.4,0.3,0.4,0.4,0.16000000000000003]]]' + ) + end() + } + ) + + await t.test('should get the basics right', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('Test/UnscopedMetric', null, 400, 200) metrics.measureMilliseconds('Test/RenameMe333', 'TEST', 400, 300) metrics.measureMilliseconds('Test/ScopedMetric', 'ANOTHER', 400, 200) - t.equal( + assert.equal( JSON.stringify(metrics._toScopedData()), '[[{"name":"Test/RenameMe333","scope":"TEST"},' + '[1,0.4,0.3,0.4,0.4,0.16000000000000003]],' + '[{"name":"Test/ScopedMetric","scope":"ANOTHER"},' + '[1,0.4,0.2,0.4,0.4,0.16000000000000003]]]' ) - t.end() + end() }) - t.test('should serialize correctly', function (t) { - const { metrics } = t.context + await t.test('should serialize correctly', function (t, end) { + const { metrics } = t.nr metrics.measureMilliseconds('Test/UnscopedMetric', null, 400, 200) metrics.measureMilliseconds('Test/RenameMe333', null, 400, 300) metrics.measureMilliseconds('Test/ScopedMetric', 'TEST', 400, 200) - t.equal( + assert.equal( JSON.stringify(metrics.toJSON()), '[[{"name":"Test/UnscopedMetric"},' + '[1,0.4,0.2,0.4,0.4,0.16000000000000003]],' + @@ -358,15 +371,14 @@ tap.test('Metrics', function (t) { '[{"name":"Test/ScopedMetric","scope":"TEST"},' + '[1,0.4,0.2,0.4,0.4,0.16000000000000003]]]' ) - t.end() + end() }) }) - t.test('when merging two metrics collections', function (t) { - t.autoend() + await t.test('when merging two metrics collections', async function (t) { t.beforeEach(function (t) { beforeEach(t) - const { metrics, agent } = t.context + const { metrics, agent } = t.nr metrics.started = 31337 metrics.measureMilliseconds('Test/Metrics/Unscoped', null, 400) metrics.measureMilliseconds('Test/Unscoped', null, 300) @@ -381,40 +393,40 @@ tap.test('Metrics', function (t) { other.measureMilliseconds('Test/Scoped', 'MERGE', 500) metrics.merge(other) - t.context.other = other + t.nr.other = other }) t.afterEach(afterEach) - t.test('has all the metrics that were only in one', function (t) { - const { metrics } = t.context - t.equal(metrics.getMetric('Test/Metrics/Unscoped').callCount, 1) - t.equal(metrics.getMetric('Test/Other/Unscoped').callCount, 1) - t.equal(metrics.getMetric('Test/Scoped', 'METRICS').callCount, 1) - t.equal(metrics.getMetric('Test/Scoped', 'OTHER').callCount, 1) - t.end() + await t.test('has all the metrics that were only in one', function (t, end) { + const { metrics } = t.nr + assert.equal(metrics.getMetric('Test/Metrics/Unscoped').callCount, 1) + assert.equal(metrics.getMetric('Test/Other/Unscoped').callCount, 1) + assert.equal(metrics.getMetric('Test/Scoped', 'METRICS').callCount, 1) + assert.equal(metrics.getMetric('Test/Scoped', 'OTHER').callCount, 1) + end() }) - t.test('merged metrics that were in both', function (t) { - const { metrics } = t.context - t.equal(metrics.getMetric('Test/Unscoped').callCount, 2) - t.equal(metrics.getMetric('Test/Scoped', 'MERGE').callCount, 2) - t.end() + await t.test('merged metrics that were in both', function (t, end) { + const { metrics } = t.nr + assert.equal(metrics.getMetric('Test/Unscoped').callCount, 2) + assert.equal(metrics.getMetric('Test/Scoped', 'MERGE').callCount, 2) + end() }) - t.test('does not keep the earliest creation time', function (t) { - const { metrics } = t.context - t.equal(metrics.started, 31337) - t.end() + await t.test('does not keep the earliest creation time', function (t, end) { + const { metrics } = t.nr + assert.equal(metrics.started, 31337) + end() }) - t.test('does keep the earliest creation time if told to', function (t) { - const { metrics, other } = t.context + await t.test('does keep the earliest creation time if told to', function (t, end) { + const { metrics, other } = t.nr metrics.merge(other, true) - t.equal(metrics.started, 1337) - t.end() + assert.equal(metrics.started, 1337) + end() }) }) - t.test('should not let exclusive duration exceed total duration', { todo: true }) + await t.test('should not let exclusive duration exceed total duration', { todo: true }) }) diff --git a/test/unit/metric/normalizer-rule.test.js b/test/unit/metric/normalizer-rule.test.js index 025c9f7b88..ad151114a7 100644 --- a/test/unit/metric/normalizer-rule.test.js +++ b/test/unit/metric/normalizer-rule.test.js @@ -4,14 +4,14 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const Rule = require('../../../lib/metrics/normalizer/rule') -tap.test('NormalizerRule', function (t) { - t.autoend() - t.test('with a very simple specification', function (t) { - t.autoend() - t.beforeEach(function (t) { +test('NormalizerRule', async function (t) { + await t.test('with a very simple specification', async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} // sample rule sent by staging collector 1 on 2012-08-29 const sample = { each_segment: false, @@ -23,97 +23,88 @@ tap.test('NormalizerRule', function (t) { replacement: '\\1' } - t.context.rule = new Rule(sample) + ctx.nr.rule = new Rule(sample) }) - t.test('should know whether the rule terminates normalization', function (t) { - const { rule } = t.context - t.equal(rule.isTerminal, true) - t.end() + await t.test('should know whether the rule terminates normalization', function (t) { + const { rule } = t.nr + assert.equal(rule.isTerminal, true) }) - t.test('should know its own precedence', function (t) { - const { rule } = t.context - t.equal(rule.precedence, 0) - t.end() + await t.test('should know its own precedence', function (t) { + const { rule } = t.nr + assert.equal(rule.precedence, 0) }) - t.test('should correctly compile the included regexp', function (t) { - const { rule } = t.context - t.equal(rule.matches('test_match_nothing'), true) - t.equal(rule.matches('a test_match_nothing'), false) - t.equal(rule.matches("test_match_nothin'"), false) - t.end() + await t.test('should correctly compile the included regexp', function (t) { + const { rule } = t.nr + assert.equal(rule.matches('test_match_nothing'), true) + assert.equal(rule.matches('a test_match_nothing'), false) + assert.equal(rule.matches("test_match_nothin'"), false) }) - t.test("shouldn't throw if the regexp doesn't compile", function (t) { + await t.test("shouldn't throw if the regexp doesn't compile", function () { const whoops = { match_expression: '$[ad^' } let bad - t.doesNotThrow(function () { + assert.doesNotThrow(function () { bad = new Rule(whoops) }) - t.equal(bad.matches(''), true) - t.end() + assert.equal(bad.matches(''), true) }) - t.test("should know if the regexp is applied to each 'segment' in the URL", function (t) { - const { rule } = t.context - t.equal(rule.eachSegment, false) - t.end() + await t.test("should know if the regexp is applied to each 'segment' in the URL", function (t) { + const { rule } = t.nr + assert.equal(rule.eachSegment, false) }) - t.test('should know if the regexp replaces all instances in the URL', function (t) { - const { rule } = t.context - t.equal(rule.replaceAll, false) - t.end() + await t.test('should know if the regexp replaces all instances in the URL', function (t) { + const { rule } = t.nr + assert.equal(rule.replaceAll, false) }) - t.test('should parse the replacement pattern', function (t) { - const { rule } = t.context - t.equal(rule.replacement, '$1') - t.end() + await t.test('should parse the replacement pattern', function (t) { + const { rule } = t.nr + assert.equal(rule.replacement, '$1') }) - t.test('should know whether to ignore the URL', function (t) { - const { rule } = t.context - t.equal(rule.ignore, false) - t.end() + await t.test('should know whether to ignore the URL', function (t) { + const { rule } = t.nr + assert.equal(rule.ignore, false) }) - t.test('should be able to take in a non-normalized URL and return it normalized', (t) => { - const { rule } = t.context - t.equal(rule.apply('test_match_nothing'), 'test_match_nothing') - t.end() + await t.test('should be able to take in a non-normalized URL and return it normalized', (t) => { + const { rule } = t.nr + assert.equal(rule.apply('test_match_nothing'), 'test_match_nothing') }) }) - t.test("with Saxon's patterns", function (t) { - t.autoend() - t.test("including '^(?!account|application).*'", function (t) { - t.autoend() - t.beforeEach(function (t) { - t.context.rule = new Rule({ + await t.test("with Saxon's patterns", async function (t) { + await t.test("including '^(?!account|application).*'", async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} + ctx.nr.rule = new Rule({ each_segment: true, match_expression: '^(?!account|application).*', replacement: '*' }) }) - t.test( + await t.test( "implies '/account/myacc/application/test' -> '/account/*/application/*'", function (t) { - const { rule } = t.context - t.equal(rule.apply('/account/myacc/application/test'), '/account/*/application/*') - t.end() + const { rule } = t.nr + assert.equal(rule.apply('/account/myacc/application/test'), '/account/*/application/*') } ) - t.test( + await t.test( "implies '/oh/dude/account/myacc/application' -> '/*/*/account/*/application'", function (t) { - const { rule } = t.context - t.equal(rule.apply('/oh/dude/account/myacc/application'), '/*/*/account/*/application') - t.end() + const { rule } = t.nr + assert.equal( + rule.apply('/oh/dude/account/myacc/application'), + '/*/*/account/*/application' + ) } ) }) @@ -121,27 +112,26 @@ tap.test('NormalizerRule', function (t) { const expression = '^(?!channel|download|popups|search|tap|user' + '|related|admin|api|genres|notification).*' - t.test(`including '${expression}'`, function (t) { - t.autoend() - t.beforeEach(function (t) { - t.context.rule = new Rule({ + await t.test(`including '${expression}'`, async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} + ctx.nr.rule = new Rule({ each_segment: true, match_expression: expression, replacement: '*' }) }) - t.test("implies '/tap/stuff/user/gfy77t/view' -> '/tap/*/user/*/*'", function (t) { - const { rule } = t.context - t.equal(rule.apply('/tap/stuff/user/gfy77t/view'), '/tap/*/user/*/*') - t.end() + await t.test("implies '/tap/stuff/user/gfy77t/view' -> '/tap/*/user/*/*'", function (t) { + const { rule } = t.nr + assert.equal(rule.apply('/tap/stuff/user/gfy77t/view'), '/tap/*/user/*/*') }) }) }) - t.test('with a more complex substitution rule', function (t) { - t.autoend() - t.beforeEach(function (t) { + await t.test('with a more complex substitution rule', async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} // sample rule sent by staging collector 1 on 2012-08-29 const sample = { each_segment: true, @@ -153,61 +143,53 @@ tap.test('NormalizerRule', function (t) { replacement: '*' } - t.context.rule = new Rule(sample) + ctx.nr.rule = new Rule(sample) }) - t.test('should know whether the rule terminates normalization', function (t) { - const { rule } = t.context - t.equal(rule.isTerminal, false) - t.end() + await t.test('should know whether the rule terminates normalization', function (t) { + const { rule } = t.nr + assert.equal(rule.isTerminal, false) }) - t.test('should know its own precedence', function (t) { - const { rule } = t.context - t.equal(rule.precedence, 1) - t.end() + await t.test('should know its own precedence', function (t) { + const { rule } = t.nr + assert.equal(rule.precedence, 1) }) - t.test('should correctly compile the included regexp', function (t) { - const { rule } = t.context - t.equal(rule.matches('/00dead_beef_00,b/hamburt'), true) - t.equal(rule.matches('a test_match_nothing'), false) - t.equal(rule.matches('/00 dead dad/nomatch'), false) - t.end() + await t.test('should correctly compile the included regexp', function (t) { + const { rule } = t.nr + assert.equal(rule.matches('/00dead_beef_00,b/hamburt'), true) + assert.equal(rule.matches('a test_match_nothing'), false) + assert.equal(rule.matches('/00 dead dad/nomatch'), false) }) - t.test("should know if the regexp is applied to each 'segment' in the URL", function (t) { - const { rule } = t.context - t.equal(rule.eachSegment, true) - t.end() + await t.test("should know if the regexp is applied to each 'segment' in the URL", function (t) { + const { rule } = t.nr + assert.equal(rule.eachSegment, true) }) - t.test('should know if the regexp replaces all instances in the URL', function (t) { - const { rule } = t.context - t.equal(rule.replaceAll, false) - t.end() + await t.test('should know if the regexp replaces all instances in the URL', function (t) { + const { rule } = t.nr + assert.equal(rule.replaceAll, false) }) - t.test('should parse the replacement pattern', function (t) { - const { rule } = t.context - t.equal(rule.replacement, '*') - t.end() + await t.test('should parse the replacement pattern', function (t) { + const { rule } = t.nr + assert.equal(rule.replacement, '*') }) - t.test('should know whether to ignore the URL', function (t) { - const { rule } = t.context - t.equal(rule.ignore, false) - t.end() + await t.test('should know whether to ignore the URL', function (t) { + const { rule } = t.nr + assert.equal(rule.ignore, false) }) - t.test('should be able to take in a non-normalized URL and return it normalized', (t) => { - const { rule } = t.context - t.equal(rule.apply('/00dead_beef_00,b/hamburt'), '/*/hamburt') - t.end() + await t.test('should be able to take in a non-normalized URL and return it normalized', (t) => { + const { rule } = t.nr + assert.equal(rule.apply('/00dead_beef_00,b/hamburt'), '/*/hamburt') }) }) - t.test('should replace all the instances of a pattern when so specified', function (t) { + await t.test('should replace all the instances of a pattern when so specified', function () { const sample = { each_segment: false, eval_order: 0, @@ -219,65 +201,53 @@ tap.test('NormalizerRule', function (t) { } const rule = new Rule(sample) - t.equal(rule.pattern.global, true) - t.equal(rule.apply('/test/xXxxXx0xXxzxxxxXx'), '/test/yy0yzyy') - t.end() + assert.equal(rule.pattern.global, true) + assert.equal(rule.apply('/test/xXxxXx0xXxzxxxxXx'), '/test/yy0yzyy') }) - t.test('when given an incomplete specification', function (t) { - t.autoend() - t.test("shouldn't throw (but it can log!)", function (t) { - t.doesNotThrow(function () { + await t.test('when given an incomplete specification', async function (t) { + await t.test("shouldn't throw (but it can log!)", function () { + assert.doesNotThrow(function () { // eslint-disable-next-line no-new new Rule() }) - t.end() }) - t.test('should default to not applying the rule to each segment', function (t) { - t.equal(new Rule().eachSegment, false) - t.end() + await t.test('should default to not applying the rule to each segment', function () { + assert.equal(new Rule().eachSegment, false) }) - t.test("should default the rule's precedence to 0", function (t) { - t.equal(new Rule().precedence, 0) - t.end() + await t.test("should default the rule's precedence to 0", function () { + assert.equal(new Rule().precedence, 0) }) - t.test('should default to not terminating rule evaluation', function (t) { - t.equal(new Rule().isTerminal, false) - t.end() + await t.test('should default to not terminating rule evaluation', function () { + assert.equal(new Rule().isTerminal, false) }) - t.test('should have a regexp that matches the empty string', function (t) { - t.same(new Rule().pattern, /^$/i) - t.end() + await t.test('should have a regexp that matches the empty string', function () { + assert.deepEqual(new Rule().pattern, /^$/i) }) - t.test('should use the entire match as the replacement value', function (t) { - t.equal(new Rule().replacement, '$0') - t.end() + await t.test('should use the entire match as the replacement value', function () { + assert.equal(new Rule().replacement, '$0') }) - t.test('should default to not replacing all instances', function (t) { - t.equal(new Rule().replaceAll, false) - t.end() + await t.test('should default to not replacing all instances', function () { + assert.equal(new Rule().replaceAll, false) }) - t.test('should default to not ignoring matching URLs', function (t) { - t.equal(new Rule().ignore, false) - t.end() + await t.test('should default to not ignoring matching URLs', function () { + assert.equal(new Rule().ignore, false) }) - t.test('should silently pass through the input if applied', function (t) { - t.equal(new Rule().apply('sample/input'), 'sample/input') - t.end() + await t.test('should silently pass through the input if applied', function () { + assert.equal(new Rule().apply('sample/input'), 'sample/input') }) }) - t.test('when given a RegExp', function (t) { - t.autoend() - t.test('should merge flags', function (t) { + await t.test('when given a RegExp', async function (t) { + await t.test('should merge flags', function () { const r = new Rule({ each_segment: false, eval_order: 0, @@ -289,15 +259,14 @@ tap.test('NormalizerRule', function (t) { }) const re = r.pattern - t.equal(re.ignoreCase, true) - t.equal(re.multiline, true) - t.equal(re.global, true) - t.end() + assert.equal(re.ignoreCase, true) + assert.equal(re.multiline, true) + assert.equal(re.global, true) }) - t.test('should not die on duplicated flags', function (t) { + await t.test('should not die on duplicated flags', function () { let r = null - t.doesNotThrow(function () { + assert.doesNotThrow(function () { r = new Rule({ each_segment: false, eval_order: 0, @@ -310,10 +279,9 @@ tap.test('NormalizerRule', function (t) { }) const re = r.pattern - t.equal(re.ignoreCase, true) - t.equal(re.multiline, false) - t.equal(re.global, true) - t.end() + assert.equal(re.ignoreCase, true) + assert.equal(re.multiline, false) + assert.equal(re.global, true) }) }) }) diff --git a/test/unit/metric/normalizer-tx-segment.test.js b/test/unit/metric/normalizer-tx-segment.test.js index a4af3c8990..f5ecb65067 100644 --- a/test/unit/metric/normalizer-tx-segment.test.js +++ b/test/unit/metric/normalizer-tx-segment.test.js @@ -5,28 +5,27 @@ 'use strict' -const tap = require('tap') - +const test = require('node:test') +const assert = require('node:assert') const TxSegmentNormalizer = require('../../../lib/metrics/normalizer/tx_segment') const txTestData = require('../../lib/cross_agent_tests/transaction_segment_terms') -tap.test('The TxSegmentNormalizer', (t) => { +test('The TxSegmentNormalizer', async (t) => { // iterate over the cross_agent_tests - txTestData.forEach((test) => { + for (const test of txTestData) { // create the test and bind the test data to it. - t.test(`should be ${test.testname}`, (t) => { - runTest(t, test) + await t.test(`should be ${test.testname}`, () => { + runTest(test) }) - }) + } - t.test('should reject non array to load', (t) => { + await t.test('should reject non array to load', () => { const normalizer = new TxSegmentNormalizer() normalizer.load(1) - t.ok(Array.isArray(normalizer.terms)) - t.end() + assert.ok(Array.isArray(normalizer.terms)) }) - t.test('should accept arrays to load', (t) => { + await t.test('should accept arrays to load', () => { const input = [ { prefix: 'WebTrans/foo', @@ -35,20 +34,15 @@ tap.test('The TxSegmentNormalizer', (t) => { ] const normalizer = new TxSegmentNormalizer() normalizer.load(input) - t.same(normalizer.terms, input) - t.end() + assert.deepEqual(normalizer.terms, input) }) - - t.end() }) -function runTest(t, data) { +function runTest(data) { const normalizer = new TxSegmentNormalizer() normalizer.load(data.transaction_segment_terms) - data.tests.forEach((test) => { - t.hasStrict(normalizer.normalize(test.input), { value: test.expected }) - }) - - t.end() + for (const test of data.tests) { + assert.deepEqual(normalizer.normalize(test.input).value, test.expected) + } } diff --git a/test/unit/metric/normalizer.test.js b/test/unit/metric/normalizer.test.js index 8ac10fd010..70b0134207 100644 --- a/test/unit/metric/normalizer.test.js +++ b/test/unit/metric/normalizer.test.js @@ -4,54 +4,50 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const Config = require('../../../lib/config') const Normalizer = require('../../../lib/metrics/normalizer') const stagingRules = require('./staging-rules') -function beforeEach(t) { +function beforeEach(ctx) { + ctx.nr = {} const config = { enforce_backstop: true } - t.context.normalizer = new Normalizer(config, 'URL') + ctx.nr.normalizer = new Normalizer(config, 'URL') } -tap.test('MetricNormalizer', function (t) { - t.autoend() - t.test('normalize', (t) => { - t.autoend() +test('MetricNormalizer', async function (t) { + await t.test('normalize', async (t) => { t.beforeEach(beforeEach) - t.test('should throw when instantiated without config', function (t) { - t.throws(function () { + await t.test('should throw when instantiated without config', function () { + assert.throws(function () { // eslint-disable-next-line no-new new Normalizer() }) - t.end() }) - t.test('should throw when instantiated without type', function (t) { + await t.test('should throw when instantiated without type', function () { const config = { enforce_backstop: true } - t.throws(function () { + assert.throws(function () { // eslint-disable-next-line no-new new Normalizer(config) }) - t.end() }) - t.test('should normalize even without any rules set', function (t) { - const { normalizer } = t.context - t.equal(normalizer.normalize('/sample').value, 'NormalizedUri/*') - t.end() + await t.test('should normalize even without any rules set', function (t) { + const { normalizer } = t.nr + assert.equal(normalizer.normalize('/sample').value, 'NormalizedUri/*') }) - t.test('should normalize with an empty rule set', function (t) { - const { normalizer } = t.context + await t.test('should normalize with an empty rule set', function (t) { + const { normalizer } = t.nr normalizer.load([]) - t.equal(normalizer.normalize('/sample').value, 'NormalizedUri/*') - t.end() + assert.equal(normalizer.normalize('/sample').value, 'NormalizedUri/*') }) - t.test('should ignore a matching name', function (t) { - const { normalizer } = t.context + await t.test('should ignore a matching name', function (t) { + const { normalizer } = t.nr normalizer.load([ { each_segment: false, @@ -64,12 +60,11 @@ tap.test('MetricNormalizer', function (t) { } ]) - t.equal(normalizer.normalize('/long_polling').ignore, true) - t.end() + assert.equal(normalizer.normalize('/long_polling').ignore, true) }) - t.test('should apply rules by precedence', function (t) { - const { normalizer } = t.context + await t.test('should apply rules by precedence', function (t) { + const { normalizer } = t.nr normalizer.load([ { each_segment: true, @@ -91,12 +86,14 @@ tap.test('MetricNormalizer', function (t) { } ]) - t.equal(normalizer.normalize('/rice/is/not/rice').value, 'NormalizedUri/rice/is/not/millet') - t.end() + assert.equal( + normalizer.normalize('/rice/is/not/rice').value, + 'NormalizedUri/rice/is/not/millet' + ) }) - t.test('should terminate when indicated by rule', function (t) { - const { normalizer } = t.context + await t.test('should terminate when indicated by rule', function (t) { + const { normalizer } = t.nr normalizer.load([ { each_segment: true, @@ -118,21 +115,22 @@ tap.test('MetricNormalizer', function (t) { } ]) - t.equal(normalizer.normalize('/rice/is/not/rice').value, 'NormalizedUri/rice/is/not/mochi') - t.end() + assert.equal( + normalizer.normalize('/rice/is/not/rice').value, + 'NormalizedUri/rice/is/not/mochi' + ) }) }) - t.test('with rules captured from the staging collector on 2012-08-29', function (t) { - t.autoend() - t.beforeEach(function (t) { - beforeEach(t) - const { normalizer } = t.context + await t.test('with rules captured from the staging collector on 2012-08-29', async function (t) { + t.beforeEach(function (ctx) { + beforeEach(ctx) + const { normalizer } = ctx.nr normalizer.load(stagingRules) }) - t.test('should eliminate duplicate rules as part of loading them', function (t) { - const { normalizer } = t.context + await t.test('should eliminate duplicate rules as part of loading them', function (t) { + const { normalizer } = t.nr const patternWithSlash = '^(.*)\\/[0-9][0-9a-f_,-]*\\.([0-9a-z][0-9a-z]*)$' const reduced = [ { @@ -173,35 +171,31 @@ tap.test('MetricNormalizer', function (t) { } ] - t.same( + assert.deepEqual( normalizer.rules.map((r) => { return r.toJSON() }), reduced ) - t.end() }) - t.test('should normalize a JPEGgy URL', function (t) { - const { normalizer } = t.context - t.equal(normalizer.normalize('/excessivity.jpeg').value, 'NormalizedUri/*.jpeg') - t.end() + await t.test('should normalize a JPEGgy URL', function (t) { + const { normalizer } = t.nr + assert.equal(normalizer.normalize('/excessivity.jpeg').value, 'NormalizedUri/*.jpeg') }) - t.test('should normalize a JPGgy URL', function (t) { - const { normalizer } = t.context - t.equal(normalizer.normalize('/excessivity.jpg').value, 'NormalizedUri/*.jpg') - t.end() + await t.test('should normalize a JPGgy URL', function (t) { + const { normalizer } = t.nr + assert.equal(normalizer.normalize('/excessivity.jpg').value, 'NormalizedUri/*.jpg') }) - t.test('should normalize a CSS URL', function (t) { - const { normalizer } = t.context - t.equal(normalizer.normalize('/style.css').value, 'NormalizedUri/*.css') - t.end() + await t.test('should normalize a CSS URL', function (t) { + const { normalizer } = t.nr + assert.equal(normalizer.normalize('/style.css').value, 'NormalizedUri/*.css') }) - t.test('should drop old rules when reloading', function (t) { - const { normalizer } = t.context + await t.test('should drop old rules when reloading', function (t) { + const { normalizer } = t.nr const newRule = { each_segment: false, eval_order: 0, @@ -222,54 +216,48 @@ tap.test('MetricNormalizer', function (t) { ignore: false, replacement: '$1' } - t.same( + assert.deepEqual( normalizer.rules.map((r) => { return r.toJSON() }), [expected] ) - t.end() }) }) - t.test('when calling addSimple', function (t) { - t.autoend() + await t.test('when calling addSimple', async function (t) { t.beforeEach(beforeEach) - t.test("won't crash with no parameters", function (t) { - const { normalizer } = t.context - t.doesNotThrow(function () { + await t.test("won't crash with no parameters", function (t) { + const { normalizer } = t.nr + assert.doesNotThrow(function () { normalizer.addSimple() }) - t.end() }) - t.test("won't crash when name isn't passed", function (t) { - const { normalizer } = t.context - t.doesNotThrow(function () { + await t.test("won't crash when name isn't passed", function (t) { + const { normalizer } = t.nr + assert.doesNotThrow(function () { normalizer.addSimple('^t') }) - t.end() }) - t.test("will ignore matches when name isn't passed", function (t) { - const { normalizer } = t.context + await t.test("will ignore matches when name isn't passed", function (t) { + const { normalizer } = t.nr normalizer.addSimple('^t') - t.equal(normalizer.rules[0].ignore, true) - t.end() + assert.equal(normalizer.rules[0].ignore, true) }) - t.test('will create rename rules that work properly', function (t) { - const { normalizer } = t.context + await t.test('will create rename rules that work properly', function (t) { + const { normalizer } = t.nr normalizer.addSimple('^/t(.*)$', '/w$1') - t.equal(normalizer.normalize('/test').value, 'NormalizedUri/west') - t.end() + assert.equal(normalizer.normalize('/test').value, 'NormalizedUri/west') }) }) - t.test('when loading from config', function (t) { - t.autoend() - t.beforeEach(function (t) { - t.context.config = new Config({ + await t.test('when loading from config', async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} + ctx.nr.config = new Config({ rules: { name: [ { pattern: '^first$', name: 'first', precedence: 500 }, @@ -280,33 +268,31 @@ tap.test('MetricNormalizer', function (t) { } }) - t.context.normalizer = new Normalizer(t.context.config, 'URL') + ctx.nr.normalizer = new Normalizer(ctx.nr.config, 'URL') }) - t.afterEach(function (t) { - t.context.config = null - t.context.normalizer = null + t.afterEach(function (ctx) { + ctx.nr.config = null + ctx.nr.normalizer = null }) - t.test('with feature flag reverse_naming_rules set to true', function (t) { - const { config, normalizer } = t.context + await t.test('with feature flag reverse_naming_rules set to true', function (t) { + const { config, normalizer } = t.nr config.feature_flag = { reverse_naming_rules: true } normalizer.loadFromConfig() - t.equal(normalizer.rules[1].replacement, 'third') - t.equal(normalizer.rules[2].replacement, 'fourth') - t.equal(normalizer.rules[3].replacement, 'second') - t.equal(normalizer.rules[4].replacement, 'first') - t.end() + assert.equal(normalizer.rules[1].replacement, 'third') + assert.equal(normalizer.rules[2].replacement, 'fourth') + assert.equal(normalizer.rules[3].replacement, 'second') + assert.equal(normalizer.rules[4].replacement, 'first') }) - t.test('with feature flag reverse_naming_rules set to false (default)', function (t) { - const { normalizer } = t.context + await t.test('with feature flag reverse_naming_rules set to false (default)', function (t) { + const { normalizer } = t.nr normalizer.loadFromConfig() - t.equal(normalizer.rules[1].replacement, 'third') - t.equal(normalizer.rules[2].replacement, 'first') - t.equal(normalizer.rules[3].replacement, 'second') - t.equal(normalizer.rules[4].replacement, 'fourth') - t.end() + assert.equal(normalizer.rules[1].replacement, 'third') + assert.equal(normalizer.rules[2].replacement, 'first') + assert.equal(normalizer.rules[3].replacement, 'second') + assert.equal(normalizer.rules[4].replacement, 'fourth') }) }) }) diff --git a/test/unit/metrics-recorder/distributed-trace.test.js b/test/unit/metrics-recorder/distributed-trace.test.js index 0e326c372d..f41d95991a 100644 --- a/test/unit/metrics-recorder/distributed-trace.test.js +++ b/test/unit/metrics-recorder/distributed-trace.test.js @@ -5,9 +5,9 @@ 'use strict' -const tap = require('tap') +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') +const { assertMetrics } = require('../../lib/custom-assertions') const recordDistributedTrace = require('../../../lib/metrics/recorders/distributed-trace') const Transaction = require('../../../lib/transaction') @@ -29,7 +29,8 @@ const record = (opts) => { recordDistributedTrace(tx, opts.type, duration, exclusive) } -function beforeEach(t) { +function beforeEach(ctx) { + ctx.nr = {} const agent = helper.loadMockedAgent({ distributed_tracing: { enabled: true @@ -41,22 +42,20 @@ function beforeEach(t) { ;(agent.config.account_id = '1234'), (agent.config.primary_application_id = '5678'), (agent.config.trusted_account_key = '1234') - t.context.tx = new Transaction(agent) - t.context.agent = agent + ctx.nr.tx = new Transaction(agent) + ctx.nr.agent = agent } -function afterEach(t) { - helper.unloadAgent(t.context.agent) +function afterEach(ctx) { + helper.unloadAgent(ctx.nr.agent) } -tap.test('recordDistributedTrace', (t) => { - t.autoend() - t.test('when a trace payload was received', (t) => { - t.autoend() +test('recordDistributedTrace', async (t) => { + await t.test('when a trace payload was received', async (t) => { t.beforeEach(beforeEach) t.afterEach(afterEach) - t.test('records metrics with payload information', (t) => { - const { tx } = t.context + await t.test('records metrics with payload information', (t) => { + const { tx } = t.nr const payload = tx._createDistributedTracePayload().text() tx.isDistributedTrace = null tx._acceptDistributedTracePayload(payload, 'HTTP') @@ -87,12 +86,11 @@ tap.test('recordDistributedTrace', (t) => { ] ] - t.assertMetrics(tx.metrics, result, true, true) - t.end() + assertMetrics(tx.metrics, result, true, true) }) - t.test('and transaction errors exist includes error-related metrics', (t) => { - const { tx } = t.context + await t.test('and transaction errors exist includes error-related metrics', (t) => { + const { tx } = t.nr const payload = tx._createDistributedTracePayload().text() tx.isDistributedTrace = null tx._acceptDistributedTracePayload(payload, 'HTTP') @@ -133,17 +131,15 @@ tap.test('recordDistributedTrace', (t) => { ] ] - t.assertMetrics(tx.metrics, result, true, true) - t.end() + assertMetrics(tx.metrics, result, true, true) }) }) - t.test('when no trace payload was received', (t) => { - t.autoend() + await t.test('when no trace payload was received', async (t) => { t.beforeEach(beforeEach) t.afterEach(afterEach) - t.test('records metrics with Unknown payload information', (t) => { - const { tx } = t.context + await t.test('records metrics with Unknown payload information', (t) => { + const { tx } = t.nr record({ tx, duration: 55, @@ -162,8 +158,7 @@ tap.test('recordDistributedTrace', (t) => { ] ] - t.assertMetrics(tx.metrics, result, true, true) - t.end() + assertMetrics(tx.metrics, result, true, true) }) }) }) diff --git a/test/unit/metrics-recorder/generic.test.js b/test/unit/metrics-recorder/generic.test.js index d863f3fdcd..35d9e5d687 100644 --- a/test/unit/metrics-recorder/generic.test.js +++ b/test/unit/metrics-recorder/generic.test.js @@ -4,7 +4,8 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') const recordGeneric = require('../../../lib/metrics/recorders/generic') const Transaction = require('../../../lib/transaction') @@ -29,33 +30,32 @@ function record(options) { recordGeneric(segment, options.transaction.name) } -tap.test('recordGeneric', function (t) { - t.autoend() - t.beforeEach((t) => { +test('recordGeneric', async function (t) { + t.beforeEach((ctx) => { + ctx.nr = {} const agent = helper.loadMockedAgent() - t.context.trans = new Transaction(agent) - t.context.agent = agent + ctx.nr.trans = new Transaction(agent) + ctx.nr.agent = agent }) - t.afterEach((t) => { - helper.unloadAgent(t.context.agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - t.test("when scoped is undefined it shouldn't crash on recording", function (t) { - const { trans } = t.context + await t.test("when scoped is undefined it shouldn't crash on recording", function (t) { + const { trans } = t.nr const segment = makeSegment({ transaction: trans, duration: 0, exclusive: 0 }) - t.doesNotThrow(function () { + assert.doesNotThrow(function () { recordGeneric(segment, undefined) }) - t.end() }) - t.test('when scoped is undefined it should record no scoped metrics', function (t) { - const { trans } = t.context + await t.test('when scoped is undefined it should record no scoped metrics', function (t) { + const { trans } = t.nr const segment = makeSegment({ transaction: trans, duration: 5, @@ -65,12 +65,11 @@ tap.test('recordGeneric', function (t) { const result = [[{ name: 'placeholder' }, [1, 0.005, 0.005, 0.005, 0.005, 0.000025]]] - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) - t.test('with scope should record scoped metrics', function (t) { - const { trans } = t.context + await t.test('with scope should record scoped metrics', function (t) { + const { trans } = t.nr record({ transaction: trans, url: '/test', @@ -88,12 +87,11 @@ tap.test('recordGeneric', function (t) { ] ] - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) - t.test('should report exclusive time correctly', function (t) { - const { trans } = t.context + await t.test('should report exclusive time correctly', function (t) { + const { trans } = t.nr const root = trans.trace.root const parent = root.add('Test/Parent', recordGeneric) const child1 = parent.add('Test/Child/1', recordGeneric) @@ -111,7 +109,6 @@ tap.test('recordGeneric', function (t) { ] trans.end() - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) }) diff --git a/test/unit/metrics-recorder/http-external.test.js b/test/unit/metrics-recorder/http-external.test.js index dc099a5cfc..8ccdcc52ee 100644 --- a/test/unit/metrics-recorder/http-external.test.js +++ b/test/unit/metrics-recorder/http-external.test.js @@ -4,7 +4,8 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') const generateRecorder = require('../../../lib/metrics/recorders/http_external') const Transaction = require('../../../lib/transaction') @@ -33,35 +34,34 @@ function record(options) { recordExternal(segment, options.transaction.name) } -tap.test('recordExternal', function (t) { - t.autoend() - t.beforeEach(function (t) { +test('recordExternal', async function (t) { + t.beforeEach(function (ctx) { + ctx.nr = {} const agent = helper.loadMockedAgent() const trans = new Transaction(agent) trans.type = Transaction.TYPES.BG - t.context.agent = agent - t.context.trans = trans + ctx.nr.agent = agent + ctx.nr.trans = trans }) - t.afterEach(function (t) { - helper.unloadAgent(t.context.agent) + t.afterEach(function (ctx) { + helper.unloadAgent(ctx.nr.agent) }) - t.test("when scoped is undefined it shouldn't crash on recording", function (t) { - const { trans } = t.context + await t.test("when scoped is undefined it shouldn't crash on recording", function (t) { + const { trans } = t.nr const segment = makeSegment({ transaction: trans, duration: 0, exclusive: 0 }) - t.doesNotThrow(function () { + assert.doesNotThrow(function () { recordExternal(segment, undefined) }) - t.end() }) - t.test('when scoped is undefined it should record no scoped metrics', function (t) { - const { trans } = t.context + await t.test('when scoped is undefined it should record no scoped metrics', function (t) { + const { trans } = t.nr const segment = makeSegment({ transaction: trans, duration: 0, @@ -76,12 +76,11 @@ tap.test('recordExternal', function (t) { [{ name: 'External/all' }, [1, 0, 0, 0, 0, 0]] ] - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) - t.test('with scope should record scoped metrics', function (t) { - const { trans } = t.context + await t.test('with scope should record scoped metrics', function (t) { + const { trans } = t.nr trans.type = Transaction.TYPES.WEB record({ transaction: trans, @@ -103,12 +102,11 @@ tap.test('recordExternal', function (t) { ] ] - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) - t.test('should report exclusive time correctly', function (t) { - const { trans } = t.context + await t.test('should report exclusive time correctly', function (t) { + const { trans } = t.nr const root = trans.trace.root const parent = root.add('/parent', recordExternal) const child1 = parent.add('/child1', generateRecorder('api.twitter.com', 'https')) @@ -131,7 +129,6 @@ tap.test('recordExternal', function (t) { ] trans.end() - t.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) - t.end() + assert.equal(JSON.stringify(trans.metrics), JSON.stringify(result)) }) }) diff --git a/test/unit/metrics-recorder/http.test.js b/test/unit/metrics-recorder/http.test.js index 4a2f8da734..afacf786ed 100644 --- a/test/unit/metrics-recorder/http.test.js +++ b/test/unit/metrics-recorder/http.test.js @@ -4,9 +4,10 @@ */ 'use strict' -const tap = require('tap') +const test = require('node:test') +const assert = require('node:assert') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') +const { assertMetrics } = require('../../lib/custom-assertions') const recordWeb = require('../../../lib/metrics/recorders/http') const Transaction = require('../../../lib/transaction') @@ -31,270 +32,297 @@ function record(options) { recordWeb(segment, options.transaction.name) } -function beforeEach(t) { - t.context.agent = helper.instrumentMockedAgent() - t.context.trans = new Transaction(t.context.agent) +function beforeEach(ctx) { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() + ctx.nr.trans = new Transaction(ctx.nr.agent) } -function afterEach(t) { - helper.unloadAgent(t.context.agent) +function afterEach(ctx) { + helper.unloadAgent(ctx.nr.agent) } -tap.test('recordWeb', function (t) { - t.autoend() - t.test('when scope is undefined', function (t) { - t.autoend() - t.beforeEach(beforeEach) - t.afterEach(afterEach) - - t.test("shouldn't crash on recording", function (t) { - const { trans } = t.context - t.doesNotThrow(function () { - const segment = makeSegment({ - transaction: trans, - duration: 0, - exclusive: 0 - }) - recordWeb(segment, undefined) - }) - t.end() - }) +test('recordWeb when scope is undefined', async function (t) { + t.beforeEach(beforeEach) + t.afterEach(afterEach) - t.test('should record no metrics', function (t) { - const { trans } = t.context + await t.test("shouldn't crash on recording", function (t) { + const { trans } = t.nr + assert.doesNotThrow(function () { const segment = makeSegment({ transaction: trans, duration: 0, exclusive: 0 }) recordWeb(segment, undefined) - t.assertMetrics(trans.metrics, [], true, true) - t.end() }) }) - t.test('when recording web transactions with distributed tracing enabled', function (t) { - t.autoend() - t.beforeEach(beforeEach) - t.afterEach(afterEach) - t.test('should record metrics from accepted payload information', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = true - agent.config.cross_application_tracer.enabled = true - agent.config.account_id = '1234' - ;(agent.config.primary_application_id = '5677'), (agent.config.trusted_account_key = '1234') - - const payload = trans._createDistributedTracePayload().text() - trans.isDistributedTrace = null - trans._acceptDistributedTracePayload(payload, 'HTTP') - - record({ - transaction: trans, - apdexT: 0.06, - url: '/test', - code: 200, - duration: 55, - exclusive: 55 - }) + await t.test('should record no metrics', function (t) { + const { trans } = t.nr + const segment = makeSegment({ + transaction: trans, + duration: 0, + exclusive: 0 + }) + recordWeb(segment, undefined) + assertMetrics(trans.metrics, [], true, true) + }) +}) + +test('recordWeb when recording web transactions with distributed tracing enabled', async function (t) { + t.beforeEach(beforeEach) + t.afterEach(afterEach) + await t.test('should record metrics from accepted payload information', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = true + agent.config.cross_application_tracer.enabled = true + agent.config.account_id = '1234' + ;(agent.config.primary_application_id = '5677'), (agent.config.trusted_account_key = '1234') - const result = [ - [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'DurationByCaller/App/1234/5677/HTTP/all' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'TransportDuration/App/1234/5677/HTTP/all' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'DurationByCaller/App/1234/5677/HTTP/allWeb' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'TransportDuration/App/1234/5677/HTTP/allWeb' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], - [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] - ] - - t.assertMetrics(trans.metrics, result, true, true) - t.end() + const payload = trans._createDistributedTracePayload().text() + trans.isDistributedTrace = null + trans._acceptDistributedTracePayload(payload, 'HTTP') + + record({ + transaction: trans, + apdexT: 0.06, + url: '/test', + code: 200, + duration: 55, + exclusive: 55 }) - t.test('should tag metrics with Unknown if no DT payload was received', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = true - agent.config.cross_application_tracer.enabled = true - agent.config.account_id = '1234' - ;(agent.config.primary_application_id = '5677'), (agent.config.trusted_account_key = '1234') + const result = [ + [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'DurationByCaller/App/1234/5677/HTTP/all' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'TransportDuration/App/1234/5677/HTTP/all' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'DurationByCaller/App/1234/5677/HTTP/allWeb' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'TransportDuration/App/1234/5677/HTTP/allWeb' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], + [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] + ] + + assertMetrics(trans.metrics, result, true, true) + }) - record({ - transaction: trans, - apdexT: 0.06, - url: '/test', - code: 200, - duration: 55, - exclusive: 55 - }) + await t.test('should tag metrics with Unknown if no DT payload was received', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = true + agent.config.cross_application_tracer.enabled = true + agent.config.account_id = '1234' + ;(agent.config.primary_application_id = '5677'), (agent.config.trusted_account_key = '1234') - const result = [ - [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/all' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [ - { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], - [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] - ] - - t.assertMetrics(trans.metrics, result, true, true) - t.end() + record({ + transaction: trans, + apdexT: 0.06, + url: '/test', + code: 200, + duration: 55, + exclusive: 55 }) + + const result = [ + [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/all' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [ + { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], + [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] + ] + + assertMetrics(trans.metrics, result, true, true) }) - t.test('with normal requests', function (t) { - t.autoend() - t.beforeEach(beforeEach) - t.afterEach(afterEach) - t.test('should infer a satisfying end-user experience', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = false + await t.test('with exceptional requests should handle internal server errors', function (t) { + const { agent, trans } = t.nr + agent.config.distributed_tracing.enabled = false - record({ - transaction: trans, - apdexT: 0.06, - url: '/test', - code: 200, - duration: 55, - exclusive: 55 - }) + record({ + transaction: trans, + apdexT: 0.01, + url: '/test', + code: 500, + duration: 1, + exclusive: 1 + }) - const result = [ - [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], - [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() + const result = [ + [{ name: 'WebTransaction' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'HttpDispatcher' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.001, 0.001, 0.001, 0.001, 0.000001] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.01, 0.01, 0]], + [{ name: 'Apdex' }, [0, 0, 1, 0.01, 0.01, 0]] + ] + assertMetrics(trans.metrics, result, true, true) + }) +}) + +test('recordWeb when recording web transactions with distributed tracing enabled with normal requests', async function (t) { + t.beforeEach(beforeEach) + t.afterEach(afterEach) + await t.test('should infer a satisfying end-user experience', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = false + + record({ + transaction: trans, + apdexT: 0.06, + url: '/test', + code: 200, + duration: 55, + exclusive: 55 }) - t.test('should infer a tolerable end-user experience', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = false + const result = [ + [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.06, 0.06, 0]], + [{ name: 'Apdex' }, [1, 0, 0, 0.06, 0.06, 0]] + ] + assertMetrics(trans.metrics, result, true, true) + }) - record({ - transaction: trans, - apdexT: 0.05, - url: '/test', - code: 200, - duration: 55, - exclusive: 100 - }) + await t.test('should infer a tolerable end-user experience', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = false - const result = [ - [{ name: 'WebTransaction' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.1, 0.1, 0.1, 0.1, 0.010000000000000002]], - [{ name: 'HttpDispatcher' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.1, 0.1, 0.1, 0.1, 0.010000000000000002] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [0, 1, 0, 0.05, 0.05, 0]], - [{ name: 'Apdex' }, [0, 1, 0, 0.05, 0.05, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() + record({ + transaction: trans, + apdexT: 0.05, + url: '/test', + code: 200, + duration: 55, + exclusive: 100 }) - t.test('should infer a frustrating end-user experience', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = false + const result = [ + [{ name: 'WebTransaction' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.1, 0.1, 0.1, 0.1, 0.010000000000000002]], + [{ name: 'HttpDispatcher' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.1, 0.055, 0.055, 0.003025]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.1, 0.1, 0.1, 0.1, 0.010000000000000002] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [0, 1, 0, 0.05, 0.05, 0]], + [{ name: 'Apdex' }, [0, 1, 0, 0.05, 0.05, 0]] + ] + assertMetrics(trans.metrics, result, true, true) + }) - record({ - transaction: trans, - apdexT: 0.01, - url: '/test', - code: 200, - duration: 55, - exclusive: 55 - }) + await t.test('should infer a frustrating end-user experience', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = false - const result = [ - [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.055, 0.055, 0.055, 0.055, 0.003025] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.01, 0.01, 0]], - [{ name: 'Apdex' }, [0, 0, 1, 0.01, 0.01, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end(0) + record({ + transaction: trans, + apdexT: 0.01, + url: '/test', + code: 200, + duration: 55, + exclusive: 55 }) - t.test('should chop query strings delimited by ? from request URLs', function (t) { - const { trans } = t.context - record({ - transaction: trans, - url: '/test?test1=value1&test2&test3=50' - }) + const result = [ + [{ name: 'WebTransaction' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'HttpDispatcher' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.055, 0.055, 0.055, 0.055, 0.003025]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.055, 0.055, 0.055, 0.055, 0.003025] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.01, 0.01, 0]], + [{ name: 'Apdex' }, [0, 0, 1, 0.01, 0.01, 0]] + ] + assertMetrics(trans.metrics, result, true, true) + }) - t.equal(trans.url, '/test') - t.end() + await t.test('should chop query strings delimited by ? from request URLs', function (t) { + const { trans } = t.nr + record({ + transaction: trans, + url: '/test?test1=value1&test2&test3=50' }) - t.test('should chop query strings delimited by ; from request URLs', function (t) { - const { trans } = t.context - record({ - transaction: trans, - url: '/test;jsessionid=c83048283dd1328ac21aed8a8277d' - }) + assert.equal(trans.url, '/test') + }) - t.equal(trans.url, '/test') - t.end() + await t.test('should chop query strings delimited by ; from request URLs', function (t) { + const { trans } = t.nr + record({ + transaction: trans, + url: '/test;jsessionid=c83048283dd1328ac21aed8a8277d' }) + + assert.equal(trans.url, '/test') + }) +}) + +test("recordWeb when recording web transactions with distributed tracing enabled when testing a web request's apdex", async function (t) { + t.beforeEach(beforeEach) + t.afterEach(afterEach) + await t.test("shouldn't automatically mark ignored status codes as frustrating", function (t) { + const { trans, agent } = t.nr + // FIXME: probably shouldn't do all this through side effects + trans.statusCode = 404 + trans._setApdex('Apdex/Uri/test', 30) + const result = [[{ name: 'Apdex/Uri/test' }, [1, 0, 0, 0.1, 0.1, 0]]] + assert.deepEqual(agent.config.error_collector.ignore_status_codes, [404]) + assertMetrics(trans.metrics, result, true, true) }) - t.test('with exceptional requests should handle internal server errors', function (t) { - beforeEach(t) - afterEach(t) - const { agent, trans } = t.context + await t.test('should handle ignored codes for the whole transaction', function (t) { + const { agent, trans } = t.nr agent.config.distributed_tracing.enabled = false + agent.config.error_collector.ignore_status_codes = [404, 500] record({ transaction: trans, - apdexT: 0.01, + apdexT: 0.2, url: '/test', code: 500, duration: 1, @@ -310,136 +338,86 @@ tap.test('recordWeb', function (t) { { name: 'WebTransactionTotalTime/NormalizedUri/*' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001] ], - [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.01, 0.01, 0]], - [{ name: 'Apdex' }, [0, 0, 1, 0.01, 0.01, 0]] + [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.2, 0.2, 0]], + [{ name: 'Apdex' }, [1, 0, 0, 0.2, 0.2, 0]] ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() + assertMetrics(trans.metrics, result, true, true) }) - t.test("when testing a web request's apdex", function (t) { - t.autoend() - t.beforeEach(beforeEach) - t.afterEach(afterEach) - t.test("shouldn't automatically mark ignored status codes as frustrating", function (t) { - const { trans, agent } = t.context - // FIXME: probably shouldn't do all this through side effects - trans.statusCode = 404 - trans._setApdex('Apdex/Uri/test', 30) - const result = [[{ name: 'Apdex/Uri/test' }, [1, 0, 0, 0.1, 0.1, 0]]] - t.same(agent.config.error_collector.ignore_status_codes, [404]) - t.assertMetrics(trans.metrics, result, true, true) - t.end() - }) - - t.test('should handle ignored codes for the whole transaction', function (t) { - const { agent, trans } = t.context - agent.config.distributed_tracing.enabled = false - agent.config.error_collector.ignore_status_codes = [404, 500] - - record({ - transaction: trans, - apdexT: 0.2, - url: '/test', - code: 500, - duration: 1, - exclusive: 1 - }) + await t.test('should otherwise mark error status codes as frustrating', function (t) { + const { trans } = t.nr + // FIXME: probably shouldn't do all this through side effects + trans.statusCode = 503 + trans._setApdex('Apdex/Uri/test', 30) + const result = [[{ name: 'Apdex/Uri/test' }, [0, 0, 1, 0.1, 0.1, 0]]] + assertMetrics(trans.metrics, result, true, true) + }) - const result = [ - [{ name: 'WebTransaction' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'HttpDispatcher' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.001, 0.001, 0.001, 0.001, 0.000001] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.2, 0.2, 0]], - [{ name: 'Apdex' }, [1, 0, 0, 0.2, 0.2, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() + await t.test('should handle non-ignored codes for the whole transaction', function (t) { + const { trans, agent } = t.nr + agent.config.distributed_tracing.enabled = false + record({ + transaction: trans, + apdexT: 0.2, + url: '/test', + code: 503, + duration: 1, + exclusive: 1 }) - t.test('should otherwise mark error status codes as frustrating', function (t) { - const { trans } = t.context - // FIXME: probably shouldn't do all this through side effects - trans.statusCode = 503 - trans._setApdex('Apdex/Uri/test', 30) - const result = [[{ name: 'Apdex/Uri/test' }, [0, 0, 1, 0.1, 0.1, 0]]] - t.assertMetrics(trans.metrics, result, true, true) - t.end() - }) + const result = [ + [{ name: 'WebTransaction' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'HttpDispatcher' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [{ name: 'WebTransactionTotalTime' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], + [ + { name: 'WebTransactionTotalTime/NormalizedUri/*' }, + [1, 0.001, 0.001, 0.001, 0.001, 0.000001] + ], + [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.2, 0.2, 0]], + [{ name: 'Apdex' }, [0, 0, 1, 0.2, 0.2, 0]] + ] + assertMetrics(trans.metrics, result, true, true) + }) - t.test('should handle non-ignored codes for the whole transaction', function (t) { - const { trans, agent } = t.context - agent.config.distributed_tracing.enabled = false - record({ - transaction: trans, - apdexT: 0.2, - url: '/test', - code: 503, - duration: 1, - exclusive: 1 - }) + await t.test('should reflect key transaction apdexT', function (t) { + const { trans, agent } = t.nr + agent.config.web_transactions_apdex = { + 'WebTransaction/WebFrameworkUri/TestJS//key/:id': 0.667, + // just to make sure + 'WebTransaction/WebFrameworkUri/TestJS//another/:name': 0.444 + } + trans.nameState.setName('TestJS', null, '/', '/key/:id') - const result = [ - [{ name: 'WebTransaction' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'HttpDispatcher' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'WebTransaction/NormalizedUri/*' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [{ name: 'WebTransactionTotalTime' }, [1, 0.001, 0.001, 0.001, 0.001, 0.000001]], - [ - { name: 'WebTransactionTotalTime/NormalizedUri/*' }, - [1, 0.001, 0.001, 0.001, 0.001, 0.000001] - ], - [{ name: 'Apdex/NormalizedUri/*' }, [0, 0, 1, 0.2, 0.2, 0]], - [{ name: 'Apdex' }, [0, 0, 1, 0.2, 0.2, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() + record({ + transaction: trans, + apdexT: 0.2, + url: '/key/23', + code: 200, + duration: 1200, + exclusive: 1200 }) - t.test('should reflect key transaction apdexT', function (t) { - const { trans, agent } = t.context - agent.config.web_transactions_apdex = { - 'WebTransaction/WebFrameworkUri/TestJS//key/:id': 0.667, - // just to make sure - 'WebTransaction/WebFrameworkUri/TestJS//another/:name': 0.444 - } - trans.nameState.setName('TestJS', null, '/', '/key/:id') - - record({ - transaction: trans, - apdexT: 0.2, - url: '/key/23', - code: 200, - duration: 1200, - exclusive: 1200 - }) - - const result = [ - [{ name: 'WebTransaction' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], - [{ name: 'HttpDispatcher' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], - [{ name: 'WebTransaction/WebFrameworkUri/TestJS//key/:id' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], - [ - { name: 'WebTransactionTotalTime/WebFrameworkUri/TestJS//key/:id' }, - [1, 1.2, 1.2, 1.2, 1.2, 1.44] - ], - [{ name: 'WebTransactionTotalTime' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], - [ - { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/all' }, - [1, 1.2, 1.2, 1.2, 1.2, 1.44] - ], - [ - { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb' }, - [1, 1.2, 1.2, 1.2, 1.2, 1.44] - ], - [{ name: 'Apdex/WebFrameworkUri/TestJS//key/:id' }, [0, 1, 0, 0.667, 0.667, 0]], - [{ name: 'Apdex' }, [0, 1, 0, 0.2, 0.2, 0]] - ] - t.assertMetrics(trans.metrics, result, true, true) - t.end() - }) + const result = [ + [{ name: 'WebTransaction' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], + [{ name: 'HttpDispatcher' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], + [{ name: 'WebTransaction/WebFrameworkUri/TestJS//key/:id' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], + [ + { name: 'WebTransactionTotalTime/WebFrameworkUri/TestJS//key/:id' }, + [1, 1.2, 1.2, 1.2, 1.2, 1.44] + ], + [{ name: 'WebTransactionTotalTime' }, [1, 1.2, 1.2, 1.2, 1.2, 1.44]], + [ + { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/all' }, + [1, 1.2, 1.2, 1.2, 1.2, 1.44] + ], + [ + { name: 'DurationByCaller/Unknown/Unknown/Unknown/Unknown/allWeb' }, + [1, 1.2, 1.2, 1.2, 1.2, 1.44] + ], + [{ name: 'Apdex/WebFrameworkUri/TestJS//key/:id' }, [0, 1, 0, 0.667, 0.667, 0]], + [{ name: 'Apdex' }, [0, 1, 0, 0.2, 0.2, 0]] + ] + assertMetrics(trans.metrics, result, true, true) }) }) diff --git a/test/unit/metrics-recorder/queue-time-http.test.js b/test/unit/metrics-recorder/queue-time-http.test.js index 42a1e2fd34..adb9aa16e8 100644 --- a/test/unit/metrics-recorder/queue-time-http.test.js +++ b/test/unit/metrics-recorder/queue-time-http.test.js @@ -5,10 +5,9 @@ 'use strict' -const tap = require('tap') - +const test = require('node:test') const helper = require('../../lib/agent_helper') -require('../../lib/metrics_helper') +const { assertMetricValues } = require('../../lib/custom-assertions') const recordWeb = require('../../../lib/metrics/recorders/http') const Transaction = require('../../../lib/transaction') @@ -34,20 +33,19 @@ function record(options) { recordWeb(segment, options.transaction.name) } -tap.test('when recording queueTime', (test) => { - let agent - let trans - - test.beforeEach(() => { - agent = helper.instrumentMockedAgent() - trans = new Transaction(agent) +test('when recording queueTime', async (t) => { + t.beforeEach((ctx) => { + ctx.nr = {} + ctx.nr.agent = helper.instrumentMockedAgent() + ctx.nr.trans = new Transaction(ctx.nr.agent) }) - test.afterEach(() => { - helper.unloadAgent(agent) + t.afterEach((ctx) => { + helper.unloadAgent(ctx.nr.agent) }) - test.test('non zero times should record a metric', (t) => { + await t.test('non zero times should record a metric', (t) => { + const { trans } = t.nr record({ transaction: trans, apdexT: 0.2, @@ -80,12 +78,11 @@ tap.test('when recording queueTime', (test) => { [{ name: 'Apdex' }, [1, 0, 0, 0.2, 0.2, 0]] ] - t.assertMetricValues(trans, result, true) - - t.end() + assertMetricValues(trans, result, true) }) - test.test('zero times should not record a metric', (t) => { + await t.test('zero times should not record a metric', (t) => { + const { trans } = t.nr record({ transaction: trans, apdexT: 0.2, @@ -116,9 +113,6 @@ tap.test('when recording queueTime', (test) => { [{ name: 'Apdex/NormalizedUri/*' }, [1, 0, 0, 0.2, 0.2, 0]], [{ name: 'Apdex' }, [1, 0, 0, 0.2, 0.2, 0]] ] - t.assertMetricValues(trans, result, true) - - t.end() + assertMetricValues(trans, result, true) }) - test.end() })