Skip to content

Commit

Permalink
Merge pull request newrelic#106 from bizob2828/wrap-externals-v3
Browse files Browse the repository at this point in the history
Wrap externals v3
  • Loading branch information
michaelgoin authored Nov 18, 2021
2 parents 467e82c + f18a6ec commit 1cfb912
Show file tree
Hide file tree
Showing 30 changed files with 1,097 additions and 51 deletions.
2 changes: 1 addition & 1 deletion merged/aws-sdk/THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ SOFTWARE.

### newrelic

This product includes source derived from [newrelic](https://github.com/newrelic/node-newrelic) ([v8.1.0](https://github.com/newrelic/node-newrelic/tree/v8.1.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic/blob/v8.1.0/LICENSE):
This product includes source derived from [newrelic](https://github.com/newrelic/node-newrelic) ([v8.6.0](https://github.com/newrelic/node-newrelic/tree/v8.6.0)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic/blob/v8.6.0/LICENSE):

```
Apache License
Expand Down
4 changes: 4 additions & 0 deletions merged/aws-sdk/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
const newrelic = require('newrelic')
newrelic.instrumentConglomerate('aws-sdk', require('./lib/instrumentation'))
newrelic.instrumentMessages('@aws-sdk/client-sns', require('./lib/v3-sns'))
newrelic.instrument({
moduleName: '@aws-sdk/smithy-client',
onResolved: require('./lib/smithy-client')
})
6 changes: 1 addition & 5 deletions merged/aws-sdk/lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,7 @@ function wrapMakeRequest(shim, fn, name, request) {

const promise = shim.applySegment(original, activeSegment, false, this, arguments)

// TODO: convert to shim.bindPromise() once released.
return shim.interceptPromise(promise, function thenTouch() {
activeSegment.opaque = false
activeSegment.touch()
})
return shim.bindPromise(promise, activeSegment)
}
})
}
Expand Down
121 changes: 121 additions & 0 deletions merged/aws-sdk/lib/smithy-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright 2021 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'
const UNKNOWN = 'Unknown'

module.exports = function instrumentSmithyClient(shim, name, resolvedName) {
const fileNameIndex = resolvedName.indexOf('/index')
const relativeFolder = resolvedName.substr(0, fileNameIndex)

// The path changes depending on the version... so we don't want to hard-code the relative
// path from the module root.
const smithyClientExport = shim.require(`${relativeFolder}/client`)

if (!shim.isFunction(smithyClientExport.Client)) {
shim.logger.debug('Could not find Smithy Client, not instrumenting.')
return
}

shim.wrapClass(smithyClientExport, 'Client', { post: postClientConstructor, es6: true })
}

/**
* Calls the instances middlewareStack.use to register
* a plugin that adds 2 different middleware at various
* stages of a middleware stack
* see: https://aws.amazon.com/blogs/developer/middleware-stack-modular-aws-sdk-js/
*
* @param {Shim} shim
*/
function postClientConstructor(shim) {
this.middlewareStack.use(getPlugin(shim, this.config))
}

/**
* Returns the plugin object that adds 2 middleware
*
* @param {Shim} shim
* @param {Object} config smithy client config
*/
function getPlugin(shim, config) {
return {
applyToStack: (clientStack) => {
clientStack.add(headerMiddleware.bind(null, shim), {
name: 'NewRelicHeader',
step: 'build'
})
clientStack.add(attrMiddleware.bind(null, shim, config), {
name: 'NewRelicDeserialize',
step: 'deserialize'
})
}
}
}

/**
* Wraps the build middleware step to add the disable DT
* header to all outgoing requests
*
* @param {Shim} shim
* @param {function} next next function in middleware chain
* @return {function}
*
*/
function headerMiddleware(shim, next) {
return async function wrappedHeaderMw(args) {
args.request.headers[shim.DISABLE_DT] = true
return await next(args)
}
}

/**
* Wraps the deserialize middleware step to add the
* appropriate segment attributes for the AWS command
*
* @param {Shim} shim
* @param {Object} config AWS command configuration
* @param {function} next next function in middleware chain
* @param {Object} contxt AWS command context
* @return {function}
*/
function attrMiddleware(shim, config, next, context) {
return async function wrappedMiddleware(args) {
let region
try {
region = await config.region()
} catch (err) {
shim.logger.debug(err, 'Failed to get the AWS region')
} finally {
const result = await next(args)
addAwsAttributes({ result, config, region, shim, context })
return result
}
}
}

/**
* Adds the necessary aws.* attributes to either the External or first
* class operation segment
*
* @param {Object} params
* @param {Object} params.result result from middleware
* @param {Object} params.config AWS config
* @param {string} params.region AWS region
* @param {Shim} params.shim
* @param {Object} params.context smithy client context
*/
function addAwsAttributes({ result, config, region, shim, context }) {
try {
const { response } = result
const segment = shim.getSegment(response.body.req)
segment.addAttribute('aws.operation', context.commandName || UNKNOWN)
segment.addAttribute('aws.requestId', response.headers['x-amzn-requestid'] || UNKNOWN)
segment.addAttribute('aws.service', config.serviceId || UNKNOWN)
segment.addAttribute('aws.region', region || UNKNOWN)
} catch (err) {
shim.logger.debug(err, 'Failed to add AWS attributes to segment')
}
}
5 changes: 5 additions & 0 deletions merged/aws-sdk/nr-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,10 @@ module.exports = [
type: 'message',
moduleName: '@aws-sdk/client-sns',
onRequire: require('./lib/v3-sns')
},
{
type: 'generic',
moduleName: '@aws-sdk/smithy-client',
onResolved: require('./lib/smithy-client')
}
]
14 changes: 7 additions & 7 deletions merged/aws-sdk/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion merged/aws-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"eslint-plugin-prettier": "^3.4.0",
"husky": "^7.0.2",
"lint-staged": "^11.1.2",
"newrelic": "^8.1.0",
"newrelic": "^8.6.0",
"prettier": "^2.3.2",
"sinon": "^7.2.3",
"tap": "^15.0.9"
Expand Down
4 changes: 2 additions & 2 deletions merged/aws-sdk/tests/versioned/aws-sdk-v2/aws-sdk.tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ tap.test('aws-sdk', (t) => {
AWS = null
})

t.test('should mark requests to be dt-disabled', { skip: true }, (t) => {
t.test('should mark requests to be dt-disabled', (t) => {
// http because we've changed endpoint to be http
const http = require('http')
sinon.spy(http, 'request')
t.tearDown(() => {
t.teardown(() => {
// `afterEach` runs before `tearDown`, so the sinon spy may have already
// been removed.
if (http.request.restore) {
Expand Down
2 changes: 1 addition & 1 deletion merged/aws-sdk/tests/versioned/aws-sdk-v2/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "aws-sdk-tests",
"name": "aws-sdk-v2-tests",
"version": "0.0.0",
"private": true,
"tests": [
Expand Down
69 changes: 69 additions & 0 deletions merged/aws-sdk/tests/versioned/aws-sdk-v3/api-gateway.tap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2021 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

const tap = require('tap')
const utils = require('@newrelic/test-utilities')

const common = require('../common')
const { createEmptyResponseServer, FAKE_CREDENTIALS } = require('../aws-server-stubs')

tap.test('APIGatewayClient', (t) => {
t.autoend()
let helper = null
let server = null
let service = null
let CreateApiKeyCommand = null

t.beforeEach(async () => {
server = createEmptyResponseServer()
await new Promise((resolve) => {
server.listen(0, resolve)
})
helper = utils.TestAgent.makeInstrumented()
common.registerCoreInstrumentation(helper)
const { APIGatewayClient, ...lib } = require('@aws-sdk/client-api-gateway')
CreateApiKeyCommand = lib.CreateApiKeyCommand
const endpoint = `http://localhost:${server.address().port}`
service = new APIGatewayClient({
credentials: FAKE_CREDENTIALS,
endpoint,
region: 'us-east-1'
})
})

t.afterEach(() => {
server.destroy()
helper && helper.unload()
})

t.test('CreateApiKeyCommand', (t) => {
helper.runInTransaction(async (tx) => {
const cmd = new CreateApiKeyCommand({
customerId: 'STRING_VALUE',
description: 'STRING_VALUE',
enabled: true || false,
generateDistinctId: true || false,
name: 'STRING_VALUE',
stageKeys: [
{
restApiId: 'STRING_VALUE',
stageName: 'STRING_VALUE'
}
],
value: 'STRING_VALUE'
})
await service.send(cmd)
tx.end()
setImmediate(common.checkExternals, {
t,
service: 'API Gateway',
operations: ['CreateApiKeyCommand'],
tx
})
})
})
})
65 changes: 65 additions & 0 deletions merged/aws-sdk/tests/versioned/aws-sdk-v3/elasticache.tap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2021 New Relic Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*/

'use strict'

const tap = require('tap')
const utils = require('@newrelic/test-utilities')

const common = require('../common')
const { createResponseServer, FAKE_CREDENTIALS } = require('../aws-server-stubs')

tap.test('ElastiCacheClient', (t) => {
t.autoend()
let helper = null
let server = null
let service = null
let AddTagsToResourceCommand = null

t.beforeEach(async () => {
server = createResponseServer()
await new Promise((resolve) => {
server.listen(0, resolve)
})
helper = utils.TestAgent.makeInstrumented()
common.registerCoreInstrumentation(helper)
const { ElastiCacheClient, ...lib } = require('@aws-sdk/client-elasticache')
AddTagsToResourceCommand = lib.AddTagsToResourceCommand
const endpoint = `http://localhost:${server.address().port}`
service = new ElastiCacheClient({
credentials: FAKE_CREDENTIALS,
endpoint,
region: 'us-east-1'
})
})

t.afterEach(() => {
server.close()
helper && helper.unload()
})

t.test('AddTagsToResourceCommand', (t) => {
helper.runInTransaction(async (tx) => {
const cmd = new AddTagsToResourceCommand({
ResourceName: 'STRING_VALUE' /* required */,
Tags: [
/* required */
{
Key: 'STRING_VALUE',
Value: 'STRING_VALUE'
}
]
})
await service.send(cmd)
tx.end()
setImmediate(common.checkExternals, {
t,
service: 'ElastiCache',
operations: ['AddTagsToResourceCommand'],
tx
})
})
})
})
Loading

0 comments on commit 1cfb912

Please sign in to comment.