Search code examples
javascriptnode.jsamazon-web-servicesaws-sdkaws-xray

AWS X Ray : inside for loop, system is not logging traces for each Trace ID as per the iteration. How to use AWS Async function here?


I am new to javascript and AWS SDK. How to get the expected output using async calls? We have a json object which has Trace IDs and related URL and etc. We need to loop through the list of Trace IDs ('id' in the below JSON) and get trace information for each trace ID using getTraceGraph of the AWS X-Ray service. But when we check the console for logs, system log traces for each trace ID only after the for loop iteration completes, refer the output.

Thank you in advance for the help.

var aws = require('aws-sdk'); 
aws.config.update({region:'us-east-1'});
var xray = new aws.XRay();
var newObj = {
    "TraceSummaries": [
        {
            "id": "1-some-example",
            "HttpURL": "https://exampleUrl",
            "Name": "name of the service"
        },
        {
            "id": "2-some-example",
            "HttpURL": "https://exampleUrl2",
            "Name": "name of the service"
        }       
    ]
};
var traceArray = newObj.TraceSummaries;
var finalIndex = traceArray.length;
for (i=0; i<finalIndex; i++) {
    console.log('before'+i);
    var singletraceParams = {TraceIds: [traceArray[i].id]}; 
    xray.getTraceGraph(singletraceParams, function(err, data) {
        if (err) console.log(err, err.stack); 
        else {
            var jsonData = JSON.stringify(data);
            console.log('Getting jsonData for'+ ' :'+jsonData);
            console.log('-------------------------------------------------------------');
        }
    }); 
    console.log('after'+i); 
}



Actual output:

before0
after0
before1
after1
Getting jsonData for :{"services":["ReferenceId":0,"Name":"sample1"], "NextToken":null}
-------------------------------------------------------------
Getting jsonData for :{"services":["ReferenceId":0,"Name":"sample2"], "NextToken":null}
-------------------------------------------------------------

Expected output:

before0
Getting jsonData for :{"services":["ReferenceId":0,"Name":"sample1"], "NextToken":null}
-------------------------------------------------------------
after0
before1
Getting jsonData for :{"services":["ReferenceId":0,"Name":"sample2"], "NextToken":null}
-------------------------------------------------------------
after1

Solution

  • You will need to use promise to make the execution in sequence. In your async method with promise await you can achieve your expected output

    async yourMethod() {
            var xray = new aws.XRay();
            var newObj = {
                "TraceSummaries": [
                    {
                        "id": "1-some-example",
                        "HttpURL": "https://exampleUrl",
                        "Name": "name of the service"
                    },
                    {
                        "id": "2-some-example",
                        "HttpURL": "https://exampleUrl2",
                        "Name": "name of the service"
                    }
                ]
            };
            var traceArray = newObj.TraceSummaries;
            var finalIndex = traceArray.length;
            for (let i = 0; i < finalIndex; i++) {
                console.log('before' + i);
                var singletraceParams = { TraceIds: [traceArray[i].id] };
                await new Promise((resolve, reject) => {
                    xray.getTraceGraph(singletraceParams, function (err, data) {
                        if (err) {
                            console.log(err, err.stack);
                            reject(err)
                        } 
                        else {
    
                            var jsonData = JSON.stringify(data);
                            console.log('Getting jsonData for' + ' :' + jsonData);
                            console.log('-------------------------------------------------------------');
                            resolve();
                        }
                    });
                })
                .catch(error=>{
                    console.error(error);
                })
                console.log('after' + i);
            }
        }