Error retrieving JSON data in node.js - javascript

I'm trying to make an android app which displays the top command data on my AWS ec2 instance. The following is the node.js file I've written. It sends the top command result using a topparser npm module. And using the checkCpuUsage function, it sends a notification if cpu usage is more than 1%.
var express = require('express');
var app = express();
var fs = require('fs');
var spawn = require('child_process').spawn;
var topparser=require("topparser");
var FCM = require('fcm-node');
var server = app.listen(8080);
var regTokens = [];
var bodyParser = require('body-parser');
app.use(bodyParser.json());
let data_builder = "";
const DEFAUT_TOP_DURATION = 2000;
function getTopData(callback, duration) {
duration = duration || DEFAUT_TOP_DURATION;
var top = spawn('top');
top.stdout.on('data', function(data) {
data_builder+=data.toString();
});
setTimeout(function() {
top.kill();
callback(topparser.parse(data_builder,10))
},duration);
}
function sendServerData(req, res) {
getTopData((data)=>{
res.status("200").send(data);
})
}
function checkCpuUsage() {
getTopData((data)=>{
var idl = data.cpu.idle;
if(idl<99) {
sendNotification(idl);
}
}, 2000)
}
function saveRegToken(req, res) {
console.log("saveRegToken req body", req.body)
regTokens.push(req.body.token);
res.send(200);
}
let server_key =JSON.parse(fs.readFileSync(('./config.json'))); ;
function sendNotification(idle){
var idl = idle;
var fcm = new FCM(server_key);
for(i=0; i<regTokens.length; i++) {
var message = {
to: 'regTokens[i]',
notification: {
title: 'CPU Usage!',
body: 'CPU Usage: ' + idl,
},
};
fcm.send(message, function(err, response){
if (err) {
console.log("Something has gone wrong!");
} else {
console.log("Successfully sent with response: ", response);
}
});
}
}
setInterval(()=>checkCpuUsage(),10000);
app.get('/sys', sendServerData);
app.post('/save_token', saveRegToken)
console.log("server listening on 8080");
I'm getting the following error in the checkCpuUsage() function:
var idl = data.cpu.idle;
^
TypeError: Cannot read property 'cpu' of undefined
at getTopData (/home/ubuntu/server_monitor/server1.1.1.js:38:17)
at Timeout._onTimeout (/home/ubuntu/server_monitor/server1.1.1.js:26:3)
at ontimeout (timers.js:469:11)
at tryOnTimeout (timers.js:304:5)
at Timer.listOnTimeout (timers.js:264:5)
Following is an example JSON result from the topparser module:
{
process:[
{
pid:'1990',
user:'alex',
pr:'20',
ni:'0',
virt:'1560516',
res:'90656',
shr:'21864',
s:'S',
cpu:'6.1',
mem:'12.5',
time:'13:46.58',
command:'cinnamon'
},
{
pid:'5381',
user:'alex',
pr:'20',
ni:'0',
virt:'929508',
res:'119792',
shr:'8132',
s:'S',
cpu:'6.1',
mem:'16.5',
time:'11:14.11',
command:'firefox'
},
{
pid:'0245',
user:'alex',
pr:'20',
ni:'0',
virt:'24948',
res:'1508',
shr:'1056',
s:'R',
cpu:'6.1',
mem:'0.2',
time:'0:00.02',
command:'top'
},
{
pid:'1',
user:'root',
pr:'20',
ni:'0',
virt:'37352',
res:'5688',
shr:'488',
s:'S',
cpu:'0.0',
mem:'0.8',
time:'0:04.93',
command:'init'
},
{
pid:'2',
user:'root',
pr:'20',
ni:'0',
virt:'0',
res:'0',
shr:'0',
s:'S',
cpu:'0.0',
mem:'0.0',
time:'0:00.07',
command:'kthreadd'
},
{
pid:'3',
user:'root',
pr:'20',
ni:'0',
virt:'0',
res:'0',
shr:'0',
s:'S',
cpu:'0.0',
mem:'0.0',
time:'0:54.23',
command:'ksoftirqd/0'
},
{
pid:'4',
user:'root',
pr:'20',
ni:'0',
virt:'0',
res:'0',
shr:'0',
s:'S',
cpu:'0.0',
mem:'0.0',
time:'0:00.00',
command:'kworker/0:0'
}
],
task:{
total:194,
running:1,
sleeping:193,
stopped:0,
zombie:0
},
cpu:{
user:0.9,
system:3.1,
ni:0.1,
'idle':95,
wa:0.3,
hi:0.6,
si:0,
st:0
},
ram:{
total:727308,
used:664028,
free:63280,
buffers:7600
},
swap:{
total:753660,
used:309516,
free:444144,
cachedMem:187424
}
}

The problem is here :
var top = spawn('top');
top.stdout.on('data', function(data) {
data_builder+=data.toString();
});
setTimeout(function() {
top.kill();
callback(topparser.parse(data_builder,10))
},duration);
You are trying to call the callback using a timeout which is bad practice. Instead, You call the callback from inside the stdout.on('data') hence, making sure that function is called and there is data available before calling the callback.
Like so :
top.stdout.on('data', function(data) {
data_builder+=data.toString();
top.kill();
callback(topparser.parse(data_builder,10))
});
Ideally, Using promises would help to make the code more readable and structured.

Error clearly pointing TypeError: Cannot read property 'cpu' of undefined
It means here your data is undefined. Here you are not getting data from your getTopData().
You can check this two lines data_builder+=data.toString(); or topparser.parse(data_builder,10)
Add some console statements, You will get the idea.
SUGGESTIONS :
Be consistent in your code. Somewhere you are writing plain JavaScript syntax and somewhere in ES6
Make a habit to follow any one.

Related

Node/Express service, span generated in logs but can not see my service in Jaeger UI

I am trying to setup Jaeger tracing for my micro service that is written in Node.js using Express.js.
I have added a simple get request handler in my express app and when I hit the endpoint via curl, I can see that a span is generated in logs, but I do not see the name of my service in Jaeger UI.
// server.js
const initTracer = require('./tracing').initTracer;
const {Tags, FORMAT_HTTP_HEADERS} = require('opentracing')
const tracer = initTracer('demo-service')
app.get('/service/model/jaeger', function(req, res) {
var requestEndpoint = req.originalUrl
console.log('[services.server.js] GET received on:', requestEndpoint)
const parentSpanContext = tracer.extract(FORMAT_HTTP_HEADERS, req.headers)
const span = tracer.startSpan('http_get_' + requestEndpoint, {
childOf : parentSpanContext,
tags : {[Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_SERVER}
});
span.log({'event': `http_get_${requestEndpoint}_end`, 'value' : 'some_value_here'});
span.finish()
res.send('Hello Jaeger bro!')
})
// tracing.js
'use strict'
var initJaegerTracer = require('jaeger-client').initTracer
function initTracer(serviceName) {
var config = {
'serviceName': serviceName,
'sampler': {
'type': 'const',
'param': 1
},
'reporter': {
'logSpans': true,
}
}
var options = {
'logger': {
'info': function logInfo(msg) {
console.log('INFO ', msg)
},
'error': function logError(msg) {
console.log('ERROR', msg)
}
}
}
const tracer = initJaegerTracer(config, options)
//hook up nodejs process exit event
process.on('exit', () => {
console.log('flush out remaining span')
tracer.close()
})
//handle ctrl+c
process.on('SIGINT', () => {
process.exit()
})
return tracer
}
exports.initTracer = initTracer
I see in logs:
2018-03-08T01:03:34.519134479Z INFO Reporting span 9b88812951bcd52f:9b88812951bcd52f:0:1
I finally figured this out after trying out different combinations. This is happening because Jaeger agent is not receiving any UDP packets from my application.
You need to tell the tracer where to send UDP packets, which in this case is docker-machine ip
I added:
'agentHost': '192.168.99.100',
'agentPort': 6832
and then I was able to see my services in Jaeger UI.
function initTracer(serviceName, options) {
var config = {
'serviceName': serviceName,
'sampler': {
'type': 'const',
'param': 1
},
'reporter': {
'logSpans': true,
'agentHost': '192.168.99.100',
'agentPort': 6832
}
}
var options = {
'logger': {
'info': function logInfo(msg) {
console.log('INFO ', msg)
},
'error': function logError(msg) {
console.log('ERROR', msg)
}
}
}
const tracer = initJaegerTracer(config, options)
//hook up nodejs process exit event
process.on('exit', () => {
console.log('flush out remaining span')
tracer.close()
})
//handle ctrl+c
process.on('SIGINT', () => {
process.exit()
})
return tracer
}
exports.initTracer = initTracer

nodejs-How use node-opcua access a remote opc server?

I found a better project node-opcua in github, use the simple example of this project can create a opc server and client, and in the local can access, I need to access a remote opc server now, provide a few parameters are: IP network nodes (such as 10.195.156.150), opc service (for example ArchestrA. FSGateway), opc group (such as ArchestrA), opc TagName (for example HXi1_P201_00. Ia), can I access it use node-opcua?
Thank you!
sample_server code:
var opcua = require("node-opcua");
var os = require("os");
// Let's create an instance of OPCUAServer
var server = new opcua.OPCUAServer({port: 4334});
var siteName = 'site01';
var var1 = {nodeId: 'ns=4;s=hook_weight', browseName: 'hook_weight', dataType: 'Double'};
var var2 = {nodeId: 'ns=4;s=rpm', browseName: 'rpm', dataType: 'Double'};
var var3 = {nodeId: 'ns=1;s=free_memory', browseName: 'free_memory', dataType: 'Double'};
function post_initialize(){
console.log("server initialized");
function construct_my_address_space(server) {
server.engine.createFolder("RootFolder",{ browseName: siteName});
// emulate variable1 changing every 500 ms
var variable1 = 1;
setInterval(function(){ variable1 += 1; }, 1000);
var1.value = {
get: function(){
return new opcua.Variant({dataType: opcua.DataType.Double, value: variable1 });
}
};
server.var1 = server.engine.addVariableInFolder(siteName, var1);
var2.value = {
get: function(){
return new opcua.Variant({dataType: opcua.DataType.Double, value: 10});
}
};
server.var2 = server.engine.addVariableInFolder(siteName, var2);
/**
/**
* returns the percentage of free memory on the running machine
* #return {double}
*/
function available_memory() {
// var value = process.memoryUsage().heapUsed / 1000000;
var percentageMemUsed = os.freemem() / os.totalmem() * 100.0;
return percentageMemUsed;
}
var3.value = {
get: function(){
return new opcua.Variant({dataType: opcua.DataType.Double, value: available_memory()});
}
};
server.var3 = server.engine.addVariableInFolder(siteName, var3);
}
construct_my_address_space(server);
server.start(function() {
console.log("Server is now listening ... ( press CTRL+C to stop)");
console.log("port ", server.endpoints[0].port);
var endpointUrl = server.endpoints[0].endpointDescription().endpointUrl;
console.log(" the primary server endpoint url is ", endpointUrl );
});
}
server.initialize(post_initialize);
sample_client code:
var opcua = require("node-opcua");
var async = require("async");
var client = new opcua.OPCUAClient();
var endpointUrl = "opc.tcp://" + require("os").hostname().toLowerCase() + ":4334/UA/SampleServer";
var session, subscription;
async.series([
// step 1 : connect to
function(callback) {
client.connect(endpointUrl,function (err) {
if(err) { console.log(" cannot connect to endpoint :" , endpointUrl ); }
else { console.log("connected !"); }
callback(err);
});
},
// step 2 : createSession
function(callback) {
client.createSession( function(err, _session) {
if(!err) { session = _session; }
callback(err);
});
},
// step 5: install a subscription and install a monitored item for 10 seconds
function(callback) {
subscription=new opcua.ClientSubscription(session,{
requestedPublishingInterval: 1000,
requestedLifetimeCount: 10,
requestedMaxKeepAliveCount: 2,
maxNotificationsPerPublish: 10,
publishingEnabled: true,
priority: 10
});
subscription.on("started",function(){
console.log("subscriptionId=", subscription.subscriptionId);
}).on("keepalive",function(){ console.log(); })
.on("terminated",function(){ callback(); });
setTimeout(function () {
subscription.terminate();
}, 10000);
// install monitored item
var monitoredItem = subscription.monitor({
nodeId: opcua.resolveNodeId("ns=1;s=free_memory"),
attributeId: opcua.AttributeIds.Value
},
{
samplingInterval: 100,
discardOldest: true,
queueSize: 100
},
opcua.read_service.TimestampsToReturn.Both
);
console.log("-------------------------------------");
monitoredItem.on("changed", function (dataValue) {
console.log(" % free mem = ", dataValue.value.value);
});
},
// close session
function (callback) {
// _"closing session"
session.close(function (err) {
if (err) {
console.log("session closed failed ?");
}
callback();
});
}
],
function(err) {
if (err) { console.log(" failure ",err); }
else { console.log('done!'); }
client.disconnect(function(){});
});
I am afraid Archestra doesn't have an OPC UA Server, so to access it from node-opcua, you will need to use an OPC UA Gateway, such as https://www.prosysopc.com/products/opc-ua-gateway/, which can convert OPC DA to OPC UA.

Node.js: REST Call and Request Function returns undefined values

I have been trying to learn the MEAN stack and ran into some issues with the javascript below that is in node.js. I have been having trouble with my module.exports.homelist function in which the functions, like function (err, response, body), have been giving me those values as undefined. I have been searching for answers for a while and came across asynchronous code and the callback function, but I was unable to find the solution that fits my situation, especially when the function is called on from within a request.
The Code:
var request = require('request');
var apiOptions = {
server : "https://localhost:3000"
};
if (process.env.NODE_ENV === 'production') {
apiOptions.server = "https://getting-mean-loc8r.herokuapp.com";
}
var renderHomepage = function (req, res, responseBody) {
var message;
if (!(responseBody instanceof Array)) {
message = "API lookup error";
responseBody = [];
} else {
if (!responseBody.length) {
message = "No places found nearby";
}
}
res.render('locations-list', {
title: 'Loc8r - find a place to work with wifi',
pageHeader: {
title: 'Loc8r',
strapline: 'Find places to work with wifi near you!'
},
sidebar: "Looking for wifi and a seat? Loc8r helps you find places to work when out and about. Perhaps with coffee, cake or a pint? Let Loc8r help you find the place you're looking for.",
locations: responseBody,
message: message
});
}
/* GET 'home' page */
module.exports.homelist = function(req, res) {
var requestOptions, path;
path = '/api/locations';
requestOptions = {
url : apiOptions.server + path,
method : "GET",
json : {},
qs : {
lng : -0.7992599,
lat : 51.378091,
maxDistance : 20
}
};
request(
requestOptions,
function(err, response, body) {
var i, data;
data = body;
if (data !== undefined && response !== undefined && response.statusCode === 200 && data.length) {
for (i=0; i<data.length; i++) {
data[i].distance = _formatDistance(data[i].distance);
}
}
renderHomepage(req, res, data);
}
);
var _formatDistance = function (distance) {
var numDistance, unit;
if (distance > 1) {
numDistance = parseFloat(distance).toFixed(1);
unit = 'km';
} else {
numDistance = parseInt(distance * 1000,10);
unit = 'm';
}
return numDistance + unit;
}
};
EDIT: This is the code I have in another file that uses my homelist function to render an HTML homepage:
var express = require('express'); var router = express.Router();
var ctrlLocations = require('../controllers/locations');
router.get('/', ctrlLocations.homelist);
module.exports = router;
You mention MEAN stack- are you requiring express? Please read the documentation on the express website.

Mock 'end' signal from emitter, but it doesn't get called

I am doing a unit testing with mocha + unit.js + proxyquire. Right now I am stuck at mocked emitter. First mocked emitter which is a fake on 'row' signal, it done. Second one I followed the same like first one. Since it is not a big difference, but I at here I have a question.
Why emitter is not emit 'end'?
userHandler_post.js :
var pg = require('pg');
var connectionString = require('./postgres.ini');
var pgdown = require('./pgdown.js');
exports.post = function(req,res, callback){
var cb_is_func = (typeof(callback)==='function');
// Grab data from http request
var adata = [req.body.username,
req.body.password,
req.body.privilege,
req.body.firstname,
req.body.middlename,
req.body.lastname,
req.body.streetaddress, //rename
req.body.subdistrict,
req.body.district,
req.body.province,
req.body.country,
req.body.zipcode,
req.body.email,
req.body.phonecountrycode,
req.body.phoneareacode,
req.body.phonenumber, //rename
req.body.faxcountrycode,
req.body.faxareacode,
req.body.faxnumber]; //rename
// Get a Postgres client from the connection pool
pg.connect(connectionString, function(err, client, done) {
// Handle Errors
if(err) {
done();
pgdown.pgdown(res);
if(cb_is_func){callback();}
}else{
// SQL Query > Insert Data
var func_ = 'SELECT Dugong.Users_Add($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)';
var addUser_ = client.query(func_, adata);
addUser_.on('error', function(error){
var data = {success : false,
username : req.body.username,
reason : {errmsg : 'Unable to add user',
errid : 'addUser_' }};
done();
res.json(data);
if(cb_is_func){callback(data);}
});
addUser_.on('end',function(result){
var data = {success : true, username : req.body.username};
done();
res.json(data);
if(cb_is_func){callback(data);}
});
}
});
pg.end();
};
userHandler_post.test.js :
var httpMocks = require('node-mocks-http');
var test = require('unit.js');
var real_userHandler = require('../routes/userHandler_post.js');
var proxyquire = require('proxyquire'),
pgStub = { };
var events = require('events');
describe('userHandler_post : ', function () {
var request;
beforeEach(function (){
request = httpMocks.createRequest({
method: 'POST',
url: '/users',
body : { Username : 'Yoda',
... //Omit to save question lines.
FaxNum: '',
}
});
});
it('should show connetion error. If cannot connect to database.', function (done) {
pgStub.connect = function (aconnectionString, cb){
cb('Connection refused',null,null);
};
var response = httpMocks.createResponse();
var userHandler_post = proxyquire('../routes/userHandler_post.js', { 'pg' : pgStub} );
userHandler_post.post(request,response); //Let it update response
var answer = response._getData();
test.value(answer).match('Connection refused');
done(); //Need
});
it('should show query error. If database rejects query.', function (done) {
pgStub.connect = function (aconnectionString, cb){
var client = {};
client.query = function(querystr){
var emitter = new events.EventEmitter();
setTimeout(function() {
emitter.emit('error', {detail: 'Query error'})
}, 0);
return emitter;
};
var done = function(){};
cb(null,client,done);
};
var response = httpMocks.createResponse();
var userHandler_post = proxyquire('../routes/userHandler_post.js', { 'pg' : pgStub} );
userHandler_post.post(request, response, function(){
var answer = response._getData();
test.value(answer).match('Query error');
});
done(); //Need
});
it('should show several records. If database processes query.', function (done) {
pgStub.connect = function (aconnectionString, cb){
var client = {};
client.query = function(querystr){
var emitter = new events.EventEmitter();
console.log('below emitter');
setTimeout(function() {
console.log('-*************--');
emitter.emit('end', {a : 1});
}, 0); //
return emitter;
};
var done = function(){};
cb(null, client, done);
};
var response = httpMocks.createResponse();
var userHandler_post = proxyquire('../routes/userHandler_post.js', { 'pg' : pgStub} );
userHandler_post.post(request, response, function(){
var answer = response._getData();
console.log(answer);
// test.value(answer).match('Connection refused');
});
// console.log(response._getData());
done(); //Need
});
});
Terminal :
mocha testing/userHandler_post.test.js
userHandler_post :
✓ should show connetion error. If cannot connect to database.
✓ should show query error. If database rejects query.
below emitter
✓ should show several records. If database processes query.
3 passing (10ms)
If it really emitted the 'end' signal. Then it should say 'Insert record completed'.
I found it.
Upgrade node from v0.10.29 to v0.12.6
npm cache clean -f
npm install -g n
aptitude install curl
n stable

NodeJS memory usage

I am playing with NodeJS and for this purpose created an email extractor. Somehow when i create multiple http requests the node.exe memory useage in windows task manager keeps increasing. I understand that the node needs more memory to process the requests but what i noticed that this memory usage does not come down even after all requests have been successfully processed.
When i start nodejs it consumes about 35000K memory but after about 80-100 request this goes upto 50000K and stays.
Here is my simple email extractor module:
var request = require('request'),
cheerio = require('cheerio'),
async = require('async'),
urlHelper = require('url');
function Extractor(config) {
this.baseUrl = config.url;
this.parsedUrl = urlHelper.parse(config.url);
this.urls = [];
this.emails = [];
}
Extractor.prototype.getEmails = function getEmails(html) {
var foundEmails = html.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi) || [];
if(foundEmails.length) this.emails = this.emails.concat(foundEmails);
}
Extractor.prototype.extract = function extract(html) {
var $ = cheerio.load(html),
that = this;
if($('body')){
this.getEmails($('body').html());
}
if(!this.emails.length){
$("a[href^='http://" + this.parsedUrl.host + "'], a[href^='https://" + this.parsedUrl.host + "'], a[href^='/'], a[href^='./'], a[href^='../']").each(function(k, v) {
that.urls.push(urlHelper.resolve(that.baseUrl, $(v).attr('href')));
});
}
};
/**
* Process the base URL
*/
Extractor.prototype.processBase = function processBase(next) {
request(this.baseUrl, function(err, response, body) {
return next(err, body);
});
}
/**
* Process the internal pages
*/
Extractor.prototype.processInternal = function processInternal(cb) {
var that = this;
async.whilst(
// while this condition returns true
function () { return that.emails.length === 0 && that.urls.length > 0; },
// do this
function (callback) {
request(that.urls.shift(), function (err, response, body) {
var $ = cheerio.load(body);
if($(body)){
that.getEmails($('body').html());
}
callback(); // async internal, needs to be called after we are done with our thing
});
},
// call this if any errors occur. An error also stops the series
// this is also called on successful completion of the series
function (err) {
cb(that);
}
);
}
Extractor.prototype.process = function process(next) {
var that = this;
this.processBase(function(err, html) {
if(err) {
console.log(err);
} else {
that.extract(html);
if(!that.emails.length) {
that.processInternal(function(res) {
return next(null, that);
});
}
}
});
}
module.exports = Extractor;
and here is how i call it:
var express = require('express');
var router = express.Router();
var Extractor = require('../services/Extractor');
router.get('/', function(req, res) {
res.json({msg: 'okay'});
var extractor = new Extractor({url: 'http://lior-197784.use1-2.nitrousbox.com:4000/crawl'});
extractor.process(function(err, res) {});
});
module.exports = router;

Categories

Resources