Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
const request = require('request')
;
const ACCOUNT_ID = 'GET THIS FROM YOUR URL';
const API_KEY = 'GET THIS FROM INSIGHTS ADMIN';
const BASE_URL = `https://insights-api.newrelic.com/v1/accounts/${ACCOUNT_ID}/query?nrql=`;
module.exports = {
query: function(query) {
return new Promise(function(resolve, reject) {
const url = BASE_URL + encodeURIComponent(query);
request({
url: url,
headers: {
'Accept': 'application/json',
'X-Query-Key': API_KEY
}
}, function(err, httpResponse, body) {
if (err) {
reject(err);
return;
}
try {
const result = JSON.parse(body);
if (result['error']) {
reject(result);
} else {
resolve(result);
}
} catch (err) {
// Possible JSON parse errors are caught here
reject(err);
}
});
});
}
};
// Create the map and the marker clusterer
const map = new goog.maps.Map(document.getElementById('google-map'), {zoom: 4, center: {lat: 39.842523, lng: -97.940038}});
const clusterer = new MarkerClusterer(map);
// Wait for events on our socket
const socket = io('/socket.io/socket.io.js');
socket.on('newLocations', function(timeAndLocationInfo) {
for (let timestamp in timeAndLocationInfo) {
// Schedule all our updates so they occur two minutes after real-time to make up for network/new relic latency
const delay = Math.max(0, timestamp - (Date.now() - 1000 * 60 * 2));
setTimeout(function(newLocations) {
newLocations.forEach((event) => {
const fromLocation = {lat: event.from_user_latitude, lng: event.from_user_longitude};
const toLocation = {lat: event.to_user_latitude, lng: event.to_user_longitude};
// Add markers to the map using a clusterer so they are combined
const fromMarker = new google.maps.Marker({
'icon': '/images/heart-icon.png',
'position': fromLocation
});
const toMarker = new google.maps.Marker({
'icon': '/images/heart-icon.png',
'position': toLocation
});
clusterer.addMarker(toMarker, false);
clusterer.addMarker(fromMarker, false);
// Draw a line between the two markers on the map
const line = new google.maps.Polyline({
path: [fromLocation, toLocation],
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1,
strokeWeight: 2
});
line.setMap(map);
// Remove everything we drew after 10 seconds
setTimeout(function() {
clusterer.removeMarker(toMarker);
clusterer.removeMarker(fromMarker);
line.setMap(null);
}, 1000 * 10);
});
clusterer.redraw();
}.bind(this, timeAndLocationInfo[timestamp]), delay);
}
});
const insightsClient = require('./insights-api-client')
;
const connectedUsers = new Set([]);
var io = null;
let locationTimeout = null;
let lastLoadedLocations = null;
function setup(server) {
io = require('socket.io')(server);
io.on('connection', function(socket) {
connectedUsers.add(socket.id);
if (connectedUsers.size == 1) {
scheduleLocationUpdates_();
} else if (lastLoadedLocations) {
io.to(socket.id).emit('newLocations', lastLoadedLocations);
}
socket.on('disconnect', function() {
connectedUsers.delete(socket.id);
if (connectedUsers.size == 0) {
stopUpdates_();
}
});
});
}
function scheduleLocationUpdates_() {
if (locationTimeout != null) {
return;
}
insightsClient
.query("ADD YOUR QUERY HERE")
.then(function(results) {
const results = results['results'][0]['events'];
for (let socketId of connectedUsers) {
io.to(socketId).emit('newLocations', timestamps);
}
lastLoadedLocations = results;
locationTimeout = setTimeout(function() {
locationTimeout = null;
scheduleLocationUpdates_();
}, 1000 * 60); // One minute forward in case you have an "until 1 minute ago" clause in your query to skip incomplete data
}, function(error) {
console.error(error);
// Retry in case this was a network error
setTimeout(scheduleLocationUpdates_, 5000);
});
}
function stopUpdates_() {
lastLoadedLocations = null;
if (locationTimeout) {
clearTimeout(locationTimeout);
locationTimeout = null;
}
}
exports.setup = setup;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.