Upgrade to Pro — share decks privately, control downloads, hide ads and more …

UMRUM - Open Source Real User Monitoring with Node.js

Rafael Verger
September 25, 2014

UMRUM - Open Source Real User Monitoring with Node.js

Apresentação feita na SEMCOMP 2014 sobre um serviço Open Source para rastreamento de usuários em tempo real. Como construímos o UMRUM usando Node.js e Redis :)

Rafael Verger

September 25, 2014
Tweet

More Decks by Rafael Verger

Other Decks in Programming

Transcript

  1. Tem que ser algo como: o último RUM que você

    vai precisar! O serviço vai ser algo mágico.. plug'n'play!
  2. Tem que ser um nome fucking awesome! Tem que ser

    algo como: o último RUM que você vai precisar! O serviço vai ser algo mágico.. plug'n'play!
  3. Então, vamos fazer um projeto, já temos um prazo, e

    o que vamos fazer? @helielson: "sempre quis implementar 'um Chartbeat'". Vamos fazer um "Chartbeat Open Source"! E por que mais um RUM?
  4. Definindo um UUID pro usuário props.uid = generate_uuid(); doc.cookie =

    [ cookieName, '=', props.uid, ';expires=', weekAhead ].join(''); // UUID = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
  5. Ei, servidor, to aqui! API.ping = function(){ if ( IS_USER_ACTIVE

    ) this.send('/ping'); this.ping_timeout = setTimeout(function(){ API.ping(); }, 30 * 1000); }
  6. API.send send = function(route){ this.element.src = [ // this.element =

    <img> this.API_URL, route, "?uid=", props.uid, "&hostId=", props.hostId, "&url=", win.location, "&title=", doct.title, "&servertime=", svtime, "&pageload=", pgload, "&t=", (+new Date) ].join(''); }
  7. Navigation Timing window.performance.timing { "loadEventStart": 1411631886735, "domComplete": 1411631886735, "responseEnd": 1411631885549,

    "responseStart": 1411631885347, "requestStart": 1411631884630, "redirectEnd": 0, "redirectStart": 0, "unloadEventStart": 0, } https://developer.mozilla.org/en-US/docs/Navigation_timing
  8. function activate_user() { USER_ACTIVE = true; } addEvent(window, 'scroll', activate_user);

    addEvent(doc.body, 'click', activate_user); addEvent(doc.body, 'mouseover', activate_user); activate_user(); Usuários ativos
  9. Usuários inativos :( _oldblur = window.onblur; window.onblur = function(){ try{_oldblur();}

    catch(e){} USER_ACTIVE = false; }; addEvent(win, 'beforeunload', API.exit);
  10. Salvando usuários ativos multi = redisclient.multi(); // pipeline multi.hincrby(user.hostId, 'curr_visits',

    1); multi.zincrby(toppagesKey, 1, user.url); multi.lpush(servertimeKey, user.servertime); multi.lpush(pageloadKey, user.pageload); multi.hmset(user.uid, user); multi.setex(EXP_PREFIX+user.uid, USR_TIMEOUT, 1); multi.exec();
  11. Entregando os dados multi = redisclient.multi(); // pipeline multi.hget(hostId, 'curr_visits');

    multi.zrevrangebyscore( toppagesKey, +inf', -inf', 'WITHSCORES', 'LIMIT', 0, MAX_TOPPAGES); multi.lrange(servertimeKey, 0, MAX_PERF_LIST); multi.lrange(pageloadKey, 0, MAX_PERF_LIST); multi.exec(send_data_to_dashboard);
  12. var TrackedSites = React.createClass({ trackNewSite: function(host) { // ... },

    render: function() { var siteItems = this.state.sites.map(function(site) { return ( <SiteItem host={site.host} code={site.code} /> ); }); return ( <div className="site-list-panel"> <h3>Your sites</h3> <div className="site-list"> {siteItems} </div> <AddSiteForm onSiteSubmit={this.trackNewSite} /> </div> ); } }); components/tracked-sites.jsx