Nesta página

Profiling Contínuo de CPU

Todo serviço no Guara Cloud emite amostras de profiling de CPU continuamente. A plataforma coleta tudo via eBPF e armazena no Grafana Pyroscope, e renderiza como flamegraphs interativos no dashboard. Não tem SDK para instalar, variável de ambiente para configurar nem toggle de opt-in: profiling fica sempre ligado para todo serviço que você fizer deploy e para todo serviço de catálogo que você provisionar.

Onde encontrar

São duas superfícies:

  • Página de detalhe do serviço → aba Profiling. O flamegraph de um único serviço na janela de tempo que você escolher. Use quando o foco é em um serviço só.
  • Profiling Explorer. Uma página dedicada que deixa você escolher qualquer projeto / serviço / janela de tempo na sidebar e comparar flamegraphs lado a lado. Use quando estiver investigando entre serviços ou compartilhando um profile com alguém do time.

Em ambas as superfícies você pode dar zoom em frames de stack, ver as porcentagens self e total de CPU e copiar uma URL deep-link que captura projeto, serviço, janela de tempo e estado do zoom.

Retenção por plano

O quão longe no passado você pode consultar profiles depende do plano. O picker do dashboard esconde opções fora da sua retenção.

PlanoRetenção de profiles
Hobby 24 horas
Pro 7 dias
Business 7 dias
Enterprise 7 dias

Se você pedir uma janela maior que a retenção do seu plano via API, a plataforma retorna um erro claro PROFILING_TIER_RETENTION_EXCEEDED com a janela máxima permitida.

Runtimes suportados

Profiling funciona para todo runtime que o Guara Cloud suporta. A fidelidade de símbolos (se os frames de stack ficam com nomes ou aparecem como endereços) depende de o runtime precisar de ajuda do JIT para expor seus frames. A plataforma injeta as variáveis de ambiente certas automaticamente conforme o runtime do seu serviço — você não precisa fazer nada.

RuntimeFidelidade de símbolosObservações
Node.jsCompletaInjeta NODE_OPTIONS=--perf-basic-prof-only-functions --interpreted-frames-native-stack.
JVM (Java, Kotlin, Scala)CompletaInjeta JAVA_TOOL_OPTIONS=-XX:+PreserveFramePointer.
PythonCompletaeBPF puro — sem variáveis de ambiente.
GoCompletaeBPF puro — sem variáveis de ambiente.
RustCompletaeBPF puro — sem variáveis de ambiente.
Outros runtimes nativosBest-effortFrames podem aparecer como endereços se o runtime não expuser símbolos.

Se você já estiver definindo NODE_OPTIONS ou JAVA_TOOL_OPTIONS nas variáveis de ambiente do seu serviço, a plataforma concatena ao seu valor em vez de sobrescrever.

Lendo um flamegraph

Um flamegraph é uma visão top-down de onde o seu serviço gastou CPU durante a janela selecionada:

  • Largura de um frame = quanto de CPU ele consumiu (porcentagem total).
  • Empilhamento = caller acima, callee abaixo. A folha mais larga no fundo de qualquer torre costuma ser o hot loop.
  • Self % (no hover) = tempo gasto diretamente naquela função, sem incluir os callees.
  • Total % = self mais todos os callees.

Use a caixa de busca para destacar todo frame cujo nome de função casa com uma substring — útil quando você lembra o nome de uma função mas não onde ela mora no call graph.

Clique em um frame para dar zoom (o resto do grafo colapsa para aquela subárvore). Clique no breadcrumb acima do grafo para voltar.

Do trace para o profile

Ao abrir um span de trace na visão de Traces, a ação Ver profile te leva direto ao flamegraph do mesmo serviço na janela em volta. É o caminho mais rápido para responder “a requisição foi lenta — o serviço estava CPU-bound ou esperando I/O?”.

Erros que você pode ver

Código de erroO que significa
PROFILING_NO_DATASem amostras na janela escolhida. O serviço pode ter acabado de subir, ficado idle ou crashado.
PROFILING_TIER_RETENTION_EXCEEDEDSua janela vai mais longe que a retenção do seu plano. Escolha uma janela mais curta ou faça upgrade.
PROFILING_PYROSCOPE_UNAVAILABLEO backend de profiling está temporariamente indisponível. Tente de novo em alguns instantes.

Privacidade e overhead

O profiling baseado em eBPF amostra a CPU em uma taxa fixa (tipicamente ~100 Hz por CPU) e captura apenas call stacks — nunca dados da aplicação, corpos de requisição, variáveis de ambiente ou conteúdo de memória. O overhead fica em poucos por cento de CPU por serviço no pior caso e é invisível na prática.

Pela CLI

guara services profiles get renderiza um flamegraph ASCII para a mesma janela que o dashboard mostraria, mais uma tabela top-N por self time para identificar os frames quentes de cara. Use de uma sessão de shell, de um jump-box SSH, ou jogue --json na sua própria ferramenta.

guara services profiles get
guara services profiles get --time-range 1h --top 20
guara services profiles get --from 2026-05-02T15:00:00Z --to 2026-05-02T15:15:00Z
guara services profiles get --json | jq .data.metadata

Saída de exemplo (truncada):

my-api · profile · 2026-05-02T15:00:00Z → 2026-05-02T15:15:00Z

▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇  100.0%  total
 ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇                         62.4%   handleRequest
  ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇                                        38.1%   db.query
   ▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇                                               25.8%   pg.client.send
  ▇▇▇▇▇▇▇▇                                                         12.6%   serialize
 ▇▇▇▇▇▇▇▇▇▇▇▇                                                      18.7%   gc.minorMark

Top 10 by self time
   #  SELF %   FRAME
   1   25.8%   pg.client.send
   2   18.7%   gc.minorMark
   3   12.6%   serialize
   4    8.4%   crypto.randomFillSync
   5    7.1%   net.write


Tier: Pro · retention 168h · window 15m

Quando stdout não é um TTY (piped para outro comando, redirecionado para arquivo), o flamegraph em si é omitido e apenas a tabela top-N é impressa, para legibilidade.

Veja guara services profiles get na referência da CLI para a lista completa de flags.