| 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