I am using the node.js agent for the new relic. I am using Node.js custom instrumentation to monitor socket.io, new relic web transaction appearing under root and no data is visible as I am not able to monitor socket.io. Below is the output under Transaction Root Path
Breakdown table
Category Segment % Time Avg calls (per txn) Avg time (ms)
WebTransaction Root path 100.0 1.0 2,150
Server Code
var http = require('http'),
fs = require('fs'),
nr = require('newrelic'),
index = fs.readFileSync(__dirname + '/sock_client.html');
var app = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(index);
});
// Socket.io server listens to our app
var io = require('socket.io').listen(app);
// Send current time to all connected clients
function sendTime() {
io.emit('time', { time: new Date().toJSON() });
}
// Send current time every 10 secs
setInterval(sendTime, 10000);
// Emit welcome message on connection
io.on('connection', function(socket) {
// Use socket to communicate with this particular client only, sending it it's own id
socket.emit('welcome', { message: 'Welcome!', id: socket.id });
socket.on('rings', function(data){
nr.startWebTransaction('websocket/ping/test_v3', function transactionHandler() {
socket.emit('pong', { message: 'Welcome!' });
console.log(data);
nr.addCustomParameters({
"Discount Code": "Summer Super Sale",
"Item Code": 31456
});
});
});
socket.on('pings', function(data){
nr.startWebTransaction('websocket/ping/test_v5', function transactionHandler() {
let trans = nr.getTransaction();
someAsyncBeha("console.log", function(){
trans.end();
})
console.log(data);
});
});
});
function someAsyncBeha(data, cb){
setTimeout(function() {
console.log("Goodbye!");
console.log(data);
cb();
}, 5000);
};
Client Code
<!doctype html>
<html>
<head>
<link rel="shortcut icon" href="/favicon.png">
<script src='/socket.io/socket.io.js'></script>
<script>
var socket = io();
socket.on('welcome', function(data) {
addMessage(data.message);
// Respond with a message including this clients' id sent from the server
socket.emit('rings', {data: 'foo!', id: data.id});
});
socket.on('time', function(data) {
addMessage(data.time);
socket.emit('pings', {data: 'foo!', id: data.time});
});
socket.on('error', console.error.bind(console));
socket.on('message', console.log.bind(console));
socket.on('pong', console.log.bind(console));
function addMessage(message) {
var text = document.createTextNode(message),
el = document.createElement('li'),
messages = document.getElementById('messages');
el.appendChild(text);
messages.appendChild(el);
}
</script>
</head>
<body>
<ul id='messages'></ul>
</body>
</html>
The issue was in the new relic module version, there are two suggestions.
First, upgrade the Node.js agent to v2.2.0
This version includes a bug fix that should resolve the issue you're seeing.
Second, move nr = require('newrelic'); to the top of the requires.
This ensures the agent catches everything in your application before the code has a chance to spin up. Without this, the code in the other requires can launch before the agent has a chance to inject its methods, resulting in no tracking for those methods.
Related
Following is my POST function in Node js. I want to call a funtion in my client side HTML to display an error message on the page.
router.post('/',(req,res)=>{
const data = JSON.stringify({
institute_name: req.body.institute_name,
email : req.body.email,
password : req.body.password
})
const options = {
host:'localhost',
port:'8888',
path:'/registerInstitute',
method:'POST',
headers: {
'Content-Type':'application/json'
}
}
const req1 = http.request(options, (res1)=>
{
const status = res1.statusCode
if (status == 201)
{
//admin created
res.redirect('/?account_created=true')
}
else if ( status == 409)
{
//CALL AJAX FUNCTION TO DISPLAY ERROR MSG
}
})
req1.write(data)
req1.end()
})
The simple answer is NO. But there are workarounds to do so and I've demonstrated the one that will suite your scenario
Sockets
You can use web sockets to trigger event to notify client to run specific function
On service side you can do something like this:
var io = require('socket.io').listen(80); // initiate socket.io server
if (
io.sockets.on('connection', function (socket) {
if ( error == 403 ) {
socket.emit('runErrorFunction', { error: "error data" });
}
});
You can do something like this on client side:
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost'); // connect to server
socket.on('runErrorFunction', function (data) { // listen to runErrorFunction event raised by the server
// Here goes your error showing logic
});
</script>
Here is the link for more info Socket.io
I am new in socket.io. I wanted to develop an small application using it. I know the basic of socket.io. I have followed this and this documentation.
I am also able to make this simple connection. Code :
Client:
<script src="/socket.io/socket.io.js"></script>
<script>
console.log(location.protocol+'//'+location.host);
var socket = io.connect(location.protocol+'//'+location.host), socketwithApi = io.connect(location.protocol+'//'+location.host + '/apikey/');
</script>
<script type="text/javascript">
var i=0;
$(document).on('click','#socket-emit-btn', function(){
let message = location.href;
socket.emit("test",message);
});
socket.on("testlistened",function(data){
i ++;
console.log(i);
console.log(data);
if(data){
$("#console-div").html(data);
}else{
$("#console-div").html("{empty}");
}
});
socketwithApi.on('apikey',function(data){
console.log(data);
});
</script>
Server:
//consider everything needed is defined
var apikey = io
.of('/apikey/')
.on('connection', function (socket) {
socket.emit('apikey', { news: 'item' });
});
io.on('connection', function (socket) {
let clientID = socket.id
let clientIP = socket.handshake.address
if (client) client.socket = socket
console.log('User-Client Connected!: IP: ' + clientIP)
socket.on("test",function(data){
console.log("listened");
let ParsedData = url.parse(data);
let responseData = {
UrlScheme:ParsedData,
socketID: clientID,
api_key: ParsedData.pathname
}
console.log(responseData);
console.log(`${TRANSACTIONGETRECEIPT}_RESPONSE`)
socket
.binary(true)
.emit('testlistened', JSON.stringify(responseData))
});
socket.on('disconnect', function (data) {
console.log(clientID + ' has disconnected')
})
})
Everything is working fine, i am able to emit and listen both from the server side and client side. But I did not find the documentation which would tell if it is possible to send http get or post request from the browser or postman to socket.io . Is it only possible to send request from a page where socket client is present or can we also send request like
http://localhost:8099/api-hastgraph-key/socket.io/?EIO=3&transport=websocket&sid=w0kDs4oGI7SVwB3YAAAC
or http://localhost:8099/socket.io/api-hastgraph-key?EIO=3&transport=websocket&sid=w0kDs4oGI7SVwB3YAAAC
from browser and connect to socket.
Thank you. Any kind of help are highly appreciated.
I have a NodeJS App with Socket Io integration. Now my web page and app both has been implemented but I am facing one issue during execution:
Below is my web page code:
<script>
$(document).ready(function(){
$("#batch")[0].reset();
var socket = io.connect('http://xx.xx.xxx.xx:xxxx',{'forceNew':true });
socket.on('message', function (data) {
var newtext = data;
document.batch.outputtext.value += newtext;
});
socket.on('end', function (data) {
socket.disconnect();
});
});
</script>
And my NodeJS App:
exec_script = function(resp) {
socket.on('connection', function (client) {
console.log('Connection Established');
client.on('disconnect', function () {
console.log('disconnected');
return;
});
var pyshell = new PythonShell('./test.py', options ={ mode: 'text', pythonOptions: ['-u'] });
pyshell.stdout.on('data', function(data) {
client.emit('message', data);
console.log(data);
});
pyshell.end(function(err) {
if (err) throw err;
console.log('End Script');
client.emit('end', 'end');
client.disconnect();
});
});
};
The issue I am facing is that when the Python scripts executes its output is send to browser while my browser status states "Waiting for xx.xx.xxx.xx" and in my FF I see the blue circle circling - that's fine - but even after the Python script has ended and socket disconnected explicitly I still see the browser status as "Waiting for xx.xx.xxx.xx browser title as Connecting with the blue circle rotating?
How can I close and end the connection successfully with the fact that I need the same page in the browser that is I would not navigate the user to some other page?
I tried by using response.end() but the issue I am facing is that if the request data was posted as URL form /today then calling response.end() changes the URL at browser side to http://xx.xx.xxx.xx:xxxx/today leading to a blank / error page which is what I a do not want in my case - the URL should remain as http://xx.xx.xxx.xx:xxxx?
Below is the method I am calling my exec_script method:
router.post('/', function(req, res) {
methods.process(req, res);
});
exports.process = function(req, resp) {
var bname = req.body['date'];
if(typeof req.body['date'] !== "undefined" && req.body['date'] !== null)
{
exec_script(req, resp);
}
};
I am entirely new to Nodejs and trying to get familiar with it.
Well, currently, I am trying to push notifications on the web browser if any change happens in the database. I have piece of code which i have been using for testing purpose first. Following code works fine to send updates to browser when database table contents change:
Server.js
var app = require('http').createServer(handler).listen(8000),
io = require('socket.io').listen(app),
fs = require('fs'),
mysql = require('mysql'),
connectionsArray = [],
connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejs',
port: 3306
}),
POLLING_INTERVAL = 3000,
pollingTimer,
pollingTimer_2;
// If there is an error connecting to the database
connection.connect(function(err) {
// connected! (unless `err` is set)
console.log(err);
});
// on server started we can load our client.html page
function handler(req, res) {
fs.readFile(__dirname + '/client.html', function(err, data) {
if (err) {
console.log(err);
res.writeHead(500);
return res.end('Error loading client.html');
}
res.writeHead(200);
res.end(data);
});
}
/*
* This function loops on itself since there are sockets connected to the page
* sending the result of the database query after a constant interval
*
*/
var pollingLoop = function() {
// Doing the database query
var query = connection.query('SELECT * FROM users'),
users = []; // this array will contain the result of our db query
// setting the query listeners
query
.on('error', function(err) {
// Handle error, and 'end' event will be emitted after this as well
console.log(err);
updateSockets(err);
})
.on('result', function(user) {
// it fills our array looping on each user row inside the db
users.push(user);
})
.on('end', function() {
// loop on itself only if there are sockets still connected
if (connectionsArray.length) {
pollingTimer = setTimeout(pollingLoop, POLLING_INTERVAL);
updateSockets({
users: users
});
}
});
};
// creating a new websocket to keep the content updated without any AJAX request
io.sockets.on('connection', function(socket) {
console.log('Number of connections:' + connectionsArray.length);
// starting the loop only if at least there is one user connected
if (!connectionsArray.length) {
pollingLoop();
}
socket.on('disconnect', function() {
var socketIndex = connectionsArray.indexOf(socket);
console.log('socket = ' + socketIndex + ' disconnected');
if (socketIndex >= 0) {
connectionsArray.splice(socketIndex, 1);
}
});
console.log('A new socket is connected!');
connectionsArray.push(socket);
});
var updateSockets = function(data) {
// adding the time of the last update
data.time = new Date();
// sending new data to all the sockets connected
connectionsArray.forEach(function(tmpSocket) {
tmpSocket.volatile.emit('notification', data);
});
};
Client.html
<html>
<head>
<title>Push notification server streaming on a MySQL db</title>
<style>
dd,dt {
float:left;
margin:0;
padding:5px;
clear:both;
display:block;
width:100%;
}
dt {
background:#ddd;
}
time {
color:gray;
}
</style>
</head>
<body>
<time></time>
<div id="container">Loading ...</div>
<script src="socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
// create a new websocket
var socket = io.connect('http://localhost:8000');
// on message received we print all the data inside the #container div
socket.on('notification', function (data) {
var usersList = "<dl>";
$.each(data.users,function(index,user){
usersList += "<dt>" + user.user_name + "</dt>\n" +
"<dd>" + user.user_desc + "\n" +
"<figure> <img class='img-polaroid' width='50px' src='" + user.user_img + "' /></figure>"
"</dd>";
});
usersList += "</dl>";
$('#container').html(usersList);
$('time').html('Last Update:' + data.time);
});
</script>
</body>
</html>
Now, as you can see that currently server is listening at the port 8000. I am just wondering that how can i change it to listen to an specific url ? Because if i am going to implement on the server project then I am not going to using the url to listen on ports ? Rather i want to use it as plain Url as I can smoothly send notification to if any user is connected to specific url?
Any help?
If you want your node server to respond to the URL http://www.example.com/updates, then you make your server listen on port 80 (the default port if no port is listed and the protocol is "http"). And, then you make your server respond to the "/updates" route.
Servers listen on a specific port at a specific IP address. They don't listen to a path or URL. The browser uses DNS to get an IP address for the host in the URL. If there's a port number in the URL, it uses that port. If not, it uses the default port for the specific protocol. It then makes a TCP connection to that IP address on that port. Then, if the protocol is http, it sends a request on that connection and includes the path.
So, the server receives the incoming connection and then as part of the HTTP protocol, it receives the verb (GET, POST, DELETE, etc...) and the path which it is then the servers job to decide what to do based on the incoming command/path.
I'm trying to develop a Faye server side client to run automatically as needed. In the official website of Faye, I find only document about server side client, there is no information about how to run it.
Please tell me how to do so
Thanks
There's a key missing piece in the documentation. It appears you need to call client.connect() in order to receive events.
Here is what worked for me:
var faye = require('faye');
var client = new faye.Client('http://localhost:8000/faye');
//This was missing from the documentation
client.connect();
var subscription = client.subscribe('/foo', function(message){
console.log("Event Received");
console.log(message);
})
//This is optional
subscription.then(function() {
console.log('Subscription is now active!');
});
var publication = client.publish('/foo', {text: "Hello World!"});
publication.then(function() {
console.log('Message received by server!');
}, function(error) {
console.log('There was a problem: ' + error.message);
});
just stumpled on this through Google. You should be able to run a client using just this code:
var faye = require('faye'),
client = new faye.Client('http://example.com/faye');
client.subscribe('/some/channel', function(message) {
// process message
});
If you still have trouble, please get on the mailing list at http://groups.google.com/group/faye-users
Create a .rb file and fill with following code
require 'rubygems'
require 'faye'
cliv=Faye::RackAdapter.new(
:mount => '/cliv',
:timeout => 25
)
cliv.listen(3000)
Go to console and type
ruby your_file.rb
Once you have done. create a js with html as following :
<script type="text/javascript" src="http://localhost:3000/faye.js"></script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js'></script>
<script>
$("document").ready(function(){
faye = new Faye.Client('http://localhost:3000/faye');
faye.connect();
subscribeObj = faye.subscribe("/hi", function(message) {
$("#response").append(message.text);
$("#content").val("");
});
$("#say").click(function(){
content=$("#content").val();
faye.publish("/hi", {text: content});
});
});
</script>
<div id='response'></div>
<br/>
<input type='text' id='content' />
<div style='cursor:pointer;' id='say'> Say Something </div>
And I think u r ready to go. :)