Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

aws-xray-sdk-core

Package Overview
Dependencies
Maintainers
15
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aws-xray-sdk-core - npm Package Compare versions

Comparing version 3.0.0-alpha.2 to 3.0.0

8

CHANGELOG.md
# Changelog for AWS X-Ray Core SDK for JavaScript
<!--LATEST=3.0.0-alpha.2-->
<!--LATEST=3.0.0-->
<!--ENTRYINSERT-->
## 3.0.0
* **BREAKING** change: Releasing all changes in 3.0.0-alpha.1 and 3.0.0-alpha.2 as stable. See below changelog entries. [#ISSUE157](https://github.com/aws/aws-xray-sdk-node/issues/157)
* improvement: Deprecated support for Node 8 [#PR 273](https://github.com/aws/aws-xray-sdk-node/pull/273)
* bugfix: Catch errors on requests to daemon [#ISSUE267](https://github.com/aws/aws-xray-sdk-node/issues/267)
* bugfix: Correct AWS patcher TS defitnitions [#ISSUE276](https://github.com/aws/aws-xray-sdk-node/issues/276)
## 3.0.0-alpha.2

@@ -5,0 +11,0 @@ * **BREAKING** change: Removed dependency on the aws-sdk, including all dependent TS definitions [PR #255](https://github.com/aws/aws-xray-sdk-node/pull/255)

2

lib/middleware/sampling/rule_poller.js

@@ -52,3 +52,3 @@ var logger = require('../../logger');

if (err) {
logger.getLogger().warn('Failed to call GetSamplingRules API: ' + err);
logger.getLogger().warn('Failed to retrieve sampling rules from X-Ray service:', err);
} else if(newRules.length !== 0) {

@@ -55,0 +55,0 @@ ruleCache.loadRules(newRules);

@@ -21,2 +21,3 @@ var crypto = require('crypto');

samplingTargetsPath: '/SamplingTargets',
logger: logger,
httpClient: http,

@@ -26,4 +27,5 @@

const body = '{}'; // Payload needed for GetSamplingRules POST request
const options = getOptions(this.samplingRulesPath, body.length);
const req = this.httpClient.request(getOptions(this.samplingRulesPath, body.length), res => {
const req = this.httpClient.request(options, res => {
var data = '';

@@ -43,3 +45,3 @@ res.on('data', d => {

} catch (err) {
callback(error);
callback(err);
}

@@ -51,2 +53,7 @@

});
req.on('error', (err) => {
this.logger.getLogger().error(`Failed to connect to X-Ray daemon at ${options.hostname}:${options.port} to get sampling rules.`);
callback(err);
});

@@ -59,4 +66,5 @@ req.write(body);

const body = JSON.stringify(constructStatisticsDocs(rules));
const options = getOptions(this.samplingTargetsPath, body.length);
const req = this.httpClient.request(getOptions(this.samplingTargetsPath, body.length), res => {
const req = this.httpClient.request(options, res => {
var data = '';

@@ -84,2 +92,7 @@ res.on('data', d => {

});
req.on('error', (err) => {
this.logger.getLogger().error(`Failed to connect to X-Ray daemon at ${options.hostname}:${options.port} to get sampling targets.`);
callback(err);
});

@@ -86,0 +99,0 @@ req.write(body);

@@ -33,9 +33,6 @@ var rulePoller = require('./rule_poller');

var candidates = getCandidates();
if(!candidates || candidates.length === 0)
logger.getLogger().debug('There is no sampling rule statistics to report.');
else {
logger.getLogger().debug('Reporting rule statistics to get new quota.');
if(candidates && candidates.length > 0) {
serviceConnector.fetchTargets(candidates, function(err, targetsMapping, ruleFreshness) {
if (err) {
logger.getLogger().debug('Failed to call GetSamplingTargets API: ' + err);
logger.getLogger().warn('Failed to retrieve sampling targets from X-Ray service:', err);
return;

@@ -49,2 +46,4 @@ }

}
logger.getLogger().info('Successfully reported rule statistics to get new sampling quota.');
});

@@ -51,0 +50,0 @@ }

@@ -1,13 +0,9 @@

/* The types returned from patching AWS clients is left as any because using types defined
* by the aws-sdk would require us to depend on that package, which would make our bundle size unreasonable.
* Instead, it is recommended to cast patched AWS clients back to their original types.
/* The type accepted and returned from patching AWS clients is generic because using types defined
* by the aws-sdk would require us to depend on it, which would make our bundle size too large.
*
* See: https://github.com/aws/aws-xray-sdk-node/issues/113
* See: https://github.com/aws/aws-xray-sdk-node/pull/255
*/
export type PatchedAWS = any;
export type PatchedAWSClient = any;
export function captureAWS<T>(awssdk: T): T;
export function captureAWS(awssdk: any): PatchedAWS;
export function captureAWSClient(service: any): PatchedAWSClient;
export function captureAWSClient<T>(service: T): T;

@@ -26,3 +26,3 @@ /**

* @alias module:aws_p.captureAWS
* @returns {any} - Typed as any to avoid dependency on AWS SDK. Otherwise would be AWS.
* @returns {AWS}
* @see https://github.com/aws/aws-sdk-js

@@ -51,3 +51,3 @@ */

* @alias module:aws_p.captureAWSClient
* @returns {any} - Typed as any to avoid dependency on AWS SDK. Otherwise would be AWS.Service.
* @returns {AWS.Service}
* @see https://github.com/aws/aws-sdk-js

@@ -54,0 +54,0 @@ */

{
"name": "aws-xray-sdk-core",
"version": "3.0.0-alpha.2",
"version": "3.0.0",
"description": "AWS X-Ray SDK for Javascript",

@@ -12,3 +12,3 @@ "author": "Amazon Web Services",

"engines": {
"node": ">= 4.x"
"node": ">= 10.x"
},

@@ -55,3 +55,3 @@ "directories": {

"repository": "https://github.com/aws/aws-xray-sdk-node/tree/master/packages/core",
"gitHead": "77a4358f9e40e4666b764e2753ec55a929e09297"
"gitHead": "bfbc97d88f8452a288dc6396c9cc0f9cffcf45fd"
}

@@ -8,28 +8,12 @@

The AWS X-Ray SDK (the SDK) automatically records information for incoming and outgoing
requests and responses (via middleware). It also automatically records local data
The AWS X-Ray SDK (the SDK) allows developers to instrument their web applications
to automatically record information for incoming and outgoing
requests and responses. It can also record local data
such as function calls, time, variables (via metadata and annotations), and Amazon
EC2 instance data (via plugins). Currently, only Express
applications are supported for automatic capturing. See the
[aws-xray-sdk-express](https://github.com/aws/aws-xray-sdk-node/tree/master/packages/express) package for additional information.
EC2, ECS, and Elastic Beanstalk metadata (via plugins). Currently, [Express](https://github.com/aws/aws-xray-sdk-node/tree/master/packages/express) and [Restify](https://github.com/aws/aws-xray-sdk-node/tree/master/packages/restify)
applications are supported for automatic capturing via middleware. AWS Lambda functions can also be instrumented.
The SDK exposes the Segment and Subsegment objects so you can create your own capturing
mechanisms, but a few are supplied.
These keep the current subsegment up to date in automatic mode, or propagate the current subsegment in manual mode.
mechanisms, but a few are supplied. See Capturing Function Calls below.
`AWSXRay.captureFunc` - Takes a function that takes a single subsegment argument. This creates a new nested subsegment and exposes it. The segment
closes automatically when the function finishes executing and returns the result if any. This does not correctly
time functions with asynchronous calls. Instead, use
captureAsyncFunc.
`AWSXRay.captureAsyncFunc` - Takes an async function that takes a single subsegment argument and returns the promise by executing the function.
This creates a new nested subsegment and exposes it.
The segment must be closed using subsegment.close() the asynchronous function completes successfully.
`AWSXRay.captureCallbackFunc` - Takes a function to be used as a callback. Useful
for capturing callback information and directly associating it to the call
that generated it. This creates a new nested subsegment and exposes it by appending it onto the arguments used to call the callback. For this reason,
always call your captured callbacks with the full parameter list. The subsegment closes
automatically when the function finishes executing.
## Setup

@@ -48,15 +32,8 @@

Automatic mode is for use with the `aws-xray-sdk-express` module to support Express
applications, but can be used outside of Express applications.
The `aws-xray-sdk-express` module captures incoming request/response information via middleware and creates the base segment object automatically.
If your application isn't using the Express middleware, you have to create a
new segment, and set this on the SDK when in automatic mode.
Automatic mode is designed for use with Express, Restify, and Lambda
applications, but can be used outside of such applications.
For more information about developing your own middleware or using automatic mode without middleware, see the [developing custom solutions
using automatic mode](https://github.com/aws/aws-xray-sdk-node/tree/master/packages/core#developing-custom-solutions-using-automatic-mode) section below.
var segment = new AWSXRay.Segment(name, [optional root ID], [optional parent ID]);
AWSXRay.setSegment(segment);
For more information about developing your own middleware or using automatic mode without middleware, see the `developing custom solutions
using automatic mode` section below.
Automatic mode uses the Continuation Local Storage package and automatically tracks
Automatic mode uses the `cls-hooked` package and automatically tracks
the current segment or subsegment when using the built-in capture functions or any

@@ -74,3 +51,3 @@ of the aws-xray-sdk modules. Using the built-in capture functions or other aws-xray-sdk modules automatically creates

Manual mode requires that you pass around the segment reference. See the examples
below for the different usages.
in the [express package](https://github.com/aws/aws-xray-sdk-node/tree/master/packages/express) for the different usages.

@@ -135,3 +112,3 @@ ### Environment variables

By default, when the X-Ray SDK is operating in automatic mode and attempts to find a segment in the `cls` context but
By default, when the X-Ray SDK is operating in automatic mode and attempts to find a segment in the `cls-hooked` context but
cannot find one, it throws a runtime error. This behavior can be undesirable when unit testing or doing experimentation.

@@ -284,7 +261,44 @@ It can be changed to instead log an error either by using the `AWS_XRAY_CONTEXT_MISSING` environment variable documented above, or programatically by calling

### Capturing Function Calls
```ts
AWSXRay.captureFunc<T>(
name: string,
fcn: (subsegment?: Subsegment) => T,
parent?: Segment | Subsegment
): T
```
`AWSXRay.captureFunc` - Takes a function that takes a single subsegment argument. This creates a new nested subsegment and exposes it. The segment
closes automatically when the function finishes executing and returns the result if any. This does not correctly
time functions with asynchronous calls. Instead, use
`captureAsyncFunc`.
```ts
captureAsyncFunc<T>(
name: string,
fcn: (subsegment?: Subsegment) => T,
parent?: Segment | Subsegment
): T
```
`AWSXRay.captureAsyncFunc` - Takes an async function that takes a single subsegment argument and returns the promise by executing the function.
This creates a new nested subsegment and exposes it.
The segment must be closed using subsegment.close() the asynchronous function completes successfully.
```ts
captureCallbackFunc<S extends any[], T>(
name: string,
fcn: (...args: S) => T,
parent?: Segment | Subsegment
): (...args: S) => T
```
`AWSXRay.captureCallbackFunc` - Takes a function to be used as a callback. Useful
for capturing callback information and directly associating it to the call
that generated it. This creates a new nested subsegment and exposes it by appending it onto the arguments used to call the callback. For this reason,
always call your captured callbacks with the full parameter list. The subsegment closes
automatically when the function finishes executing.
### Developing custom solutions using automatic mode
Automatic mode is for use with the aws-xray-sdk-express module to support Express
applications, however it can be used outside of Express applications.
If your application isn't using the Express middleware, you have to create the
If your application isn't using a supported framework, you have to create the
new segment and set this on the SDK.

@@ -320,30 +334,16 @@ You need to create a new level of CLS, and you can do so by using the CLS namespace object. We expose this via the following.

## Example code
## Usage in AWS Lambda
### Version capturing
To understand X-Ray's integration with Lambda functions, please read the [Lambda Developer Guide](https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html). Lambda functions are unique environments because a segment is automatically provided in function code once `Active Tracing` is enabled for a function. That segment is immutable, however all subsegment operations described below are permitted.
Use the 'npm start' script to enable.
By default in Lambda, the streaming threshold is set to 0 (immediate subsegment streaming), centralized sampling is disabled, automatic mode is enabled, and the daemon address is set by the Lambda runtime.
### Capture all incoming HTTP requests to '/'
For an example function, see [tracing node.js functions](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-tracing.html).
var app = express();
## Example code
//...
### Version capturing
var AWSXRay = require('aws-xray-sdk');
Use the 'npm start' script to enable.
app.use(AWSXRay.express.openSegment('defaultName')); //required at the start of your routes
app.get('/', function (req, res) {
res.render('index');
});
app.use(AWSXRay.express.closeSegment()); //Required at the end of your routes / first in error handling routes
### Capture all outgoing AWS requests
var AWS = captureAWS(require('aws-sdk'));
// Create new AWS clients as usual.
### Configure AWSXRay to automatically capture EC2 instance data

@@ -380,61 +380,27 @@

var newSubseg = subsegment.addNewSubsegment(name);
...
newSubseg.close();
// Or
var subsegment = new Subsegment(name);
var newSubseg = new Subsegment(name);
subsegment.addSubsegment(newSubseg);
...
newSubseg.close();
## Automatic mode examples
Automatic mode is for use with the aws-xray-sdk-express module to support Express
applications, however it can be used outside of Express applications.
If the Express middleware isn't being used, you have to create a root segment and
set on the SDK using the following.
var segment = new AWSXRay.Segment(name, [optional root ID], [optional parent ID]);
AWSXRay.setSegment(segment);
Only then will the segment be available for use in automatic mode and be able to be picked up by the capture functions and other aws-xray-sdk modules.
### Capture all incoming HTTP requests to '/'
var app = express();
//...
var AWSXRay = require('aws-xray-sdk');
app.use(AWSXRay.express.openSegment('defaultName'));
app.get('/', function (req, res) {
res.render('index');
});
app.use(AWSXRay.express.closeSegment());
### Capture through function calls
var AWSXRay = require('aws-xray-sdk');
This creates 5 nested subsegments on the root segment and captures timing data individually for each subsegment. This example assumes an automatic mode environment.
app.use(AWSXRay.express.openSegment('defaultName'));
captureFunc('1', function(subsegment1) {
//Exposing the subsegment in the function is optional, and is listed here as an example
//You can also use:
//var subsegment1 = AWSXRay.getSegment();
//...
//The root segment is created by the Express middleware
//This creates 5 nested subsegments on the root segment
//and captures timing data individually for each subsegment
app.get('/', function (req, res) {
captureFunc('1', function(subsegment1) {
//Exposing the subsegment in the function is optional, and is listed here
as an example
//You can also use
//var subsegment1 = AWSXRay.getSegment();
captureFunc('2', function(subsegment2) {
captureFunc('3', function(subsegment3) {
captureFunc('4', function(subsegment4) {
captureFunc('5', function() {
//exposing the subsegment is optional
res.render('index');
});
captureFunc('2', function(subsegment2) {
captureFunc('3', function(subsegment3) {
captureFunc('4', function(subsegment4) {
captureFunc('5', function() {
//exposing the subsegment is optional
res.render('index');
});

@@ -446,29 +412,16 @@ });

app.use(AWSXRay.express.closeSegment());
### Capture through async function calls
var AWSXRay = require('aws-xray-sdk');
var host = 'samplego-env.us-east-1.elasticbeanstalk.com';
//...
AWSXRay.captureAsyncFunc('send', function(subsegment) {
//'subsegment' here is the newly created and exposed subsegment for the async
//request, and must be closed manually (this ensures timing data is correct)
app.use(AWSXRay.express.openSegment('defaultName'));
app.get('/', function (req, res) {
var host = 'samplego-env.us-east-1.elasticbeanstalk.com';
AWSXRay.captureAsyncFunc('send', function(subsegment) {
//'subsegment' here is the newly created and exposed subsegment for the async
//request, and must be closed manually (this ensures timing data is correct)
sendRequest(host, function() {
console.log("rendering!");
res.render('index');
subsegment.close();
});
sendRequest(host, function() {
console.log("Request sent!");
subsegment.close();
});
});
app.use(AWSXRay.express.closeSegment());
function sendRequest(host, cb) {

@@ -495,2 +448,8 @@ var options = {

### Capture all outgoing AWS requests
var AWS = captureAWS(require('aws-sdk'));
// Create new AWS clients as usual.
### Capture outgoing AWS requests on a single client

@@ -504,13 +463,15 @@

### Capture outgoing AWS requests on every AWS SDK client
### Capture all outgoing HTTP and HTTPS requests
var aws = AWSXRay.captureAWS(require('aws-sdk'));
AWSXRay.captureHTTPsGlobal(require('http'));
AWSXRay.captureHTTPsGlobal(require('https'));
//Create new clients as usual
//Be sure any outgoing calls that are dependent on another async
//function are wrapped with captureAsyncFunc, or duplicate segments might leak
// Requests with this http client, and any other http/https client including
// those used by third party modules, will now be traced
var http = require('http');
### Capture all outgoing HTTP/S requests
### Capture outgoing HTTP/S requests with a traced client
var tracedHttp = AWSXRay.captureHTTPs(require('http')); //returns a copy of the http module that is patched, can patch https as well.
//returns a copy of the http module that is patched, can patch https as well
var tracedHttp = AWSXRay.captureHTTPs(require('http'));

@@ -535,122 +496,1 @@ var options = {

const AxiosWithXray = require('axios');
## Manual mode examples
Enable manual mode:
AWSXRay.enableManualMode();
### Capture through function calls
var AWSXRay = require('aws-xray-sdk');
app.use(AWSXRay.express.openSegment('defaultName'));
//...
//The root segment is created by the Express middleware
//This creates 5 nested subsegments on the root segment
//and captures timing data individually for each subsegment
app.get('/', function (req, res) {
var segment = req.segment;
captureFunc('1', function(subsegment1) {
captureFunc('2', function(subsegment2) {
captureFunc('3', function(subsegment3) {
captureFunc('4', function(subsegment4) {
captureFunc('5', function() {
//subsegment need not be exposed here since we're not doing anything with it
res.render('index');
}, subsegment4);
}, subsegment3);
}, subsegment2);
}, subsegment1);
}, segment);
});
app.use(AWSXRay.express.closeSegment());
### Capture through async function calls
var AWSXRay = require('aws-xray-sdk');
AWSXRay.enableManualMode();
app.use(AWSXRay.express.openSegment('defaultName'));
app.get('/', function (req, res) {
var segment = req.segment;
var host = 'samplego-env.us-east-1.elasticbeanstalk.com';
AWSXRay.captureAsyncFunc('send', function(subsegment) {
sendRequest(host, function() {
console.log("rendering!");
res.render('index');
subsegment.close();
}, subsegment);
}, segment);
});
app.use(AWSXRay.express.closeSegment());
function sendRequest(host, cb, subsegment) {
var options = {
host: host,
path: '/',
XRaySegment: subsegment //required 'XRaySegment' param
};
var callback = function(response) {
var str = '';
//The whole response has been received, so we just print it out here
//Another chunk of data has been received, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
cb();
});
}
http.request(options, callback).end();
};
### Capture outgoing AWS requests on a single client
var s3 = AWSXRay.captureAWSClient(new AWS.S3());
var params = {
Bucket: bucketName,
Key: keyName,
Body: 'Hello!',
XRaySegment: subsegment //required 'XRaySegment' param
};
s3.putObject(params, function(err, data) {
...
});
### Capture all outgoing AWS requests
var AWS = captureAWS(require('aws-sdk'));
//Create new clients as usual
//Be sure any outgoing calls that are dependent on another async
//function are wrapped, or duplicate segments might leak
### Capture all outgoing HTTP/S requests
var tracedHttp = AWSXRay.captureHTTPs(require('http')); //returns a copy of the http module that is patched, can patch https as well.
...
//Include sub/segment reference in options as 'XRaySegment'
var options = {
...
XRaySegment: subsegment //required 'XRaySegment' param
}
tracedHttp.request(options, callback).end();
var assert = require('chai').assert;
var expect = require('chai').expect;
var chai = require('chai');

@@ -36,7 +37,10 @@ var sinon = require('sinon');

function generateMockClient(samplingRules) {
var res = buildFakeResponse();
var req = buildFakeRequest(res, samplingRules);
return buildFakeHttpClient(req, res);
};
function buildFakeHttpClient(req, res) {
return {
request: function(options, callback) {
var res = buildFakeResponse();
var req = buildFakeRequest(res, samplingRules);
callback(res);

@@ -191,3 +195,4 @@ return req;

write: () => {},
end: () => {}
end: () => {},
on: (event, func) => {}
});

@@ -227,2 +232,24 @@ });

});
describe('HttpException', function() {
var logging;
beforeEach(function() {
var path = '../../../lib/logger';
delete require.cache[require.resolve(path)];
logging = require(path);
});
it('should log an error when the HTTP request fails', function() {
let response = buildFakeResponse();
let request = buildFakeRequest(response, []);
sandbox.spy(ServiceConnector.logger, 'getLogger');
sandbox.stub(ServiceConnector, 'httpClient')
.value(buildFakeHttpClient(request, response));
ServiceConnector.fetchSamplingRules(function() {});
request.emit('error', new Error('Fake ECONNREFUSED error'));
expect(ServiceConnector.logger.getLogger).to.be.calledOnce;
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc