"Qual variação da flag essa requisição recebeu?" é a pergunta que fica sem resposta em muitos retrôs de incidente, porque a avaliação da flag e o trace que mostra a falha ficam em lugares que não se referenciam. Colocar o resultado da avaliação no span da requisição fecha essa lacuna.
Aqui está exatamente o que o rollfuse faz e o que fica com você. Os SDKs avaliam as flags localmente e devolvem o resultado, com a chave da variação e o motivo; eles não gravam atributos de span sozinhos. Registrar o resultado num span são poucas linhas no seu código. O que o SDK de Node.js faz por conta própria é propagar o contexto de trace W3C nas chamadas que ele faz à API do rollfuse.
Registre a avaliação no span ativo
Com o SDK de Node.js (@rollfuse/sdk-js) e o @opentelemetry/api, leia o resultado e grave no span que estiver ativo para a requisição:
import { trace } from "@opentelemetry/api";
import { RollfuseClient } from "@rollfuse/sdk-js";
const client = new RollfuseClient({
baseUrl: "https://api.rollfuse.com",
credential: process.env.ROLLFUSE_SERVICE_CREDENTIAL!,
});
// Obrigatório: start() começa a buscar a configuração. Aguardar o fim é opcional.
void client.start();
export function isCheckoutRedesignOn(subjectKey: string): boolean {
const result = client.evaluate(subjectKey, "checkout-redesign", { fallback: false });
const span = trace.getActiveSpan();
span?.setAttribute("rollfuse.flag_key", "checkout-redesign");
span?.setAttribute("rollfuse.variation_key", result.variation_key);
span?.setAttribute("rollfuse.reason", result.reason);
return Boolean(result.value);
}
Os nomes dos atributos são escolha sua; estes são os usados no exemplo público mais abaixo. client.start() é obrigatório: é ele que começa a buscar a configuração, e sem ele toda avaliação devolve o fallback. Aguardar o fim dele é opcional; use await na inicialização se quiser a primeira configuração carregada antes de servir tráfego. O SDK de Go devolve os mesmos campos (VariationKey, Reason), então dá para gravá-los num span do mesmo jeito num serviço em Go. O SDK de Go não adiciona cabeçalhos de trace às próprias chamadas à API.
O que isso permite
- Um span lento ou com erro filtra direto pela variação. Consulte traces onde
rollfuse.flag_key = checkout-redesignerollfuse.variation_key = on, e você vê as requisições que passaram pelo código novo, sem cruzar um log separado por horário. - "Isso é código novo ou antigo" vira um filtro. Durante um incidente, a resposta está no span, e não na memória de alguém sobre o que deveria estar no ar.
- Funciona no visualizador de traces que você já usa, porque são atributos de span comuns, exportados pela sua configuração atual de OpenTelemetry. Não há exportador do rollfuse para instalar.
O que o SDK faz sozinho: contexto de trace nas próprias chamadas
O @rollfuse/sdk-js adiciona o contexto de trace W3C (traceparent) às chamadas que faz à API do rollfuse, como buscar a configuração e enviar lotes de exposição. Se o @opentelemetry/api estiver instalado e houver um span ativo naquele momento, o SDK injeta o contexto desse span; se não, gera um traceparent novo. Os lotes de exposição saem de um temporizador em segundo plano, então normalmente começam um trace próprio em vez de entrar no trace de uma requisição. A avaliação da flag em si não faz chamada de rede, então não gera span próprio.
Teste localmente
O repositório público examples-node-opentelemetry roda um serviço de checkout com flag, OpenTelemetry e Jaeger num único docker compose up, contra um substituto local da API do rollfuse, então não precisa de conta no rollfuse. Cada trace mostra o span HTTP, um span evaluate-flag com os atributos acima e o trabalho de checkout que veio depois. Trace não alimenta guardrail. Para uma métrica do OpenTelemetry disparar um rollback automático, o valor precisa chegar ao rollfuse como observações, do mesmo jeito que a página do Prometheus descreve.