From dfbd589d6c7223d35eea9eb5da02d4580ba264b1 Mon Sep 17 00:00:00 2001 From: Natalie Wolfe Date: Thu, 1 Feb 2018 13:50:36 -0800 Subject: [PATCH 1/4] Delinting stub test --- test/unit/api/stub.test.js | 166 +++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 82 deletions(-) diff --git a/test/unit/api/stub.test.js b/test/unit/api/stub.test.js index e6e7be7a2f..6588f40f9d 100644 --- a/test/unit/api/stub.test.js +++ b/test/unit/api/stub.test.js @@ -22,237 +22,239 @@ describe("the stubbed New Relic agent API", function() { expect(api.setTransactionName).a('function') }) - it("exports a dispatcher naming function", function () { + it("exports a dispatcher naming function", function() { should.exist(api.setDispatcher) expect(api.setDispatcher).a('function') }) - it("shouldn't throw when transaction is named", function () { - expect(function () { api.setTransactionName('TEST/*'); }).not.throws() + it("shouldn't throw when transaction is named", function() { + expect(function() { api.setTransactionName('TEST/*') }).not.throws() }) - it("exports a controller naming function", function () { + it("exports a controller naming function", function() { should.exist(api.setControllerName) expect(api.setControllerName).a('function') }) - it("shouldn't throw when controller is named without an action", function () { - expect(function () { api.setControllerName('TEST/*'); }).not.throws() + it("shouldn't throw when controller is named without an action", function() { + expect(function() { api.setControllerName('TEST/*') }).not.throws() }) - it("shouldn't throw when controller is named with an action", function () { - expect(function () { api.setControllerName('TEST/*', 'test'); }).not.throws() + it("shouldn't throw when controller is named with an action", function() { + expect(function() { api.setControllerName('TEST/*', 'test') }).not.throws() }) - it("exports a transaction ignoring function", function () { + it("exports a transaction ignoring function", function() { should.exist(api.setIgnoreTransaction) expect(api.setIgnoreTransaction).a('function') }) - it("exports a function to get the current transaction handle", function () { + it("exports a function to get the current transaction handle", function() { should.exist(api.getTransaction) expect(api.getTransaction).a('function') }) - it("exports a function for adding naming rules", function () { + it("exports a function for adding naming rules", function() { should.exist(api.addNamingRule) expect(api.addNamingRule).a('function') }) - it("shouldn't throw when a naming rule is added", function () { - expect(function () { api.addNamingRule(/^foo/, "/foo/*"); }).not.throws() + it("shouldn't throw when a naming rule is added", function() { + expect(function() { api.addNamingRule(/^foo/, "/foo/*") }).not.throws() }) - it("exports a function for ignoring certain URLs", function () { + it("exports a function for ignoring certain URLs", function() { should.exist(api.addIgnoringRule) expect(api.addIgnoringRule).a('function') }) - it("shouldn't throw when an ignoring rule is added", function () { - expect(function () { api.addIgnoringRule(/^foo/, "/foo/*"); }).not.throws() + it("shouldn't throw when an ignoring rule is added", function() { + expect(function() { api.addIgnoringRule(/^foo/, "/foo/*") }).not.throws() }) - it("exports a function for capturing errors", function () { + it("exports a function for capturing errors", function() { should.exist(api.noticeError) expect(api.noticeError).a('function') }) - it("shouldn't throw when an error is added", function () { - expect(function () { api.noticeError(new Error()); }).not.throws() + it("shouldn't throw when an error is added", function() { + expect(function() { api.noticeError(new Error()) }).not.throws() }) - it("should return an empty string when requesting browser monitoring", function () { + it("should return an empty string when requesting browser monitoring", function() { api.getBrowserTimingHeader().should.equal('') }) - it("exports a function for adding custom parameters", function () { + it("exports a function for adding custom parameters", function() { should.exist(api.addCustomParameter) expect(api.addCustomParameter).a('function') }) - it("shouldn't throw when a custom parameter is added", function () { - expect(function () { api.addCustomParameter('test', 'value'); }).not.throws() + it("shouldn't throw when a custom parameter is added", function() { + expect(function() { api.addCustomParameter('test', 'value') }).not.throws() }) - it("exports a function for adding multiple custom parameters at once", function () { + it("exports a function for adding multiple custom parameters at once", function() { should.exist(api.addCustomParameters) expect(api.addCustomParameters).a('function') }) - it("shouldn't throw when multiple custom parameters are added", function () { - expect(function () { api.addCustomParameters({test: 'value', test2: 'value2'}); }).not.throws() + it("shouldn't throw when multiple custom parameters are added", function() { + expect(function() { + api.addCustomParameters({test: 'value', test2: 'value2'}) + }).to.not.throw() }) - it("shouldn't throw when a custom segment is added", function () { - expect(function () { - api.createTracer('name', function nop(){}) + it("shouldn't throw when a custom segment is added", function() { + expect(function() { + api.createTracer('name', function nop() {}) }).not.throws() }) - it("should return a function when calling createTracer", function () { - function myNop () {} + it("should return a function when calling createTracer", function() { + function myNop() {} var retVal = api.createTracer('name', myNop) expect(retVal).to.be.equal(myNop) }) - it("shouldn't throw when a custom web transaction is started", function () { - expect(function () { - api.startWebTransaction('test', function nop(){}) + it("shouldn't throw when a custom web transaction is started", function() { + expect(function() { + api.startWebTransaction('test', function nop() {}) }).not.throws() }) - it("should call the function passed into startWebTransaction", function (done) { - api.startWebTransaction('test', function nop(){ + it("should call the function passed into startWebTransaction", function(done) { + api.startWebTransaction('test', function nop() { done() }) }) - it("shouldn't throw when a callback isn't passed into startWebTransaction", function () { - expect(function () { + it("shouldn't throw when a callback isn't passed into startWebTransaction", function() { + expect(function() { api.startWebTransaction('test') }).not.throws() }) - it("shouldn't throw when a non-function callback is passed into startWebTransaction", function () { - expect(function () { + it("shouldn't throw when a non-function callback is passed into startWebTransaction", function() { + expect(function() { api.startWebTransaction('test', 'asdf') }).not.throws() }) - it("shouldn't throw when a custom background transaction is started", function () { - expect(function () { - api.startBackgroundTransaction('test', 'group', function nop(){}) + it("shouldn't throw when a custom background transaction is started", function() { + expect(function() { + api.startBackgroundTransaction('test', 'group', function nop() {}) }).not.throws() }) - it("should call the function passed into startBackgroundTransaction", function (done) { - api.startBackgroundTransaction('test', 'group', function nop(){ + it("should call the function passed into startBackgroundTransaction", function(done) { + api.startBackgroundTransaction('test', 'group', function nop() { done() }) }) - it("shouldn't throw when a callback isn't passed into startBackgroundTransaction", function () { - expect(function () { + it("shouldn't throw when a callback isn't passed into startBackgroundTransaction", function() { + expect(function() { api.startBackgroundTransaction('test', 'group') }).not.throws() }) - it("shouldn't throw when a non-function callback is passed into startBackgroundTransaction", function () { - expect(function () { + it("shouldn't throw when a non-function callback is passed into startBackgroundTransaction", function() { + expect(function() { api.startBackgroundTransaction('test', 'group', 'asdf') }).not.throws() }) - it("shouldn't throw when a custom background transaction is started with no group", function () { - expect(function () { - api.startBackgroundTransaction('test', function nop(){}) + it("shouldn't throw when a custom background transaction is started with no group", function() { + expect(function() { + api.startBackgroundTransaction('test', function nop() {}) }).not.throws() }) - it("should call the function passed into startBackgroundTransaction with no group", function (done) { - api.startBackgroundTransaction('test', function nop(){ + it("should call the function passed into startBackgroundTransaction with no group", function(done) { + api.startBackgroundTransaction('test', function nop() { done() }) }) - it("shouldn't throw when a callback isn't passed into startBackgroundTransaction with no group", function () { - expect(function () { + it("shouldn't throw when a callback isn't passed into startBackgroundTransaction with no group", function() { + expect(function() { api.startBackgroundTransaction('test') }).not.throws() }) - it("shouldn't throw when a custom web transaction is added", function () { - expect(function () { - api.createWebTransaction('name', function nop(){}) + it("shouldn't throw when a custom web transaction is added", function() { + expect(function() { + api.createWebTransaction('name', function nop() {}) }).not.throws() }) - it("should return a function when calling createWebTransaction", function () { - function myNop () {} + it("should return a function when calling createWebTransaction", function() { + function myNop() {} var retVal = api.createWebTransaction('name', myNop) expect(retVal).to.be.equal(myNop) }) - it("shouldn't throw when a custom background transaction is added", function () { - expect(function () { - api.createBackgroundTransaction('name', function nop(){}) + it("shouldn't throw when a custom background transaction is added", function() { + expect(function() { + api.createBackgroundTransaction('name', function nop() {}) }).not.throws() }) - it("should return a function when calling createBackgroundTransaction", function () { - function myNop () {} + it("should return a function when calling createBackgroundTransaction", function() { + function myNop() {} var retVal = api.createBackgroundTransaction('name', myNop) expect(retVal).to.be.equal(myNop) }) - it("shouldn't throw when a custom background transaction with a group is added", function () { - expect(function () { - api.createBackgroundTransaction('name', 'group', function nop(){}) + it("shouldn't throw when a custom background transaction with a group is added", function() { + expect(function() { + api.createBackgroundTransaction('name', 'group', function nop() {}) }).not.throws() }) - it("should return a function when calling createBackgroundTransaction", function () { - function myNop () {} + it("should return a function when calling createBackgroundTransaction", function() { + function myNop() {} var retVal = api.createBackgroundTransaction('name', 'group', myNop) expect(retVal).to.be.equal(myNop) }) - it("shouldn't throw when a transaction is ended", function () { - expect(function () { + it("shouldn't throw when a transaction is ended", function() { + expect(function() { api.endTransaction() }).not.throws() }) - it('exports a metric recording function', function () { + it('exports a metric recording function', function() { should.exist(api.recordMetric) expect(api.recordMetric).a('function') }) - it('should not throw when calling the metric recorder', function () { - expect(function () { + it('should not throw when calling the metric recorder', function() { + expect(function() { api.recordMetric('metricname', 1) }).not.throws() }) - it('exports a metric increment function', function () { + it('exports a metric increment function', function() { should.exist(api.incrementMetric) expect(api.incrementMetric).a('function') }) - it('should not throw when calling a metric incrementor', function () { - expect(function () { + it('should not throw when calling a metric incrementor', function() { + expect(function() { api.incrementMetric('metric name') }).not.throws() }) - it('exports a record custom event function', function () { + it('exports a record custom event function', function() { should.exist(api.recordCustomEvent) expect(api.recordCustomEvent).a('function') }) - it('should not throw when calling the custom metric recorder', function () { - expect(function () { + it('should not throw when calling the custom metric recorder', function() { + expect(function() { api.recordCustomEvent('EventName', {id: 10}) }).not.throws() }) From 5c8dc444d83d1491d63432cf08172b211a1469c6 Mon Sep 17 00:00:00 2001 From: Natalie Wolfe Date: Tue, 23 Jan 2018 11:23:54 -0800 Subject: [PATCH 2/4] Add newrelic.startSegment --- api.js | 78 ++++++++++++++++++- .../background-transactions/example1-basic.js | 2 +- examples/api/segments/example1-callbacks.js | 33 ++++++++ examples/api/segments/example2-promises.js | 24 ++++++ examples/api/segments/example3-async.js | 22 ++++++ stub_api.js | 16 +++- test/unit/api/stub.test.js | 4 +- 7 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 examples/api/segments/example1-callbacks.js create mode 100644 examples/api/segments/example2-promises.js create mode 100644 examples/api/segments/example3-async.js diff --git a/api.js b/api.js index f4018f39a1..172d820990 100644 --- a/api.js +++ b/api.js @@ -629,13 +629,23 @@ API.prototype.getBrowserTimingHeader = function getBrowserTimingHeader() { return out } +API.prototype.createTracer = util.deprecate( + createTracer, [ + 'API#createTracer is being deprecated!', + 'Please use API#startSegment for segment creation.' + ].join(' ') +) + /** * This creates a new tracer with the passed in name. It then wraps the * callback and binds it to the current transaction and segment so any further * custom instrumentation as well as auto instrumentation will also be able to * find the current transaction and segment. + * + * @memberof API# + * @deprecated use {@link API#startSegment} instead */ -API.prototype.createTracer = function createTracer(name, callback) { +function createTracer(name, callback) { var metric = this.agent.metrics.getOrCreateMetric( NAMES.SUPPORTABILITY.API + '/createTracer' ) @@ -687,6 +697,70 @@ API.prototype.createTracer = function createTracer(name, callback) { return arity.fixArity(callback, tracer.bindFunction(callback, segment, true)) } +/** + * Wraps the given handler in a segment which may optionally be turned into a + * metric. + * + * @example + * newrelic.startSegment('mySegment', false, function handler() { + * // The returned promise here will signify the end of the segment. + * return myAsyncTask().then(myNextTask) + * }) + * + * @param {string} name + * The name to give the new segment. This will also be the name of the metric. + * + * @param {bool} record + * Indicates if the segment should be recorded as a metric. Metrics will show + * up on the transaction breakdown table and server breakdown graph. Segments + * just show up in transaction traces. + * + * @param {function(cb) -> ?Promise} handler + * The function to track as a segment. + * + * @param {function} [callback] + * An optional callback for the handler. This will indicate the end of the + * timing if provided. + * + * @return {*} Returns the result of calling `handler`. + */ +API.prototype.startSegment = function startSegment(name, record, handler, callback) { + this.agent.metrics.getOrCreateMetric( + NAMES.SUPPORTABILITY.API + '/startSegment' + ).incrementCallCount() + + // Check that we have usable arguments. + if (!name || typeof handler !== 'function') { + logger.warn('Name and handler function are both required for startSegment') + if (typeof handler === 'function') { + return handler(callback) + } + return + } + if (callback && typeof callback !== 'function') { + logger.warn('If using callback, it must be a function') + return handler(callback) + } + + // Are we inside a transaction? + if (!this.shim.getActiveSegment()) { + logger.debug('startSegment(%j) called outside of a transaction, not recording.', name) + return handler(callback) + } + + // Create the segment and call the handler. + var wrappedHandler = this.shim.record(handler, function handlerNamer(shim) { + return { + name: name, + recorder: record ? customRecorder : null, + callback: callback ? shim.FIRST : null, + promise: !!callback + } + }) + + return wrappedHandler(callback) +} + API.prototype.createWebTransaction = util.deprecate( createWebTransaction, [ 'API#createWebTransaction is being deprecated!', @@ -713,7 +787,7 @@ API.prototype.createWebTransaction = util.deprecate( name and not iclude any variable parameters. * @param {Function} handle Function that represents the transaction work. * - * @memberOf API# + * @memberof API# * * @deprecated since version 2.0 */ diff --git a/examples/api/background-transactions/example1-basic.js b/examples/api/background-transactions/example1-basic.js index d476f9959e..8e71bf4189 100644 --- a/examples/api/background-transactions/example1-basic.js +++ b/examples/api/background-transactions/example1-basic.js @@ -4,7 +4,7 @@ var newrelic = require('newrelic') var transactionName = 'myCustomTransaction' -// startBackgroundTransaction() takes a name, group, and a handler function to +// `startBackgroundTransaction()` takes a name, group, and a handler function to // execute. The group is optional. The last parameter is the function performing // the work inside the transaction. Once the transaction starts, there are // three ways to end it: diff --git a/examples/api/segments/example1-callbacks.js b/examples/api/segments/example1-callbacks.js new file mode 100644 index 0000000000..5533074982 --- /dev/null +++ b/examples/api/segments/example1-callbacks.js @@ -0,0 +1,33 @@ +'use strict' + +var newrelic = require('newrelic') + +// Segments can only be created inside of transactions. They could be automatically +// generated HTTP transactions or custom transactions. +newrelic.startBackgroundTransaction('bg-tx', function transHandler() { + var tx = newrelic.getTransaction() + + // `startSegment()` takes a segment name, a boolean if a metric should be + // created for this segment, the handler function, and an optional callback. + // The handler is the function that will be wrapped with the new segment. When + // a callback is provided, the segment timing will end when the callback is + // called. + + newrelic.startSegment('myCustomSegment', false, someTask, function cb(err, output) { + // Handle the error and output as appropriate. + console.log(output) + tx.end() + }) +}) + +function someTask(cb) { + myAsyncTask(function firstCb(err, result) { + if (err) { + return cb(err) + } + + myNextTask(result, function secondCb(err, output) { + cb(err, output) + }) + }) +} diff --git a/examples/api/segments/example2-promises.js b/examples/api/segments/example2-promises.js new file mode 100644 index 0000000000..31741be36f --- /dev/null +++ b/examples/api/segments/example2-promises.js @@ -0,0 +1,24 @@ +'use strict' + +var newrelic = require('newrelic') + +// Segments can only be created inside of transactions. They could be automatically +// generated HTTP transactions or custom transactions. +newrelic.startBackgroundTransaction('bg-tx', function transHandler() { + // `startSegment()` takes a segment name, a boolean if a metric should be + // created for this segment, the handler function, and an optional callback. + // The handler is the function that will be wrapped with the new segment. If + // a promise is returned from the handler, the segment's ending will be tied + // to that promise resolving or rejecting. + + return newrelic.startSegment('myCustomSegment', false, someTask) + .then(function thenAfter(output) { + console.log(output) + }) +}) + +function someTask() { + return myAsyncTask().then(function thenNext(result) { + return myNextTask(result) + }) +} diff --git a/examples/api/segments/example3-async.js b/examples/api/segments/example3-async.js new file mode 100644 index 0000000000..f4cc4f0164 --- /dev/null +++ b/examples/api/segments/example3-async.js @@ -0,0 +1,22 @@ +'use strict' + +var newrelic = require('newrelic') + +// Segments can only be created inside of transactions. They could be automatically +// generated HTTP transactions or custom transactions. +newrelic.startBackgroundTransaction('bg-tx', async function transHandler() { + // `startSegment()` takes a segment name, a boolean if a metric should be + // created for this segment, the handler function, and an optional callback. + // The handler is the function that will be wrapped with the new segment. + // Since `async` functions just return a promise, they are covered just the + // same as the promise example. + + var output = await newrelic.startSegment('myCustomSegment', false, someTask) + console.log(output) +}) + +async function someTask() { + var result = await myAsyncTask() + var output = await myNextTask(result) + return output +} diff --git a/stub_api.js b/stub_api.js index a73793696a..7e4d229e64 100644 --- a/stub_api.js +++ b/stub_api.js @@ -30,7 +30,12 @@ for (var i = 0; i < length; i++) { Stub.prototype[functionName] = stubFunction(functionName) } -Stub.prototype.createTracer = createTracer +Stub.prototype.createTracer = util.deprecate( + createTracer, [ + 'API#createTracer is being deprecated!', + 'Please use API#startSegment for segment creation.' + ].join(' ') +) Stub.prototype.createWebTransaction = util.deprecate( createWebTransaction, [ 'API#createWebTransaction is being deprecated!', @@ -47,6 +52,7 @@ Stub.prototype.createBackgroundTransaction = util.deprecate( 'ending transactions.' ].join(' ') ) +Stub.prototype.startSegment = startSegment Stub.prototype.startWebTransaction = startWebTransaction Stub.prototype.startBackgroundTransaction = startBackgroundTransaction Stub.prototype.getTransaction = getTransaction @@ -81,6 +87,14 @@ function createBackgroundTransaction(name, group, callback) { return (callback === undefined) ? group : callback } +function startSegment(name, record, handler, callback) { + logger.debug('Not calling `startSegment` becuase New Relic is disabled.') + if (typeof handler === 'function') { + return handler(callback) + } + return null +} + function startWebTransaction(url, callback) { logger.debug('Not calling startWebTransaction because New Relic is disabled.') if (typeof callback === 'function') { diff --git a/test/unit/api/stub.test.js b/test/unit/api/stub.test.js index 6588f40f9d..ac67e791ac 100644 --- a/test/unit/api/stub.test.js +++ b/test/unit/api/stub.test.js @@ -13,8 +13,8 @@ describe("the stubbed New Relic agent API", function() { api = new API() }) - it("should export 27 API calls", function() { - expect(Object.keys(api.constructor.prototype).length).to.equal(27) + it("should export 28 API calls", function() { + expect(Object.keys(api.constructor.prototype).length).to.equal(28) }) it("exports a transaction naming function", function() { From 77129ceec35eb9f600df59b1e0d38416079eaa82 Mon Sep 17 00:00:00 2001 From: Natalie Wolfe Date: Thu, 1 Feb 2018 14:55:47 -0800 Subject: [PATCH 3/4] Added tests for startSegment --- api.js | 2 +- test/unit/api/api.test.js | 85 ++++++++++++++++++++++++++++++++++++++ test/unit/api/stub.test.js | 19 ++++++++- 3 files changed, 103 insertions(+), 3 deletions(-) diff --git a/api.js b/api.js index 172d820990..43e2d0749c 100644 --- a/api.js +++ b/api.js @@ -754,7 +754,7 @@ API.prototype.startSegment = function startSegment(name, record, handler, callba name: name, recorder: record ? customRecorder : null, callback: callback ? shim.FIRST : null, - promise: !!callback + promise: !callback } }) diff --git a/test/unit/api/api.test.js b/test/unit/api/api.test.js index 32943bdc1f..06c1bc29d1 100644 --- a/test/unit/api/api.test.js +++ b/test/unit/api/api.test.js @@ -262,6 +262,91 @@ describe('the New Relic agent API', function() { }) }) + describe('when creating a segment with `startSegment`', function() { + it('should name the segment as provided', function() { + helper.runInTransaction(agent, function() { + api.startSegment('foobar', false, function() { + var segment = api.shim.getSegment() + expect(segment).to.exist().and.have.property('name', 'foobar') + }) + }) + }) + + it('should return the return value of the handler', function() { + helper.runInTransaction(agent, function() { + var obj = {} + var ret = api.startSegment('foobar', false, function() { + return obj + }) + expect(ret).to.equal(obj) + }) + }) + + it('should not record a metric when `record` is `false`', function(done) { + helper.runInTransaction(agent, function(tx) { + tx.name = 'test' + api.startSegment('foobar', false, function() { + var segment = api.shim.getSegment() + expect(segment).to.exist().and.have.property('name', 'foobar') + }) + tx.end(function() { + expect(tx.metrics.scoped).to.not.have.property(tx.name) + expect(tx.metrics.unscoped).to.not.have.property('Custom/foobar') + done() + }) + }) + }) + + it('should record a metric when `record` is `true`', function(done) { + helper.runInTransaction(agent, function(tx) { + tx.name = 'test' + api.startSegment('foobar', true, function() { + var segment = api.shim.getSegment() + expect(segment).to.exist().and.have.property('name', 'foobar') + }) + tx.end(function() { + expect(tx.metrics.scoped).property(tx.name) + .to.have.property('Custom/foobar') + expect(tx.metrics.unscoped).to.have.property('Custom/foobar') + done() + }) + }) + }) + + it('should time the segment from the callback if provided', function(done) { + helper.runInTransaction(agent, function() { + api.startSegment('foobar', false, function(cb) { + var segment = api.shim.getSegment() + setTimeout(cb, 150, null, segment) + }, function(err, segment) { + expect(err).to.be.null() + expect(segment).to.exist() + expect(segment.getDurationInMillis()).to.be.within(100, 200) + done() + }) + }) + }) + + it('should time the segment from a returned promise', function() { + // TODO: Once Node <0.12 is deprecated, remove this check for Promise. + if (!global.Promise) { + return + } + + return helper.runInTransaction(agent, function() { + return api.startSegment('foobar', false, function() { + var segment = api.shim.getSegment() + return new Promise(function(resolve) { + setTimeout(resolve, 150, segment) + }) + }).then(function(segment) { + expect(segment).to.exist() + expect(segment.getDurationInMillis()).to.be.within(100, 200) + }) + }) + }) + }) + describe("when starting a web transaction using startWebTransaction", function() { var thenCalled = false var FakePromise = { diff --git a/test/unit/api/stub.test.js b/test/unit/api/stub.test.js index ac67e791ac..553728c593 100644 --- a/test/unit/api/stub.test.js +++ b/test/unit/api/stub.test.js @@ -27,7 +27,6 @@ describe("the stubbed New Relic agent API", function() { expect(api.setDispatcher).a('function') }) - it("shouldn't throw when transaction is named", function() { expect(function() { api.setTransactionName('TEST/*') }).not.throws() }) @@ -115,7 +114,23 @@ describe("the stubbed New Relic agent API", function() { it("should return a function when calling createTracer", function() { function myNop() {} var retVal = api.createTracer('name', myNop) - expect(retVal).to.be.equal(myNop) + expect(retVal).to.equal(myNop) + }) + + it('should call the function passed into `startSegment`', function(done) { + api.startSegment('foo', false, done) + }) + + it('should not throw when a non-function is passed to `startSegment`', function() { + expect(function() { + api.startSegment('foo', false, null) + }).to.not.throw() + }) + + it('should return the return value of the handler', function() { + var obj = {} + var ret = api.startSegment('foo', false, function() { return obj }) + expect(obj).to.equal(ret) }) it("shouldn't throw when a custom web transaction is started", function() { From 2bf0d2f050d88109e0ed44b95a16e7cfbcc0b62e Mon Sep 17 00:00:00 2001 From: Peter Svetlichny Date: Mon, 26 Mar 2018 12:11:24 -0700 Subject: [PATCH 4/4] chore(api): add sync startSegment example --- examples/api/segments/example4-sync-assign.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 examples/api/segments/example4-sync-assign.js diff --git a/examples/api/segments/example4-sync-assign.js b/examples/api/segments/example4-sync-assign.js new file mode 100644 index 0000000000..ba8cbf80d9 --- /dev/null +++ b/examples/api/segments/example4-sync-assign.js @@ -0,0 +1,22 @@ +'use strict' + +var newrelic = require('newrelic') + +// Segments can only be created inside of transactions. They could be automatically +// generated HTTP transactions or custom transactions. +newrelic.startBackgroundTransaction('bg-tx', function transHandler() { + // `startSegment()` takes a segment name, a boolean if a metric should be + // created for this segment, the handler function, and an optional callback. + // The handler is the function that will be wrapped with the new segment. + + var output = newrelic.startSegment('myCustomSegment', false, function timedFunction() { + return someSyncTask() + }) + console.log(output) +}) + +function someSyncTask() { + var result = mySyncTask() + var output = myNextTask(result) + return output +}