Repository: aws/aws-xray-sdk-node (js)

Issue:
Failed tracing errors on xray.getSamplingTargets and x-ray.getSamplingRules
I get failed tracing errors on `xray.getSamplingTargets` and `xray.getSamplingRules` calls after enabling tracing for all Amazon clients: 

```const AWS = AWSXRay.captureAWS(require('aws-sdk'))```

The failed traces are polluting the logs, but otherwise, they're not a big issue. I can't, however, figure out how to avoid them:

> "Call xray.getSamplingRules is missing the sub/segment context for automatic mode. Ignoring."
> "Call xray.getSamplingTargets is missing the sub/segment context for automatic mode. Ignoring."

Seems like X-Ray traces its own calls when capturing the entire AWS SDK. I

n my app, I'm actually interested in capturing DynamoDB calls only. I've tried capturing it like this but I don't seem to get any traces.

```
const dynamo = AWSXRay.captureAWSClient(new AWS.DynamoDB({...})
                                            
db = new AWS.DynamoDB.DocumentClient({
      service: dynamo,
      params: ...})
```

Is it maybe because I'm using `AWS.DynamoDB.DocumentClient`?




Pull request description:
bugfix(core): prevents xray calls made for centralized sampling from being traced
*Issue #, if available:*
Fixes #100 

*Description of changes:*
The X-Ray SDK now checks if the AWS SDK client it is instrumenting is the one used internally to poll the x-ray daemon. This prevents traces being generated (and resulting in missing context errors) for x-ray calls made by this SDK.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.


Patch:
diff --git a/packages/core/lib/patchers/aws_p.js b/packages/core/lib/patchers/aws_p.js
index 6278cb6..2902613 100644
--- a/packages/core/lib/patchers/aws_p.js
+++ b/packages/core/lib/patchers/aws_p.js
@@ -10,6 +10,7 @@ var contextUtils = require('../context_utils');
 var Utils = require('../utils');
 
 var logger = require('../logger');
+var ServiceConnector = require('../middleware/sampling/service_connector');
 
 var minVersion = '2.7.15';
 
@@ -57,6 +58,11 @@ var captureAWSClient = function captureAWSClient(service) {
 };
 
 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));
 
   if (!parent) {


Test patch:
diff --git a/packages/core/test/functional/service_connector_patching.test.js b/packages/core/test/functional/service_connector_patching.test.js
new file mode 100644
index 0000000..9201e72
--- /dev/null
+++ b/packages/core/test/functional/service_connector_patching.test.js
@@ -0,0 +1,76 @@
+var expect = require('chai').expect;
+var sinon = require('sinon');
+var XRay = require('aws-sdk/clients/xray');
+var AWS = require('aws-sdk/global');
+var AWSXRay = require('../../lib/index');
+var ServiceConnector = require('../../lib/middleware/sampling/service_connector');
+
+function generateXrayClient() {
+  var client = new XRay({
+    region: 'mock-region',
+    credentials: {
+      accessKeyId: 'akid',
+      secretAccessKey: 'secret',
+      sessionToken: 'session'
+    },
+    endpoint: 'http://localhost:3000'
+  });
+
+  // remove events that require network calls
+  client.makeUnauthenticatedRequest = function(operation, params, cb) {
+    var request = this.makeRequest(operation, params).toUnauthenticated();
+    request.removeAllListeners('send');
+    request.removeListener('validateResponse', AWS.EventListeners.Core.VALIDATE_RESPONSE);
+    request.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);
+    request.removeAllListeners('extractData');
+    request.on('validateResponse', function() {
+      request.emit('success', request);
+    });
+    return request.send(cb);
+  }
+  
+  return client;
+}
+
+describe('X-Ray AWS', function() {
+  var sandbox;
+  var client;
+  before(function() {
+    client = ServiceConnector.client;
+    ServiceConnector.client = generateXrayClient();
+  });
+
+  after(function() {
+    ServiceConnector.client = client;
+  });
+
+  beforeEach(function() {
+    sandbox = sinon.sandbox.create();
+  });
+  
+  afterEach(function() {
+    sandbox.restore();
+    // reset customizations
+    XRay.prototype.customizeRequests(null);
+  });
+
+  describe('client patching', function() {
+    it('should not affect the centralized sampling x-ray client', function(done) {
+      AWSXRay.captureAWSClient(XRay.prototype);
+      ServiceConnector.client.makeUnauthenticatedRequest('getSamplingTargets', {}, function(err, data) {
+        expect(err).to.be.a('null');
+        done();
+      });
+    });
+
+    it('should affect non x-ray sdk clients', function() {
+      AWSXRay.captureAWSClient(XRay.prototype);
+      // expect to get a context missing error if the client is instrumented
+      expect(function() {
+        generateXrayClient().makeUnauthenticatedRequest('getSamplingTargets', {}, function(err, data) {})
+          .to.throw(Error, 'Failed to get the current sub/segment from the context.');
+      });
+      
+    });
+  });
+});
\ No newline at end of file