Em um mundo onde a comunicação digital se tornou essencial, plataformas como o Discord estão desafiando os limites da escalabilidade e performance. Recentemente, a equipe de engenharia do Discord revelou uma solução inovadora para um problema que muitos desenvolvedores enfrentam: como implementar tracing distribuído em arquiteturas baseadas em actors sem sacrificar a performance. Eles introduziram uma biblioteca chamada "Transport", que envolve o sistema de mensagens do Elixir com o contexto de rastreamento, permitindo uma visibilidade de ponta a ponta em sua infraestrutura de chat.

O Desafio do Tracing em Arquiteturas de Actors

A arquitetura de actor do Elixir, embora poderosa, apresenta um desafiu único em termos de rastreamento. Diferente dos microserviços baseados em HTTP, onde o contexto de rastreamento viaja em cabeçalhos, o Elixir passa mensagens arbitrárias entre processos sem uma camada de metadados embutida. Isso significa que o OpenTelemetry, uma solução padrão para rastreamento, não conseguia propagar o contexto entre os processos do Elixir. Para resolver esse dilema, o time do Discord identificou três requisitos cruciais: a solução precisava ser ergonômica, suportar tanto mensagens brutas quanto abstrações do GenServer, e permitir implementações sem downtime.

A Solução do Envelope

A solução encontrada foi a introdução de um primitvo chamado "Envelope", que envolve mensagens com o contexto de rastreamento. A implementação é simples, mas eficaz, consistindo em uma estrutura que contém a menssagen original e um portador de rastreamento serializado. Abaixo, um exemplo de como isso é feito:

defmodule Discord.Transport.Envelope do
  defstruct [:message, trace_carrier: []]
  def wrap_message(message) do
    %__MODULE__{
      message: message,
      trace_carrier: :otel_propagator_text_map.inject([])
    }
  end
end

Essa biblioteca substitui as funções de chamada e envio do GenServer, automaticamente envolvendo as mensagens de saída. E na recepção, uma função handle_message normaliza tanto as mensagens tradicionais quanto as novas mensagens embrulhadas no Envelope, extraindo o contexto de rastreamento quando presente.

Dicas para Implementação Eficiente

Reflexões Finais

A implementação do tracing distribuído pelo Discord em seu sistema baseado em Elixir é uma verdadeira aula de como é possível inovar sem perder a essência da arquitetura. Ao invés de tentar adaptar uma solução HTTP, eles encontraram uma maneira de manter a força de sua arquitetura enquanto ganhavam a visibilidade necessária. Isso não só melhorou a capacidade de resposta em incidentes, como também trouxe uma nova camada de insights sobre o comportamento dos usuários.

Se você trabalha com arquiteturas de actors, considere como a implementação de um sistema de rastreamento similar poderia beneficiar sua aplicação. Nunca subestime o poder de ter visibilidade — é um divisor de águas quando se trata de resolver problemas complexos.