UNPKG

deep-framework

Version:
139 lines (112 loc) 4.24 kB
/** * Capture module. * @module aws_p */ var _ = require('underscore'); var semver = require('semver'); var Aws = require('../segments/attributes/aws'); var Downstream = require('../segments/attributes/downstream'); var CLSUtils = require('../utils').CLSUtils; var Utils = require('../utils'); var logger = require('../logger'); var minVersion = '2.7.15'; var throttledErrorOverriden = false; var throttledError = function throttledError() { return false; // If the customer doesn't provide an aws-sdk with a throttled error function, we can't make assumptions. }; /** * Configures the AWS SDK to automatically capture information for the segment. * All created clients will automatically be captured. See 'captureAWSClient' * for additional details. * @param {AWS} awssdk - The Javascript AWS SDK. * @alias module:aws_p.captureAWS * @returns {AWS} * @see https://github.com/aws/aws-sdk-js */ var captureAWS = function captureAWS(awssdk) { if (!semver.gte(awssdk.VERSION, minVersion)) throw new Error ('AWS SDK version ' + minVersion + ' or greater required.'); for (var prop in awssdk) { if (!_.isUndefined(awssdk[prop].serviceIdentifier)) { var Service = awssdk[prop]; Service.prototype.customizeRequests(captureAWSRequest); } } if (!throttledErrorOverriden) { var newThrottledError = new awssdk.Service().throttledError; if (typeof newThrottledError === 'function') { throttledError = newThrottledError; throttledErrorOverriden = true; } } return awssdk; }; /** * Configures any AWS Client instance to automatically capture information for the segment. * For manual mode, a param with key called 'Segment' is required as a part of the AWS * call paramaters, and must reference a Segment or Subsegment object. * @param {AWS.Service} service - An instance of a AWS service to wrap. * @alias module:aws_p.captureAWSClient * @returns {AWS.Service} * @see https://github.com/aws/aws-sdk-js */ var captureAWSClient = function captureAWSClient(service) { service.customizeRequests(captureAWSRequest); if (!throttledErrorOverriden) { var newThrottledError = service.throttledError; if (typeof newThrottledError === 'function') { throttledError = newThrottledError; throttledErrorOverriden = true; } } return service; }; function captureAWSRequest(req) { var parent = CLSUtils.isCLSMode() ? CLSUtils.getSegment() : (req.params ? req.params.Segment : null); if (!parent) { logger.info('Call ' + this.serviceIdentifier + '.' + req.operation + ' requires a segment object for tracing.'); return req; } if (req.params && req.params.Segment) delete req.params.Segment; var stack = (new Error()).stack; var traceId = parent.segment ? parent.segment.trace_id : parent.trace_id; var subsegment = parent.addNewSubsegment(this.serviceIdentifier); req.on('build', function(req) { req.httpRequest.headers['X-Amzn-Trace-Id'] = 'Root=' + traceId + '; Parent=' + subsegment.id + '; Sampled=' + (subsegment.segment.notTraced ? '0' : '1'); }).on('complete', function(res) { var e = res.error; subsegment.addAttribute('namespace', 'aws'); subsegment.addAttribute('aws', new Aws(res, subsegment.name)); subsegment.addAttribute('http', new Downstream(res)); if (!_.isEmpty(e)) { var error = { message: e.message, name: e.code, stack: stack }; if (res.httpResponse && res.httpResponse.statusCode) { if (res.httpResponse.statusCode === 429 || throttledError(e)) subsegment.addThrottle(); subsegment.close(error, Utils.getCauseTypeFromHttpStatus(res.httpResponse.statusCode), true); } else { subsegment.close(error); } } else { subsegment.close(); } }); if (!req.__send) { req.__send = req.send; req.send = function (callback) { if (CLSUtils.isCLSMode()) { var session = CLSUtils.getNamespace(); session.run(function() { CLSUtils.setSegment(subsegment); req.__send(callback); }); } else { req.__send(callback); } }; } } module.exports.captureAWSClient = captureAWSClient; module.exports.captureAWS = captureAWS;