Skip to content

Commit

Permalink
Allow lambda passthrough trace header
Browse files Browse the repository at this point in the history
  • Loading branch information
majanjua-amzn committed Jun 7, 2024
1 parent 1502470 commit dd12415
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 3 deletions.
4 changes: 3 additions & 1 deletion packages/core/lib/patchers/aws3_p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ const getXRayMiddleware = (config: RegionResolvedConfig, manualSegment?: Segment
}
}

args.request.headers['X-Amzn-Trace-Id'] = traceHeader;
if (!segment.noOp) {
args.request.headers['X-Amzn-Trace-Id'] = traceHeader;
}

let res;
try {
Expand Down
3 changes: 3 additions & 0 deletions packages/core/lib/patchers/aws_p.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ function captureAWSRequest(req) {
const data = parent.segment ? parent.segment.additionalTraceData : parent.additionalTraceData;

var buildListener = function(req) {
if (parent.noOp) {
return;
}
let traceHeader = 'Root=' + traceId + ';Parent=' + subsegment.id +
';Sampled=' + (subsegment.notTraced ? '0' : '1');
if (data != null) {
Expand Down
6 changes: 4 additions & 2 deletions packages/core/lib/patchers/http_p.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,10 @@ function enableCapture(module, downstreamXRayEnabled, subsegmentCallback) {
options.headers = {};
}

options.headers['X-Amzn-Trace-Id'] = 'Root=' + root.trace_id + ';Parent=' + subsegment.id +
';Sampled=' + (subsegment.notTraced ? '0' : '1');
if (!parent.noOp) {
options.headers['X-Amzn-Trace-Id'] = 'Root=' + root.trace_id + ';Parent=' + subsegment.id +
';Sampled=' + (subsegment.notTraced ? '0' : '1');
}

const errorCapturer = function errorCapturer(e) {
if (subsegmentCallback) {
Expand Down
1 change: 1 addition & 0 deletions packages/core/lib/segments/attributes/subsegment.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Subsegment.prototype.addSubsegment = function(subsegment) {
subsegment.parent = this;

subsegment.notTraced = subsegment.parent.notTraced;
subsegment.noOp = subsegment.parent.noOp;

if (subsegment.end_time === undefined) {
this.incrementCounter(subsegment.counter);
Expand Down
1 change: 1 addition & 0 deletions packages/core/lib/segments/segment.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ Segment.prototype.addSubsegment = function addSubsegment(subsegment) {
subsegment.parent = this;

subsegment.notTraced = subsegment.parent.notTraced;
subsegment.noOp = subsegment.parent.noOp;
this.subsegments.push(subsegment);

if (!subsegment.end_time) {
Expand Down
4 changes: 4 additions & 0 deletions packages/core/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ var utils = {
if (!traceData) {
traceData = {};
logger.getLogger().error('_X_AMZN_TRACE_ID is empty or has an invalid format');
} else if (traceData.root && !traceData.parent && !traceData.sampled) {
// Lambda PassThrough only has root, treat as valid in this case and mark the segment
segment.noOp = true;
valid = true;
} else if (!traceData.root || !traceData.parent || !traceData.sampled) {
logger.getLogger().error('_X_AMZN_TRACE_ID is missing required information');
} else {
Expand Down
88 changes: 88 additions & 0 deletions packages/core/test/unit/patchers/aws_p.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,92 @@ describe('AWS patcher', function() {
});

});


describe('#captureAWSRequest-PassThrough-Header', function() {
var awsClient, awsRequest, MyEmitter, sandbox, segment, stubResolve, addNewSubsegmentStub, sub, addNewServiceSubsegmentStub, service;

before(function() {
MyEmitter = function() {
EventEmitter.call(this);
};

awsClient = {
customizeRequests: function customizeRequests(captureAWSRequest) {
this.call = captureAWSRequest;
},
throttledError: function throttledError() {}
};
awsClient = awsPatcher.captureAWSClient(awsClient);

util.inherits(MyEmitter, EventEmitter);
});

beforeEach(function() {
sandbox = sinon.createSandbox();

awsRequest = {
httpRequest: {
method: 'GET',
url: '/',
connection: {
remoteAddress: 'localhost'
},
headers: {}
},
response: {}
};

awsRequest.on = function(event, fcn) {
if (event === 'complete') {
this.emitter.on(event, fcn.bind(this, this.response));
} else {
this.emitter.on(event, fcn.bind(this, this));
}
return this;
};

awsRequest.emitter = new MyEmitter();

segment = new Segment('testSegment', traceId);
segment.noOp = true; // enforce passthrough behaviour
segment.additionalTraceData = {'Foo': 'bar'};
sub = segment.addNewSubsegmentWithoutSampling('subseg');
service = sub.addNewSubsegmentWithoutSampling('service');

stubResolve = sandbox.stub(contextUtils, 'resolveSegment').returns(sub);
addNewSubsegmentStub = sandbox.stub(segment, 'addNewSubsegmentWithoutSampling').returns(sub);
addNewServiceSubsegmentStub = sandbox.stub(sub, 'addNewSubsegmentWithoutSampling').returns(service);
});

afterEach(function() {
sandbox.restore();
});

it('should log an info statement and exit if parent is not found on the context or on the call params', function(done) {
stubResolve.returns();
var logStub = sandbox.stub(logger, 'info');

awsClient.call(awsRequest);

setTimeout(function() {
logStub.should.have.been.calledOnce;
done();
}, 50);
});

it('should not inject the tracing headers if passthrough mode', function(done) {
sandbox.stub(contextUtils, 'isAutomaticMode').returns(true);

awsClient.call(awsRequest);

awsRequest.emitter.emit('build');

setTimeout(function() {
assert.equal(awsRequest.httpRequest.headers['X-Amzn-Trace-Id'], undefined);
done();
}, 50);
});

});
});

0 comments on commit dd12415

Please sign in to comment.