Aws-xray-sdk-node: Recommended configuration order

Created on 9 Jan 2020  路  14Comments  路  Source: aws/aws-xray-sdk-node

Version:
"aws-xray-sdk-core": "^3.0.0-alpha.1",
"aws-xray-sdk-express": "^3.0.0-alpha.1",

RIght now I am using the package in following order:

const AWSXRay = require('aws-xray-sdk-core');
const xrayExpress = require('aws-xray-sdk-express');
app.use(xrayExpress.openSegment(process.env.ENVIRONMENT));
AWSXRay.captureHTTPsGlobal(require('http'));
AWSXRay.captureHTTPsGlobal(require('https'));
AWSXRay.capturePromise();
AWSXRay.config([AWSXRay.plugins.ElasticBeanstalkPlugin]);
...
app.use(xrayExpress.closeSegment());

I read doc before and figured out usages of these configurations but did not find instruction on usage order.
I would like to know Is the order matter?

question

Most helpful comment

Hi @Mangosteen-Yang,
You can capture these HTTP requests with custom segments that will appear as separate nodes in the X-Ray service map. Please see the developing custom solutions documentation for details. You can safely make the HTTP request inside the ns.run block and will see it as long as you call segment.close() at the end of the block.

All 14 comments

Your current order is perfectly acceptable with the exception of where you call xrayExpress.openSegment. We recommend you begin segments in express immediately before declaring your paths with Express. So I'd recommend adjusting to:

const AWSXRay = require('aws-xray-sdk-core');
const xrayExpress = require('aws-xray-sdk-express');
AWSXRay.captureHTTPsGlobal(require('http'));
AWSXRay.captureHTTPsGlobal(require('https'));
AWSXRay.capturePromise();
AWSXRay.config([AWSXRay.plugins.ElasticBeanstalkPlugin]);
app.use(xrayExpress.openSegment(process.env.ENVIRONMENT));
...
app.use(xrayExpress.closeSegment());

@willarmiros Thanks.

Sometimes I need to call other services outside path. (e.g confirm SQS subscribtion request)
I will get following erros. Is still recommend to ignore these errors in v3?

2020-01-09 23:24:33.902 +00:00 [ERROR] Error: Failed to get the current sub/segment from the context.
    at Object.contextMissingLogError [as contextMissing] (/var/app/current/node_modules/aws-xray-sdk-core/lib/context_utils.js:26:19)
    at Object.getSegment (/var/app/current/node_modules/aws-xray-sdk-core/lib/context_utils.js:92:45)
    at Object.resolveSegment (/var/app/current/node_modules/aws-xray-sdk-core/lib/context_utils.js:73:19)
    at captureOutgoingHTTPs (/var/app/current/node_modules/aws-xray-sdk-core/lib/patchers/http_p.js:66:31)
    at Object.captureHTTPsRequest [as request] (/var/app/current/node_modules/aws-xray-sdk-core/lib/patchers/http_p.js:153:12)
    at features.constructor.handleRequest (/var/app/current/node_modules/aws-sdk/lib/http/node.js:45:23)
    at executeSend (/var/app/current/node_modules/aws-sdk/lib/event_listeners.js:342:29)
    at Request.SEND (/var/app/current/node_modules/aws-sdk/lib/event_listeners.js:356:9)
    at Request.callListeners (/var/app/current/node_modules/aws-sdk/lib/sequential_executor.js:102:18)
    at Request.emit (/var/app/current/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/app/current/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/var/app/current/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/app/current/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/app/current/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/app/current/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/app/current/node_modules/aws-sdk/lib/request.js:685:12)
2020-01-09 23:24:25.833 +00:00 [ERROR] Error: Failed to get the current sub/segment from the context.
    at Object.contextMissingLogError [as contextMissing] (/var/app/current/node_modules/aws-xray-sdk-core/lib/context_utils.js:26:19)
    at Object.getSegment (/var/app/current/node_modules/aws-xray-sdk-core/lib/context_utils.js:92:45)
    at tryGetCurrentSegment (/var/app/current/node_modules/aws-xray-sdk-core/lib/patchers/promise_p.js:31:28)
    at Promise.then (/var/app/current/node_modules/aws-xray-sdk-core/lib/patchers/promise_p.js:16:10)
    at process._tickCallback (internal/process/next_tick.js:68:7)

I capture globally rather than manually because:

  1. I am lazy
  2. prevent forget to add xray for future requets
  3. I am using axois (https://github.com/aws/aws-xray-sdk-node/pull/11#issuecomment-368907780)

Please see below for comment for clarification on this recommendation

If you are making requests using the AWS SDK outside of your path declaration blocks then those will throw context missing errors because segments are only automatically created inside of express path declarations. If you'd like, you could also use the closeSegment middleware, make your AWS calls, then use the openSegment middleware and continue your path declarations to avoid the errors. For example:

const express = require('express');
const AWSXRay = require('aws-xray-sdk');
const XRayExpress = AWSXRay.express;
const app = express();

app.use(XRayExpress.openSegment('expressPaths'));

app.get('/', (req, res) => { 
    res.send('Hello World!');
});

app.use(XRayExpress.closeSegment());

// Make some AWS SDK Calls without context missing errors

app.use(XRayExpress.openSegment('expressPaths'));

app.get('/test/', (req, res) => {
    res.send('This is a test!');
});

app.use(XRayExpress.closeSegment());

Let me know if this works for you.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sorry, I just tried. (v3.0.0)

This not works well for my case because the request can be made at any time. I still get the error if request made outside path declaration blocks.

Hi @Mangosteen-Yang,
These are called context missing errors. You can change the SDK's handling of them by setting the context missing strategy to LOG_ERROR or to a custom function as described in the docs. For example, if you'd like to ignore them since you don't care about those errors, you can do:

AWSXRay.setContextMissingStrategy(() => {});

Yeah. I am using the same way, thanks!

Just curious, any plan to support request from express rather than the user?

We do support instrumentation of requests via express with our express middleware. Is that what you mean?

Maybe not.
For example, we are calling a third-party API every 5 seconds to sync data, which is out of the route.
Because we are using Capture all outgoing HTTP/S requests so every call outside route will get Failed to get the current sub/segment from the context.

I hope these requests showing in x-ray.

Hi @Mangosteen-Yang,
You can capture these HTTP requests with custom segments that will appear as separate nodes in the X-Ray service map. Please see the developing custom solutions documentation for details. You can safely make the HTTP request inside the ns.run block and will see it as long as you call segment.close() at the end of the block.

If you are making requests using the AWS SDK outside of your path declaration blocks then those will throw context missing errors because segments are only automatically created inside of express path declarations. If you'd like, you could also use the closeSegment middleware, make your AWS calls, then use the openSegment middleware and continue your path declarations to avoid the errors. For example:

const express = require('express');
const AWSXRay = require('aws-xray-sdk');
const XRayExpress = AWSXRay.express;
const app = express();

app.use(XRayExpress.openSegment('expressPaths'));

app.get('/', (req, res) => { 
    res.send('Hello World!');
});

app.use(XRayExpress.closeSegment());

// Make some AWS SDK Calls without context missing errors

app.use(XRayExpress.openSegment('expressPaths'));

app.get('/test/', (req, res) => {
    res.send('This is a test!');
});

app.use(XRayExpress.closeSegment());

Let me know if this works for you.

I just tried this one again today and I got:

Error: Failed to get the current sub/segment from the context.
    at Object.contextMissingRuntimeError [as contextMissing] (C:\Users\yangs\Documents\pmg\mii-api\node_modules\aws-xray-sdk-core\lib\context_utils.js:21:15)
    at Object.getSegment (C:\Users\yangs\Documents\pmg\mii-api\node_modules\aws-xray-sdk-core\lib\context_utils.js:92:45)
    at Object.subscribe (C:\Users\yangs\Documents\pmg\mii-api\app\services\sns.handler.js:34:11)
    at Object.<anonymous> (C:\Users\yangs\Documents\pmg\mii-api\app.js:37:41)
    at Module._compile (internal/modules/cjs/loader.js:1176:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1196:10)
    at Module.load (internal/modules/cjs/loader.js:1040:32)
    at Function.Module._load (internal/modules/cjs/loader.js:929:14)
    at Module.require (internal/modules/cjs/loader.js:1080:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (C:\Users\yangs\Documents\pmg\mii-api\server.js:1:13)
    at Module._compile (internal/modules/cjs/loader.js:1176:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1196:10)
    at Module.load (internal/modules/cjs/loader.js:1040:32)
    at Function.Module._load (internal/modules/cjs/loader.js:929:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)

line 34 of sns.handler.js is
const subscribePromise = new AWS.SNS({ apiVersion: '2010-03-31' }).subscribe(params).promise();
at the beginning of the file we have const AWS = AWSXRay.captureAWS(require('aws-sdk'));

And require of this file is outside of open/close segment as suggested.


v3.0.1

Hi @Mangosteen-Yang,
Sorry, it appears I was mistaken with that recommendation. It will in fact still cause context missing errors even with the open/close segment middleware usage. If you'd like to capture those requests, you'll have to use the custom solutions strategy with beginning and ending your own segments I mentioned above.

If you don't want to instrument those requests, then you can capture individual AWS clients rather than capturing all AWS requests, so that the the SNS client you use to make a request outside of your express routes is NOT instrumented, but other clients you use inside your express routes are. Alternatively, you could just set your contextMissingStrategy to do nothing or log an error as I mentioned above.

@willarmiros No problem. Thanks.
Can you provide more detail on why this kind of request cannot (or should not) be captured automatically?

Segments are meant to represent users' requests to a web service, such as one built using express. Therefore we automatically create segments using middleware for all defined routes. Outside of those routes there's no way for our library to know what should be instrumented, and so therefore it is up to the user to define custom segments if they'd like such code paths to be instrumented.

Was this page helpful?
0 / 5 - 0 ratings