Conceitos
Distributed tracing / spans
Intuição
Imagine pedir um item num restaurante que na verdade é uma central de vários fornecedores: o garçom anota seu pedido, repassa pra cozinha, a cozinha manda buscar um ingrediente num depósito terceirizado, e o depósito aciona um entregador. Se o prato demora, ninguém sozinho sabe onde travou — cada um só viu seu próprio pedacinho. Um rastro (trace) é como se cada etapa carimbasse um recibo com 'comecei aqui, fui chamado por aquele recibo ali', e no fim você junta todos os recibos numa árvore só, vendo exatamente quem chamou quem e quanto tempo cada um levou.
Como funciona
O Dapper representa o caminho completo de um pedido do usuário como uma árvore de causalidade chamada trace, identificada por um ID único compartilhado por toda a árvore. Cada nó dessa árvore é um span: uma unidade de trabalho com nome legível, um identificador próprio e o identificador do seu span pai — é esse par (span id, parent id) que reconstrói as arestas de 'quem chamou quem'. Cada span registra o intervalo de tempo em que aquele trabalho ocorreu (por exemplo, uma chamada RPC específica) e pode carregar anotações adicionais que a aplicação insere voluntariamente com informações de negócio. O ponto central do design é que essa árvore não é montada por cada time escrevendo código de instrumentação manual: o Dapper instrumenta um pequeno número de bibliotecas comuns (camada de RPC, threading, controle de fluxo) usadas por praticamente todo serviço do Google, e é essa instrumentação compartilhada, e não código de aplicação, que cria e liga os spans automaticamente. Como resultado, a maior parte da árvore de um trace é montada de forma transparente; anotações manuais são um complemento opcional, e o artigo reporta que a maioria dos spans e a grande maioria dos traces continha ao menos uma anotação específica de aplicação, mostrando que os times usavam esse mecanismo voluntário quando útil, mesmo sem serem obrigados.
Na prática
Esse modelo de árvore de spans com nome, span id e parent id é exatamente o vocabulário que Zipkin, Jaeger e o padrão OpenTelemetry usam hoje para visualizar o caminho de uma requisição através de microsserviços; a lição prática do Dapper é que tracing só escala em uma organização grande se a instrumentação vier de bibliotecas compartilhadas (SDKs, middlewares de RPC), e não da disciplina de cada time em anotar manualmente seu próprio serviço.
Use em um desenho
Pratique na escola de System Design os casos que dependem deste conceito.