Como funciona o rastreamento de posts no Discourse

O Discourse rastreia o tempo de leitura para cada postagem que os usuários veem na tela. Este sistema evoluiu ao longo dos anos e, frequentemente, preciso consultar o código para entender como isso funciona e por que existe.

Esta postagem aborda os detalhes técnicos difíceis da implementação atual.

Como o cliente do Discourse rastreia o tempo

O rastreamento de tempo das postagens é implementado em screen-track.js.es6. Este módulo é responsável por rastrear quanto tempo uma postagem permaneceu na tela e quanto tempo o tópico ficou visível.

Quando uma página de tópico “rola”, ela informa ao rastreador de tela quais postagens estão visíveis E quais dessas postagens foram lidas. Consideramos postagens parcialmente visíveis como “visíveis”.

O rastreador de tela então dispara um “tick” a cada segundo que decide quais dados precisam ser enviados ao servidor.

O rastreador de tela manterá o controle de várias listas.

a. Uma lista de (postagem/tempo gasto lendo a postagem) que ainda não foi enviada ao servidor
b. Uma lista de postagens que sabemos que foram lidas
c. Uma lista de postagens que sabemos que estão na tela agora

No início de um tick (a cada segundo), se houver postagens em (a), consideraremos enviá-las ao servidor:

  • Se a configuração do Site flush_timing_secs (padrão de 60 segundos) tiver passado desde a última vez que enviamos dados ao servidor.

  • Se alguma das postagens estiver “não lida” pelo usuário, enviaremos a lista inteira imediatamente

No final de um tick, se o Discourse estiver em foco:

Se houver alguma “postagem na tela”, registraremos “1 tick” de tempo para cada postagem

Se em algum momento sairmos do tópico (navegarmos para outro lugar no Discourse)

Enviaremos imediatamente tudo que estiver “em trânsito” em (a) para o servidor.

Limites

  • Cada vez que você visualiza um tópico, registraremos no máximo 6 minutos de tempo de leitura por postagem (isso será redefinido se você navegar para fora e voltar à postagem)

  • Se 3 minutos se passarem e você não tiver rolado nada, desativaremos este subsistema até que algo role novamente

  • Registraremos o tempo de até 5 tópicos para usuários anônimos (o que é convertido quando o usuário se cadastra em dados na tabela posts_timing)

Observação importante

  1. Embora a tabela post_timings rastreie até o milissegundo, temos entre “0-1000ms” de tempo “não registrado” por postagem, dependendo de quando o tick é disparado.

  2. Cada “sessão” de visualização de um tópico pode registrar até 6 minutos de tempo de leitura por postagem. Não há limite superior de tempo de leitura por postagem; uma postagem pode ser lida por dias por um usuário se ele retornar ao tópico.

O que fazemos com esses dados?

A informação mais crítica que utilizamos é “o usuário X leu a postagem Y”, o que determina as contagens de não lidos no tópico e muitos outros dados críticos.

Exceto pelo uso binário, usamos o tempo registrado em post_timings para calcular o avg_time de uma postagem.

O tempo médio de uma postagem é calculado como o exponencial da média do logaritmo natural do tempo (ou seja, média geométrica).

Por exemplo:

Postagem 1: sam, 10 segundos
Postagem 2: jane, 1 hora

avg_time = exp((log(3600000) + log(10000)) / 2)
=~ exp((15,09 + 9,2) / 2)
=~ 189094
=~ 189 segundos

Esse avg_time é então usado na calculadora de pontuação como um componente para a “pontuação da postagem”.

Pontuação = 5 * número de respostas + 15 * pontuação de curtidas + 5 * número de links de entrada + 2 * número de favoritos + 0,05 * avg_time + 0,2 * leituras da postagem.

Portanto, no caso acima, 189 segundos de leitura média de uma postagem equivalem a 37 pontos. Então… aproximadamente 2 curtidas e um pouco mais. Ou 72 leituras.

A “pontuação da postagem” é usada então para o “melhor de” para determinar quais são as melhores postagens em um tópico.

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.