Come funziona il tracking dei post in Discourse

Discourse traccia il tempo di lettura per ogni post visualizzato dagli utenti sullo schermo. Questo sistema si è evoluto nel corso degli anni e spesso devo fare riferimento al codice per capire come funziona e perché esiste.

Questo post tratta i dettagli tecnici dolorosi dell’implementazione attuale.

Come il client Discourse traccia i tempi

Il tracciamento dei tempi dei post è implementato in screen-track.js.es6. Questo modulo è responsabile del tracciamento di quanto tempo un post è rimasto sullo schermo e di quanto tempo il topic è stato visibile.

Quando una pagina di un topic “scorre”, informa il tracciatore dello schermo su quali post sono visibili E quali di questi post sono stati letti. Consideriamo i post parzialmente visibili come “in vista”.

Il tracciatore dello schermo quindi invia un “tick” ogni secondo che decide quali dati devono essere inviati al server.

Il tracciatore dello schermo manterrà traccia di più elenchi.

a. Un elenco di (post/tempo trascorso leggendo il post) che non è stato inviato al server
b. Un elenco di post che sappiamo essere stati letti
c. Un elenco di post che sappiamo essere attualmente sullo schermo

All’inizio di un tick (ogni secondo), se abbiamo post in (a), valuteremo di inviarli al server:

  • Se l’impostazione del sito flush_timing_secs (default 60 secondi) è passata dall’ultima volta che abbiamo inviato dati al server.

  • Se uno qualsiasi dei post è “non letto” dall’utente, invieremo l’intero elenco immediatamente

Alla fine di un tick, se Discourse è in primo piano:

Se abbiamo “post sullo schermo”, registreremo “1 tick” di tempo per ogni post

Se in qualsiasi momento usciamo dal topic (navigando in un’altra parte di Discourse)

Invieremo immediatamente tutto ciò che è “in volo” in (a) al server.

Limiti

  • Ogni volta che visualizzi un topic, registreremo un massimo di 6 minuti di tempo di lettura per post (questo si resetta se navighi via e torni al post)

  • Se passano 3 minuti e non hai affatto scorruto, disabilitiamo questo sottosistema finché non scorri di nuovo

  • Registreremo i tempi per un massimo di 5 topic per gli utenti anonimi (che viene convertito quando l’utente si registra nei dati nella tabella posts_timing)

Osservazione chiave

  1. Anche se la tabella post_timings traccia fino al millisecondo, abbiamo tra “0-1000ms” di tempo “non registrato” per post, a seconda di quando scatta il tick.

  2. Ogni “sessione” di visualizzazione di un topic può registrare fino a 6 minuti di tempo di lettura per post. Non c’è un limite superiore al tempo di lettura per post; un post può essere letto per giorni da un utente se l’utente torna a un topic.

Cosa facciamo con questi dati?

La parte più critica di informazioni che utilizziamo è “l’utente X ha letto il post Y”, questo determina i conteggi dei non letti nel topic e molte altre informazioni critiche.

Tranne per l’uso binario, utilizziamo il tempo registrato in post_timings per calcolare avg_time per un post.

Il tempo medio per un post è calcolato come l’esponenziale della media del logaritmo naturale del tempo (cioè la media geometrica).

Quindi, ad esempio:

Post 1: sam, 10 secondi
Post 2: jane, 1 ora

avg_time = exp((log(3600000) + log(10000)) / 2)
=~ exp((15.09 + 9.2) / 2)
=~ 189094
=~ 189 secondi

Questo avg_time viene quindi utilizzato nel calcolatore dei punteggi come un componente per il “punteggio del post”.

Punteggio = 5 * conteggio risposte + 15 * punteggio like + 5 * conteggio link in entrata + 2 * conteggio segnalibri + 0.05 * avg_time + 0.2 * letture del post.

Quindi, nel caso sopra, 189 secondi in media di lettura di un post si traducono in 37 punti. Quindi… circa 2 like e un po’. O 72 letture.

Il “punteggio del post” viene quindi utilizzato per “i migliori” per capire quali sono i migliori post in un topic.

Isn’t this read data the backing store for these numbers, total read time?

Yes the “topic read time” I will update the OP to explain about that, I touched on it very lightly.

The topic_users table has a column called total_msecs_viewed. This number is updated independent of post_timings in the same controller action. We can not “rebuild” that number from post timings cause we have no idea about overlapping times.

The “topic timing” piece has no 6 minute limit like post timing does. The number is flushed with the same post timing batch according to the same rules.

I think I was so focused on talking about post tracking that I missed out on explaining the topic tracking part.

Whoa… we do? Do we really need to do this? It feels unnecessary?

What do you mean by “overlapping times”?

I have not tested this recently, but yes the code is all there to do it. I guess it means you can get to TL1 a bit faster.

Say you we know about my timings:

Post 1: 10 seconds
Post 2: 12 seconds
Post 3: 17 seconds

The time I spent reading the topic can be anywhere between 17 seconds and 39 seconds.

So we can not use the data in the posts timing table to figure out what the number in topic users should be. So we are forced to track that other number independently.

It is not a huge deal and makes no big diff, but there is no way to “run an inventory” and check that the number in topic user is 100% correct.