Monitoring Electric Scooters in Paris with Datadog and NodeJS

Eric Mustin
Apr 29 · 5 min read



async (req) => {
try {
// get zip code lat/lng and format, throw error if missing
let [zip, country] = [,]
if (zip === undefined || country === undefined) { throw "please submit a zip and country code" } let geoApiDetails = `${config.geonames_username}&country=${country}&postalcode=${zip}`
let geoInfo = await axios.get(geoApiDetails)
let mappedGeoInfo = {[zip]: { "lat":[0]["lat"], "lng":[0]["lng"]} }

} catch (err) {
console.log('error', err);
//register token w/any email then get+format scooters in 500m radius of zip code lat/lng
await bird.login(;
let results = await Promise.all([bird.getScootersNearby(mappedGeoInfo[zip]["lat"],mappedGeoInfo[zip]["lng"])])
let mapped = results.reduce( (mapping, zip_scooter_list) => {
if (mapping[zip] === undefined) { mapping[zip] = {} }
mapping[zip]['avg_scooter_battery_level'] = average( (scoot) => scoot.battery_level))
mapping[zip]['scooter_count'] = zip_scooter_list.length
return mapping
//send bird custom metrics to DD with zip code tags
await Promise.all( Object.keys(mapped).map( (x) => dogapi.metric.send("bird.scooterCount", mapped[x]['scooter_count'], {tags: "zip:"+x})))
await Promise.all( Object.keys(mapped).map( (x) => dogapi.metric.send("bird.avgScooterBatteryLevel", mapped[x]['avg_scooter_battery_level'], {tags: "zip:"+x})))
*/10 *  *  *  *     curl -k http://localhost:3000?country=FR&zip=75001


Datadog timeseries dashboard of average scooter battery level per arrondissement
Datadog timeseries dashboard of number of scooters per arrondissement

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade