-
Notifications
You must be signed in to change notification settings - Fork 156
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Oversampling Mitigation #541
Oversampling Mitigation #541
Conversation
Codecov Report
@@ Coverage Diff @@
## master #541 +/- ##
==========================================
+ Coverage 82.36% 82.73% +0.36%
==========================================
Files 36 37 +1
Lines 1758 1784 +26
==========================================
+ Hits 1448 1476 +28
+ Misses 310 308 -2
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
packages/core/lib/patchers/aws_p.js
Outdated
@@ -81,7 +81,8 @@ function captureAWSRequest(req) { | |||
|
|||
var buildListener = function(req) { | |||
req.httpRequest.headers['X-Amzn-Trace-Id'] = 'Root=' + traceId + ';Parent=' + subsegment.id + | |||
';Sampled=' + (subsegment.segment.notTraced ? '0' : '1'); | |||
';Sampled=' + (subsegment.isSampled ? '1' : '0'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we stick with the variable name notTraced since customers are expecting that on segment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
@@ -286,7 +304,7 @@ Subsegment.prototype.close = function close(err, remote) { | |||
} | |||
|
|||
if (root && root.counter > SegmentUtils.getStreamingThreshold()) { | |||
if (this.streamSubsegments() && this.parent) { | |||
if (this.streamSubsegments() && this.parent) { // this.isSampled ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems this comment needs to be taken out?
] | ||
} | ||
|
||
it('testing sqsmessagehelper', function(){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's also have a test for when it doesn't have the sampled flag present.
@@ -38,10 +39,24 @@ Subsegment.prototype.init = function init(name) { | |||
|
|||
Subsegment.prototype.addNewSubsegment = function addNewSubsegment(name) { | |||
var subsegment = new Subsegment(name); | |||
subsegment.isSampled = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to set this to the parent's value, not a default true.
It is possible the upstream call was not sampled. This will create an orphaned segment since its parent was never sent to the backend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great callout! I believe checking the value of subsegment.segment.notTraced
would be more accurate in this case as to capture the parent segment's sampling decision not the parent subsegment (since it is possible to have subsegments of subsegments).
@@ -262,6 +262,57 @@ describe('Segment', function() { | |||
}); | |||
}); | |||
|
|||
describe('#addSubsegmentWithoutSampling', function (){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice set of tests!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
}) | ||
|
||
it('should not sample subsegment or subsegment of subsegment - mix', function(){ | ||
var segment = new Segment('parent'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Us needing to create the segment here signals that we re not running through the lambda specific code.
When the code thinks it is in lambda it will create a facade segment for us. The facade segment's trace data is filled out by what is in this variable. You can see an example in aws_lambda.test.js
process.env._X_AMZN_TRACE_ID
packages/core/test/unit/env/aws_lambda.test.js
I believe you need to call "init" here with that variable set.
packages/core/lib/env/aws_lambda.js
Let me know if you need more context here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing that out! I've incorporated that change into the updated unit tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this tested in Lambda directly? |
assert.equal(child3.isSampled, false); | ||
}) | ||
}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After we close the segment, is it possible to check if the emitter sent out the segment or not?
And can we examine the trace header of the subsegment that is sent downstream to see what the sample flag is set to?
packages/core/lib/patchers/aws_p.js
Outdated
@@ -81,7 +81,8 @@ function captureAWSRequest(req) { | |||
|
|||
var buildListener = function(req) { | |||
req.httpRequest.headers['X-Amzn-Trace-Id'] = 'Root=' + traceId + ';Parent=' + subsegment.id + | |||
';Sampled=' + (subsegment.segment.notTraced ? '0' : '1'); | |||
';Sampled=' + (subsegment.isSampled ? '1' : '0'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
}; | ||
|
||
Subsegment.prototype.addNewSubsegmentWithoutSampling = function addNewSubsegmentWithoutSampling(name){ | ||
var subsegment = new Subsegment(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use const
constructor() { | ||
} | ||
|
||
isSampled(message) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this static
? Would need to update docs as well
packages/core/lib/context_utils.js
Outdated
@@ -42,11 +42,11 @@ var contextUtils = { | |||
* @alias module:context_utils.resolveManualSegmentParams | |||
*/ | |||
|
|||
resolveManualSegmentParams: function resolveManualSegmentParams(params) { | |||
resolveManualSegmentParams: function resolveManualSegmentParams (params) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed with Carol,
The linter has not been run in a long time which is causing the large code churn.
packages/core/lib/patchers/aws3_p.ts
Outdated
@@ -110,15 +110,21 @@ const getXRayMiddleware = (config: RegionResolvedConfig, manualSegment?: Segment | |||
return next(args); | |||
} | |||
|
|||
const subsegment: Subsegment = segment.addNewSubsegment(service); | |||
let subsegment: Subsegment; | |||
if (segment.notTraced == false || !segment.subsegments[segment.subsegments.length - 1].notTraced) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this also work?
if (!segment.subsegments[segment.subsegments.length - 1].notTraced)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a design decision: check the parent sampling decision here for unsampled segments, or only check the subsegment and rely on the emitter not sending the entire segment if it is unsampled down the line. If the latter was used in the other SDKs, I am happy to incorporate the same design here as well.
packages/core/lib/patchers/aws_p.js
Outdated
|
||
var buildListener = function(req) { | ||
let subsegment; | ||
if (parent.notTraced === false || !parent.subsegments[parent.subsegments.length - 1].notTraced) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Can we just look at the subsegment and not have the segment check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above
awsClient.call(awsRequest); | ||
|
||
setTimeout(function () { | ||
logStub.should.have.been.calledOnce; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is not supposed to sample, then should this have emitted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is unrelated - just checking if a log is produced. There is another test right below checking the trace header being sent out
e99c271
to
95df8a6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM - please wait for @atshaw43 review too
Issue #, if available: N/A
Description of changes: Implemented oversampling mitigation - added methods to create subsegments without sampling (control sampling decisions at the subsegment level) and an SQS message helper class
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.