ExeWatch 1.35: Nested Timing Traces, profiling hierárquico das suas operações
🇮🇹 Italiano • 🇬🇧 English • 🇩🇪 Deutsch • 🇪🇸 Español
TL;DR: O ExeWatch 1.35 apresenta os Nested Timing Traces: timings aninhados como uma árvore, no estilo de um profiler. Abra um trace com
StartTrace, execute dentro dele osStartTiming/EndTimingde sempre (inclusive em vários níveis), feche-o comEndTrace. O ExeWatch reconstrói a hierarquia em tempo de leitura e a mostra em duas visões: o waterfall de uma única execução e a árvore agregada (Calling-Context-Tree) de todas as execuções de uma operação. API uniforme em Delphi, .NET, Python, JavaScript e a DLL para C++Builder/MSVC, e total compatibilidade com os seus timings planos existentes. Experimente em exewatch.com
O ExeWatch cresce, e cresce rápido
Vamos começar com uma boa notícia: o ExeWatch está crescendo muito. Em poucos meses já somos centenas de usuários monitorando em produção suas aplicações desktop, servidor e web — e a comunidade continua aumentando semana após semana, entre desenvolvedores Delphi, C++Builder, .NET, JavaScript e Python.
O que mais nos orgulha é que cada release nasce do feedback de quem usa o ExeWatch todos os dias. A 1.35 não é exceção: os Nested Timing Traces são um dos recursos mais pedidos desde que o ExeWatch nasceu, e finalmente chegaram.
Do timing individual à árvore
Os timings sempre foram uma das ferramentas mais queridas do ExeWatch: StartTiming('LoadCustomers') … EndTiming('LoadCustomers'), e o dashboard te dá na hora a duração média, o p95, o count e a tendência de cada operação. São a forma mais rápida e direta de medir o desempenho, continuam sendo o coração do produto e funcionam exatamente como antes.
Às vezes, porém, uma operação importante é feita de muitos passos aninhados, e além do quanto demora você também quer ver como ela é por dentro. Quando GenerateInvoiceReport leva 250 ms, é bom poder descer um nível: como esses 250 ms se distribuem entre o carregamento dos dados, o rendering e talvez um loop que repete a mesma função? Os Nested Timing Traces adicionam exatamente essa dimensão — a hierarquia — por cima dos timings que você já usa, sem tirar nada.
A ideia é simples e segue o modelo dos profilers e do distributed tracing: um trace é uma árvore de spans, onde cada span é uma operação cronometrada com um pai. A novidade é que no ExeWatch cada span é simplesmente um log event de timing enriquecido com trace_id, span_id e parent_span_id. Os spans são enviados em streaming, cada um ao fechar, e a árvore é reconstruída em tempo de leitura pelo backend. Nenhuma estrutura para manter em memória no lado do cliente, nenhuma montagem em tempo de ingestão: apenas logs, como sempre.
A API: StartTrace / EndTrace
A interface adiciona apenas duas primitivas, coerentes com os StartTiming/EndTiming que você já conhece. Exemplo em Delphi:
EW.StartTrace('GenerateInvoiceReport');
try
EW.StartTiming('LoadCustomers', 'db');
// ... carrego os dados ...
EW.EndTiming('LoadCustomers');
EW.StartTiming('RenderReport', 'cpu');
EW.StartTiming('RenderRow', 'cpu'); // filho de RenderReport
// ...
EW.EndTiming('RenderRow');
EW.EndTiming('RenderReport');
finally
Total := EW.EndTrace; // duração total do trace, em ms
end;
O aninhamento você não declara: o ExeWatch o deduz. Cada SDK mantém uma pilha LIFO por thread; quando você abre um timing dentro de um trace ativo, esse timing vira automaticamente filho da operação que está no topo da pilha. Abra um StartTrace enquanto já há um trace ativo e ele degrada com elegância para um span filho (devolve o id do trace em andamento); esqueça um EndTiming e o EndTrace fecha à força os spans que ficaram abertos, marcando-os como falhos em vez de perdê-los.
A mesma API, com a mesma semântica, está disponível em Delphi nativo, .NET, Python, JavaScript e na DLL nativa que leva o ExeWatch ao C++Builder e ao Microsoft Visual C++. Um trace escrito em Python e um escrito em C++Builder produzem a mesma árvore no dashboard.
Visão 1: o waterfall de um único trace
Na lista de logs, um trace se reconhece na hora: a linha raiz é marcada com o ícone da árvore e o rótulo [TRACE]. Um clique abre o waterfall, a hierarquia exata daquela única execução.
Cada nó mostra sua duração, uma barra proporcional ao tempo total e o percentual em relação à raiz (com o detalhe “X% do pai” no tooltip). As operações repetidas no mesmo nível — um timing dentro de um loop — são agrupadas em uma única linha com um badge ×N e as estatísticas média / mín / máx / p95 sobre as execuções bem-sucedidas. A árvore é expansível e recolhível: deixe aberto o que te interessa, recolha os ramos que você não está olhando agora.
Visão 2: a árvore agregada (Calling-Context-Tree)
O waterfall te conta um run. Mas para caçar uma regressão de desempenho você precisa do panorama geral: como essa operação se comporta em todas as suas execuções? Por isso, na página de Timings, as operações que são raízes de trace abrem uma segunda visão — a árvore agregada, uma Calling-Context-Tree.
É a técnica clássica dos profilers. Cada execução de uma operação segue um caminho de chamada; a árvore agregada funde os spans por caminho, não só por nome. As execuções que seguem o mesmo caminho colapsam em um único nó — com o count acumulado de todas as execuções, loops incluídos — enquanto um caminho que diverge em alguns runs se ramifica em um nó próprio. O resultado é uma única árvore que diz, para cada nó, count, média, mínimo, máximo e p95 agregados sobre centenas de execuções. Para onde o tempo vai, em média, deixa de ser um palpite.
Compatibilidade total com versões anteriores
Uma regra que prezamos no ExeWatch: nada quebra. Os Nested Timing Traces são completamente aditivos.
- Os seus timings planos existentes continuam aparecendo como antes, tanto na lista de logs quanto nos agregados da página de Timings. Um span filho não polui as visões de nível superior: ele aparece apenas no drill-down do seu trace.
- As versões antigas dos SDKs continuam funcionando sem alterações. A API de tracing é nova, mas quem não a usa nem percebe.
- Para a DLL (C++Builder/MSVC) deixamos o upgrade o mais suave possível: uma DLL mais recente funciona até sob uma unit de import mais antiga, então atualizar a biblioteca não obriga a uma recompilação coordenada.
Para começar a usar os traces, basta atualizar o SDK na página Integration do dashboard e adicionar StartTrace/EndTrace em volta das operações que você quer perfilar. Todo o resto do seu código de logging fica como está.
Se você já usa o ExeWatch, os Nested Timing Traces já estão ativos na sua conta: atualize o SDK e comece a tracear. Se ainda não experimentou, o plano Hobby é gratuito e não exige cartão de crédito.
Links e Recursos
- Site oficial: exewatch.com
- Changelog completo: exewatch.com/ui/changelog
- Pricing e On Premise: exewatch.com/ui/pricing
- Exemplos de integração: github.com/danieleteti/ExeWatchSamples
- Contato On Premise: exewatch@bittime.it
- Artigos anteriores:
ExeWatch: Application Performance Monitoring para aplicações de servidor, desktop e web, com Artificial Intelligence Engine integrado. Criado pela bit Time Professionals.
Comments
comments powered by Disqus