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.1 to 3.0.0-alpha.2

test/unit/segments/attributes/remote_request_data.test.js

16

CHANGELOG.md
# Changelog for AWS X-Ray Core SDK for JavaScript
<!--LATEST=3.0.0-alpha.1-->
<!--LATEST=3.0.0-alpha.2-->
<!--ENTRYINSERT-->
## 3.0.0-alpha.2
* **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)
* improvement: Support Node 10 syntax for `http.request` [PR #247](https://github.com/aws/aws-xray-sdk-node/pull/247)
* bugfix: Disable centralized sampling in Lambda [#ISSUE217](https://github.com/aws/aws-xray-sdk-node/issues/217)
* bugfix: Allow lerna to bump version number of top-level package.json [PR #254](https://github.com/aws/aws-xray-sdk-node/pull/254)
* bugfix: Add missing subsegment fields [PR #249](https://github.com/aws/aws-xray-sdk-node/pull/249)
* bugfix: Remove query string from URL field [#ISSUE246](https://github.com/aws/aws-xray-sdk-node/issues/246)
* bugfix: `unref` sockets in `segment_emitter.js` [#ISSUE241](https://github.com/aws/aws-xray-sdk-node/issues/241)
* bugfix: Swap out `continuation-local-storage` types for `cls-hooked` types [PR #242](https://github.com/aws/aws-xray-sdk-node/pull/242)
* bugfix: Stopped throwing context missing errors for Centralized sampling with `captureHTTPsGlobal` [#ISSUE161](https://github.com/aws/aws-xray-sdk-node/issues/161)
* bugfix: Fixed `.setDaemonAddress` API not propagating address to `service_connector` [#ISSUE233](https://github.com/aws/aws-xray-sdk-node/issues/233)
* bugfix: Removed TS race condition involving AWS SDK type definition [#ISSUE253](https://github.com/aws/aws-xray-sdk-node/issues/253)
## 3.0.0-alpha.1

@@ -5,0 +19,0 @@ * **BREAKING** change: Merged `2.x` branch into `master`, breaking node v4 [PR #226](https://github.com/aws/aws-xray-sdk-node/pull/226)

2

lib/context_utils.d.ts

@@ -1,2 +0,2 @@

import { Namespace } from 'continuation-local-storage';
import { Namespace } from 'cls-hooked';
import Segment = require('./segments/segment');

@@ -3,0 +3,0 @@ import Subsegment = require('./segments/attributes/subsegment');

var contextUtils = require('../context_utils');
var mwUtils = require('../middleware/mw_utils');
var LambdaUtils = require('../utils').LambdaUtils;

@@ -28,2 +29,11 @@ var Segment = require('../segments/segment');

/**
* Disabling all centralized sampling in Lambda environments. The sampling decisions would be
* uselessly applied to the facade segment, and the sampling pollers were causing errors.
*
* See: https://github.com/aws/aws-xray-sdk-node/issues/217
*/
logger.getLogger().info('Disabling centralized sampling in Lambda environment.');
mwUtils.disableCentralizedSampling();
var namespace = contextUtils.getNamespace();

@@ -30,0 +40,0 @@ namespace.enter(namespace.createContext());

@@ -40,11 +40,11 @@ var validLogLevels = [ 'debug', 'info', 'warn', 'error', 'silent' ];

var tzo = -date.getTimezoneOffset(), // Negate to make this tzo = local - UTC
dif = tzo >= 0 ? '+' : '-',
pad = function(num) {
var norm = Math.floor(Math.abs(num));
return (norm < 10 ? '0' : '') + norm;
};
dif = tzo >= 0 ? '+' : '-',
pad = function(num) {
var norm = Math.floor(Math.abs(num));
return (norm < 10 ? '0' : '') + norm;
};
return new Date(date.getTime() + (tzo * 60 * 1000)).toISOString()
.replace(/T/, ' ')
.replace(/Z/, ' ') +
.replace(/T/, ' ')
.replace(/Z/, ' ') +
dif + pad(tzo / 60) +

@@ -51,0 +51,0 @@ ':' + pad(tzo % 60);

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

} catch (e) {
logger.getLogger().debug('Encountered unexpected exception when fetching sampling rules: ' + e);
logger.getLogger().warn('Encountered unexpected exception when fetching sampling rules: ' + e);
}

@@ -51,4 +51,6 @@ };

// successfully fetched.
ServiceConnector.fetchSamplingRules(function(newRules) {
if(newRules.length !== 0) {
ServiceConnector.fetchSamplingRules(function(err, newRules) {
if (err) {
logger.getLogger().warn('Failed to call GetSamplingRules API: ' + err);
} else if(newRules.length !== 0) {
ruleCache.loadRules(newRules);

@@ -55,0 +57,0 @@ ruleCache.timestamp(now);

var crypto = require('crypto');
var AWS = require('aws-sdk/global');
var Xray = require('aws-sdk/clients/xray');
var logger = require('../../logger');

@@ -8,2 +6,3 @@ var SamplingRule = require('./sampling_rule');

const util = require('util');
const http = require('http');

@@ -21,29 +20,65 @@

clientId: crypto.randomBytes(12).toString('hex'),
client: new Xray({endpoint: util.format('http://%s:%d', DaemonConfig.tcp_ip, DaemonConfig.tcp_port)}),
samplingRulesPath: '/GetSamplingRules',
samplingTargetsPath: '/SamplingTargets',
httpClient: http,
fetchSamplingRules: function fetchSamplingRules(callback) {
const body = '{}'; // Payload needed for GetSamplingRules POST request
const req = this.httpClient.request(getOptions(this.samplingRulesPath, body.length), res => {
var data = '';
res.on('data', d => {
data += d;
});
res.on('error', error => {
callback(error);
});
res.on('end', () => {
var dataObj;
try {
dataObj = JSON.parse(data);
} catch (err) {
callback(error);
}
this.client.makeUnauthenticatedRequest('getSamplingRules', null, function(err, data) {
if(err)
logger.getLogger().warn(err.stack);
else {
var newRules = assembleRules(data);
callback(newRules);
}
var newRules = assembleRules(dataObj);
callback(null, newRules);
});
});
req.write(body);
req.end();
},
fetchTargets: function fetchTargets(rules, callback) {
var params = constructStatisticsDocs(rules);
const body = JSON.stringify(constructStatisticsDocs(rules));
const req = this.httpClient.request(getOptions(this.samplingTargetsPath, body.length), res => {
var data = '';
res.on('data', d => {
data += d;
});
res.on('error', error => {
callback(error)
});
res.on('end', () => {
var dataObj;
try {
dataObj = JSON.parse(data);
} catch (err) {
callback(err);
}
this.client.makeUnauthenticatedRequest('getSamplingTargets', params, function(err, data) {
if(err) {
logger.getLogger().warn(err.stack);
}
else{
var targetsMapping = assembleTargets(data);
var ruleFreshness = dateToEpoch(data['LastRuleModification']);
callback(targetsMapping, ruleFreshness);
}
var targetsMapping = assembleTargets(dataObj);
var ruleFreshness = dateToEpoch(dataObj['LastRuleModification']);
callback(null, targetsMapping, ruleFreshness);
});
});
req.write(body);
req.end();
}

@@ -128,6 +163,18 @@ };

ServiceConnector.client.setupRequestListeners = function setupRequestListeners(request) {
request.removeListener('validate', AWS.EventListeners.Core.VALIDATE_REGION);
var getOptions = function getOptions(path, contentLength) {
const options = {
hostname: DaemonConfig.tcp_ip,
port: DaemonConfig.tcp_port,
method: 'POST',
path: path,
headers: {
'Content-Type': 'application/json',
'Content-Length': contentLength,
'Host': util.format('%s:%d', DaemonConfig.tcp_ip, DaemonConfig.tcp_port)
}
};
return options;
};
module.exports = ServiceConnector;

@@ -27,3 +27,3 @@ var rulePoller = require('./rule_poller');

} catch (e) {
logger.getLogger().debug('Encountered unexpected exception when fetching sampling targets: ' + e);
logger.getLogger().warn('Encountered unexpected exception when fetching sampling targets: ' + e);
}

@@ -38,3 +38,8 @@ };

logger.getLogger().debug('Reporting rule statistics to get new quota.');
serviceConnector.fetchTargets(candidates, function(targetsMapping, ruleFreshness) {
serviceConnector.fetchTargets(candidates, function(err, targetsMapping, ruleFreshness) {
if (err) {
logger.getLogger().debug('Failed to call GetSamplingTargets API: ' + err);
return;
}
ruleCache.loadTargets(targetsMapping);

@@ -41,0 +46,0 @@ if(ruleFreshness > ruleCache.getLastUpdated()) {

@@ -1,38 +0,13 @@

import * as AWS from 'aws-sdk';
import Segment = require('../segments/segment');
import Subsegment = require('../segments/attributes/subsegment');
/* 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.
*
* See: https://github.com/aws/aws-xray-sdk-node/issues/113
*/
export type Callback<D> = (err: AWS.AWSError | undefined, data: D) => void;
export type PatchedAWS = any;
export type PatchedAWSClient = any;
export interface AWSRequestMethod<P, D> {
(params: P, callback?: Callback<D>): AWS.Request<D, AWS.AWSError>;
(callback?: Callback<D>): AWS.Request<D, AWS.AWSError>;
}
export function captureAWS(awssdk: any): PatchedAWS;
export type PatchedAWSRequestMethod<P, D> = AWSRequestMethod<P & { XRaySegment?: Segment | Subsegment }, D>;
export type PatchedAWSClient<T extends AWS.Service> = {
[K in keyof T]: T[K] extends AWSRequestMethod<infer P, infer D>
? PatchedAWSRequestMethod<P, D>
: T[K]
};
export interface AWSClientConstructor<P, T extends typeof AWS.Service> {
new(params?: P): InstanceType<T>;
}
export interface PatchedAWSClientConstructor<P, T extends typeof AWS.Service> {
new(params?: P): PatchedAWSClient<InstanceType<T>>;
}
export type PatchedAWS<T = typeof AWS> = {
[K in keyof T]: T[K] extends typeof AWS.Service
? (T[K] extends AWSClientConstructor<infer P, T[K]>
? PatchedAWSClientConstructor<P, T[K]>
: T[K])
: T[K];
};
export function captureAWS(awssdk: typeof AWS): PatchedAWS;
export function captureAWSClient<T extends AWS.Service>(service: T): PatchedAWSClient<T>;
export function captureAWSClient(service: any): PatchedAWSClient;

@@ -13,3 +13,2 @@ /**

var logger = require('../logger');
var ServiceConnector = require('../middleware/sampling/service_connector');

@@ -28,3 +27,3 @@ var minVersion = '2.7.15';

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

@@ -53,3 +52,3 @@ */

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

@@ -64,7 +63,2 @@ */

function captureAWSRequest(req) {
// short-circuit if the client is the sampling poller
if (req.service === ServiceConnector.client) {
return req;
}
var parent = contextUtils.resolveSegment(contextUtils.resolveManualSegmentParams(req.params));

@@ -71,0 +65,0 @@

@@ -12,2 +12,4 @@ /**

var contextUtils = require('../context_utils');
var DaemonConfig = require('../daemon_config');
var ServiceConnector = require('../middleware/sampling/service_connector');
var Utils = require('../utils');

@@ -58,7 +60,32 @@

function enableCapture(module, downstreamXRayEnabled) {
function captureOutgoingHTTPs(baseFunc, options, callback) {
if (!options || (options.headers && (options.headers['X-Amzn-Trace-Id']))) {
return baseFunc(options, callback);
function captureOutgoingHTTPs(baseFunc, ...args) {
let options;
let callback;
let hasUrl;
let urlObj;
let arg0 = args[0];
if (typeof args[1] === 'object') {
hasUrl = true;
urlObj = typeof arg0 === 'string' ? url.parse(arg0) : arg0;
options = args[1],
callback = args[2];
} else {
hasUrl = false;
options = arg0;
callback = args[1];
}
// Short circuit if the HTTP request has no options, is already being captured,
// or represents a centralized sampling request to the daemon
if (!options ||
(options.headers && (options.headers['X-Amzn-Trace-Id'])) ||
(options.hostname == DaemonConfig.tcp_ip &&
options.port == DaemonConfig.tcp_port &&
(options.path == ServiceConnector.samplingRulesPath ||
options.path == ServiceConnector.samplingTargetsPath)))
{
return baseFunc(...args);
}
if (typeof options === 'string') {

@@ -68,4 +95,8 @@ options = url.parse(options);

if (!hasUrl) {
urlObj = options;
}
var parent = contextUtils.resolveSegment(contextUtils.resolveManualSegmentParams(options));
var hostname = options.hostname || options.host || 'Unknown host';
var hostname = options.hostname || options.host || urlObj.hostname || urlObj.host || 'Unknown host';

@@ -75,3 +106,3 @@ if (!parent) {

output = options.method ? (output + ', method: ' + options.method) : output;
output += ', path: ' + options.path + ' ]';
output += ', path: ' + Utils.stripQueryStringFromPath(options.path || urlObj.path) + ' ]';

@@ -86,3 +117,4 @@ if (!contextUtils.isAutomaticMode()) {

return baseFunc(options, callback);
// Options are not modified, only parsed for logging. We can pass in the original arguments.
return baseFunc(...args);
}

@@ -121,3 +153,3 @@

var req = baseFunc(optionsCopy, function(res) {
var req = baseFunc(...(hasUrl ? [arg0, optionsCopy] : [options]), function(res) {
res.on('end', function() {

@@ -158,9 +190,9 @@ if (res.statusCode === 429)

module.__request = module.request;
module.request = function captureHTTPsRequest(options, callback) {
return captureOutgoingHTTPs(module.__request, options, callback);
module.request = function captureHTTPsRequest(...args) {
return captureOutgoingHTTPs(module.__request, ...args);
};
module.__get = module.get;
module.get = function captureHTTPsGet(options, callback) {
return captureOutgoingHTTPs(module.__get, options, callback);
module.get = function captureHTTPsGet(...args) {
return captureOutgoingHTTPs(module.__get, ...args);
};

@@ -167,0 +199,0 @@ }

@@ -125,3 +125,3 @@ var dgram = require('dgram');

} else {
this.socket = dgram.createSocket('udp4');
this.socket = dgram.createSocket('udp4').unref();
}

@@ -192,5 +192,2 @@ }

if (SegmentEmitter.socket && (typeof SegmentEmitter.socket.unref === 'function'))
SegmentEmitter.socket.unref();
module.exports = SegmentEmitter;

@@ -1,5 +0,3 @@

import * as AWS from 'aws-sdk';
declare class Aws {
constructor(res: AWS.Response<any, any>, serviceName: string);
constructor(res: any, serviceName: string);

@@ -6,0 +4,0 @@ addData(data: any): void;

@@ -10,3 +10,3 @@ var CallCapturer = require('../../patchers/call_capturer.js');

* @constructor
* @param {AWS.Response} res - The response object from the AWS call.
* @param {any} res - The response object from the AWS call. Typed as any to avoid AWS SDK dependency. Otherwise would be AWS.Response.
* @param {string} serviceName - The service name of the AWS client.

@@ -13,0 +13,0 @@ * @see https://github.com/aws/aws-sdk-js/blob/master/lib/response.js

@@ -0,1 +1,3 @@

var { stripQueryStringFromPath } = require('../../utils');
/**

@@ -15,3 +17,3 @@ * Represents an outgoing HTTP/HTTPS call.

this.request = {
url: (req.agent.protocol + '//' + req.getHeader('host') + req.path) || '',
url: (req.agent.protocol + '//' + req.getHeader('host') + stripQueryStringFromPath(req.path)) || '',
method: req.method || '',

@@ -18,0 +20,0 @@ };

@@ -8,2 +8,3 @@ import * as http from 'http';

in_progress?: boolean;
subsegments?: Array<Subsegment>;

@@ -10,0 +11,0 @@ constructor(name: string);

@@ -12,2 +12,3 @@ import Subsegment = require('./attributes/subsegment');

origin?: string;
subsegments?: Array<Subsegment>;

@@ -14,0 +15,0 @@ constructor(name: string, rootId?: string | null, parentId?: string | null);

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

this.user = user;
}
};

@@ -98,0 +98,0 @@ /**

@@ -5,2 +5,4 @@ import Segment = require('./segments/segment');

export function stripQueryStringFromPath(path: string): string;
export function wildcardMatch(pattern: string, text: string): boolean;

@@ -7,0 +9,0 @@

@@ -25,2 +25,19 @@ /**

/**
* Removes the query string parameters from a given http request path
* as it may contain sensitive information
*
* Related issue: https://github.com/aws/aws-xray-sdk-node/issues/246
*
* Node documentation: https://nodejs.org/api/http.html#http_http_request_url_options_callback
*
* @param {string} path - options.path in a http.request callback
* @returns [string] - removes query string element from path
* @alias module:utils.stripQueryStringFromPath
*/
stripQueryStringFromPath: function stripQueryStringFromPath(path) {
return path.split('?')[0];
},
/**
* Performs a case-insensitive wildcard match against two strings. This method works with pseduo-regex chars; specifically ? and * are supported.

@@ -27,0 +44,0 @@ * An asterisk (*) represents any combination of characters

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

@@ -18,5 +18,4 @@ "author": "Amazon Web Services",

"dependencies": {
"@types/continuation-local-storage": "*",
"@types/cls-hooked": "*",
"atomic-batcher": "^1.0.2",
"aws-sdk": "^2.304.0",
"cls-hooked": "^4.2.2",

@@ -56,3 +55,3 @@ "pkginfo": "^0.4.0",

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

@@ -307,3 +307,3 @@

### Capture subsegmenets within chained native Promise using automatic mode
### Capture subsegments within chained native Promise using automatic mode

@@ -314,3 +314,3 @@ If you have chained native Promise and you have subsegments generated within those promises, you should consider to run the following code to patch the behavior of CLS on binding X-Ray context to Promise.

This will solve the issue where the subsegments within a Promise chain are attached to wrong segments or nested instead of being siblings. For more details on the discussion please see this [PR](https://github.com/aws/aws-xray-sdk-node/pull/11).
This will solve the issue where the subsegments within a Promise chain are attached to wrong segments or nested instead of being siblings. For more details on the discussion please see this [PR](https://github.com/aws/aws-xray-sdk-node/pull/11). See the "Capture all outgoing Axios requests" section for full sample code.

@@ -519,2 +519,11 @@ ## Example code

### Capture all outgoing Axios requests
This sample code works with any promise-based HTTP client.
const AWSXRay = require('aws-xray-sdk');
AWSXRay.captureHTTPsGlobal(require('http'));
AWSXRay.capturePromise();
const AxiosWithXray = require('axios');
## Manual mode examples

@@ -521,0 +530,0 @@

@@ -1,4 +0,2 @@

import * as AWS from 'aws-sdk';
import { AWSError } from 'aws-sdk';
import { PromiseResult } from 'aws-sdk/lib/request';
import { Namespace } from 'cls-hooked';
import * as http from 'http';

@@ -69,20 +67,2 @@ import * as https from 'https';

const aws = AWSXRay.captureAWS(AWS);
const sqs = new aws.SQS();
const queues = sqs.listQueues({
QueueNamePrefix: 'test',
XRaySegment: segment
});
expectType<AWS.Request<AWS.SQS.ListQueuesResult, AWSError>>(queues);
const s3 = AWSXRay.captureAWSClient(new AWS.S3());
async function main() {
const objects = await s3.listObjectsV2({
Bucket: 'test',
XRaySegment: segment
}).promise();
expectType<PromiseResult<AWS.S3.ListObjectsV2Output, AWSError>>(objects);
}
expectType<typeof http>(AWSXRay.captureHTTPs(http, true));

@@ -152,3 +132,3 @@ expectType<typeof https>(AWSXRay.captureHTTPs(https, true));

expectType<string>(AWSXRay.getNamespace().name);
expectType<Namespace>(AWSXRay.getNamespace());
expectType<AWSXRay.Segment | AWSXRay.Subsegment | undefined>(AWSXRay.resolveSegment(segment));

@@ -155,0 +135,0 @@ expectType<AWSXRay.Segment | AWSXRay.Subsegment | undefined>(AWSXRay.resolveSegment(undefined));

@@ -9,2 +9,3 @@ var assert = require('chai').assert;

var contextUtils = require('../../../lib/context_utils');
var mwUtils = require('../../../lib/middleware/mw_utils');
var Lambda = require('../../../lib/env/aws_lambda');

@@ -48,2 +49,3 @@ var LambdaUtils = require('../../../lib/utils').LambdaUtils;

disableReusableSocketStub = sandbox.stub(SegmentEmitter, 'disableReusableSocket');
disableCentralizedSamplingStub = sandbox.stub(mwUtils, 'disableCentralizedSampling');
validateStub = sandbox.stub(LambdaUtils, 'validTraceData').returns(true);

@@ -63,2 +65,7 @@ populateStub = sandbox.stub(LambdaUtils, 'populateTraceData').returns(true);

it('should disable centralized sampling', function() {
Lambda.init();
disableCentralizedSamplingStub.should.have.been.calledOnce;
});
it('should override the default streaming threshold', function() {

@@ -65,0 +72,0 @@ Lambda.init();

@@ -81,2 +81,4 @@ var assert = require('chai').assert;

var traceId = '1-57fbe041-2c7ad569f5d6ff149137be86';
const DEFAULT_DAEMON_ADDRESS = '127.0.0.1';
const DEFAULT_DAEMON_PORT = 2000;

@@ -116,3 +118,4 @@ beforeEach(function() {

httpClient = { request: function(options, callback) {
httpClient = { request: function(...args) {
const callback = args[typeof args[1] === 'object' ? 2 : 1];
callback(fakeResponse);

@@ -185,2 +188,13 @@ return fakeRequest;

if (process.version.startsWith('v') && process.version >= 'v10') {
it('should inject the tracing headers into the options if a URL is also provided', function() {
capturedHttp.request(`http://${httpOptions.host}${httpOptions.path}`, httpOptions);
// example: 'Root=1-59138384-82ff54d5ba9282f0c680adb3;Parent=53af362e4e4efeb8;Sampled=1'
var xAmznTraceId = new RegExp('^Root=' + traceId + ';Parent=([a-f0-9]{16});Sampled=1$');
var options = requestSpy.firstCall.args[1];
assert.match(options.headers['X-Amzn-Trace-Id'], xAmznTraceId);
});
}
it('should return the request object', function() {

@@ -190,2 +204,26 @@ var request = capturedHttp.request(httpOptions);

});
it('should not add header to get sampling rules calls', function() {
var options = {
hostname: DEFAULT_DAEMON_ADDRESS,
port: DEFAULT_DAEMON_PORT,
path: '/GetSamplingRules'
};
capturedHttp.request(options, (res) => {});
sinon.assert.notCalled(newSubsegmentStub);
});
it('should not create subsegment for sampling targets calls', function() {
var options = {
hostname: DEFAULT_DAEMON_ADDRESS,
port: DEFAULT_DAEMON_PORT,
path: '/SamplingTargets'
};
capturedHttp.request(options, (res) => {});
sinon.assert.notCalled(newSubsegmentStub);
});
});

@@ -192,0 +230,0 @@

@@ -5,3 +5,5 @@ var assert = require('chai').assert;

var DaemonConfig = require('../../../lib/daemon_config');
var ServiceConnector = require('../../../lib/middleware/sampling/service_connector');
var TestEmitter = require('../test_utils').TestEmitter;

@@ -11,12 +13,36 @@ chai.should();

function buildFakeResponse() {
var response = new TestEmitter();
return response;
};
function buildFakeRequest(res, rules) {
var rulesObj = {
'SamplingRuleRecords': rules,
'NextToken': null
};
var request = new TestEmitter();
request.method = 'GET';
request.url = '/';
request.connection = { remoteAddress: 'myhost' };
request.write = () => {};
request.end = () => {
res.emit('data', JSON.stringify(rulesObj));
res.emit('end');
};
return request;
};
function generateMockClient(samplingRules) {
return {
makeUnauthenticatedRequest: function(_, _, callback) {
callback(null, {
'SamplingRuleRecords': samplingRules,
'NextToken': null
});
request: function(options, callback) {
var res = buildFakeResponse();
var req = buildFakeRequest(res, samplingRules);
callback(res);
return req;
}
};
}
};

@@ -94,3 +120,3 @@ describe('ServiceConnector', function() {

it('filters invalid rules', function(done) {
sandbox.stub(ServiceConnector, 'client').value(generateMockClient([
sandbox.stub(ServiceConnector, 'httpClient').value(generateMockClient([
noSamplingRule,

@@ -101,3 +127,3 @@ invalidRule,

ServiceConnector.fetchSamplingRules(function(rules) {
ServiceConnector.fetchSamplingRules(function(_, rules) {
// should contain 2 rules

@@ -134,3 +160,3 @@ assert.include(rules[0], {

it('respects a fixed rate of 0', function(done) {
sandbox.stub(ServiceConnector, 'client').value(generateMockClient([
sandbox.stub(ServiceConnector, 'httpClient').value(generateMockClient([
noSamplingRule,

@@ -140,3 +166,3 @@ defaultSamplingRule

ServiceConnector.fetchSamplingRules(function(rules) {
ServiceConnector.fetchSamplingRules(function(_, rules) {
assert.deepEqual(rules.length, 2);

@@ -159,2 +185,48 @@ assert.include(rules[0], {

});
describe('DaemonConfig', function() {
const DEFAULT_DAEMON_ADDRESS = '127.0.0.1';
const DEFAULT_DAEMON_PORT = 2000;
var requestSpy;
beforeEach(function() {
delete process.env.AWS_XRAY_DAEMON_ADDRESS;
DaemonConfig.setDaemonAddress(`${DEFAULT_DAEMON_ADDRESS}:${DEFAULT_DAEMON_PORT}`);
requestSpy = sandbox.stub(ServiceConnector.httpClient, 'request').returns({
write: () => {},
end: () => {}
});
});
afterEach(function() {
sandbox.restore();
});
it('Should call the daemon at its default address', function() {
ServiceConnector.fetchSamplingRules(function() {});
ServiceConnector.fetchTargets([], function() {});
assert.equal(DEFAULT_DAEMON_ADDRESS, requestSpy.getCall(0).args[0].hostname);
assert.equal(DEFAULT_DAEMON_PORT, requestSpy.getCall(0).args[0].port);
assert.equal(DEFAULT_DAEMON_ADDRESS, requestSpy.getCall(1).args[0].hostname);
assert.equal(DEFAULT_DAEMON_PORT, requestSpy.getCall(1).args[0].port);
});
it('Should call the daemon at new address when updated', function() {
const new_address = '1.1.1.1';
const new_port = '1999';
DaemonConfig.setDaemonAddress(`${new_address}:${new_port}`);
ServiceConnector.fetchSamplingRules(function() {});
ServiceConnector.fetchTargets([], function() {});
assert.equal(new_address, requestSpy.getCall(0).args[0].hostname);
assert.equal(new_port, requestSpy.getCall(0).args[0].port);
assert.equal(new_address, requestSpy.getCall(1).args[0].hostname);
assert.equal(new_port, requestSpy.getCall(1).args[0].port);
});
});
});

@@ -241,3 +241,4 @@ var assert = require('chai').assert;

sandbox.stub(dgram, 'createSocket').returns({
send: emitStub
send: emitStub,
unref: sinon.stub().returnsThis()
});

@@ -244,0 +245,0 @@

@@ -22,2 +22,12 @@ var assert = require('chai').assert;

describe('#stripQueryStringFromPath', function() {
it('should remove query string for simple path', function() {
assert.equal(Utils.stripQueryStringFromPath('/index.html?page=12'), '/index.html');
});
it('should remove query string for complex path', function() {
assert.equal(Utils.stripQueryStringFromPath('/really/long/path/to/content.html?page=12'), '/really/long/path/to/content.html');
});
});
describe('#processTraceData', function() {

@@ -24,0 +34,0 @@ it('should parse X-Amzn-Trace-Id with spaces', function() {

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