Copia questo codice: monitoraggio ExeWatch per Delphi, .NET, C++ e altro
🇬🇧 English • 🇩🇪 Deutsch • 🇪🇸 Español • 🇧🇷 Português
ExeWatch: monitoraggio in tempo reale per applicazioni Delphi, C++Builder, .NET, JavaScript e Python, con motore AI integrato e piano Hobby gratuito.
TL;DR: Il repository ExeWatch Samples è un insieme di progetti pronti all’uso che mostrano come integrare ExeWatch in applicazioni reali: Delphi (VCL, FMX, Android, WebBroker, DMVCFramework, runtime package, webhook), .NET (Console, Windows Forms, Windows Service), JavaScript nel browser, e C++Builder / MSVC / Python tramite la DLL nativa. Ogni esempio esercita una porzione dell’SDK, così copi il pattern adatto alla tua app. Una API key, piano Hobby gratuito, e i tuoi eventi compaiono nella dashboard in pochi secondi.
ExeWatch cresce, e la community ci costruisce sopra
ExeWatch continua a crescere, in fretta. In pochi mesi ha raggiunto centinaia di sviluppatori registrati che oggi monitorano in produzione software scritto in Delphi, C++Builder, .NET, JavaScript e Python: dalle applicazioni desktop ai servizi Windows, dalle API REST alle web application complete.
Quello che usano per primo dice molto sul perché poi restano:
- Cattura automatica delle eccezioni - gli errori non gestiti vengono intercettati e riportati, con classe, messaggio e stack.
- Trail di breadcrumb - la sequenza esatta di azioni che ha portato a un errore, allegata automaticamente al guasto.
- Timing delle performance con Avg / Min / Max / P95 - misuri qualsiasi operazione e ne osservi l’andamento nella dashboard.
- Nested timing traces - waterfall in stile profiler e un albero aggregato Calling-Context-Tree, per vedere dove se ne va davvero il tempo.
- Contatori e gauge - metriche di business e di runtime accanto ai log.
- Intelligence su hardware e device - CPU, RAM, disco, OS, monitor, dettagli dei dispositivi mobili.
- Tracciamento multi-cliente - filtri ogni log per id cliente.
- Alert via email e su timing più webhook - vieni avvisato, o piloti la tua automazione, quando qualcosa va storto o rallenta.
- Un motore AI integrato che aiuta a dare senso a tutto questo.
Una funzionalità merita una menzione speciale: i Nested Timing Traces, tra le aggiunte più richieste e quella su cui riceviamo più riscontri positivi. Trasforma una lista piatta di timing in un waterfall in stile profiler che mostra esattamente dove se ne va il tempo, con i loop accorpati e media/min/max/p95 per ogni nodo. Ogni SDK del repository include una demo di nested trace pronta all’uso (GenerateInvoiceReport), così puoi produrre un albero come questo dalla tua app in pochi minuti:
Se vuoi la storia completa su come i trace vengono costruiti e visualizzati, leggi l’articolo dedicato: ExeWatch 1.35: Nested Timing Traces.
Il modo più veloce per capire come si traduce tutto questo nel tuo codice è il repository di esempi. Vediamolo insieme.
Perché questi esempi contano: versioni reali, linguaggi reali
Questo repository non è solo una vetrina di marketing. Esiste perché le domande sono reali. Solo nelle ultime settimane, un cliente mi ha chiesto di aggiungere ExeWatch a un’applicazione Delphi 6, un altro a un progetto C++Builder 10, e un altro ancora voleva pilotarlo da un linguaggio che non è affatto nella lista solita.
Ognuna di queste richieste ha una risposta qui dentro, ed è esattamente questo il punto: gli esempi sono il modo più rapido per capire quale SDK usare per quale ambiente, e come.
- Delphi moderno (XE8 e successivi) usa l’SDK Pascal nativo (
ExeWatchSDKv1.pas+ l’hook VCL o FMX): gli esempi VCL, FMX, Android, WebBroker e DMVCFramework seguono tutti questa strada. - Delphi legacy (fino a Delphi 6/7) e qualsiasi versione pre-XE8 non possono compilare la unit moderna, quindi parlano con la DLL nativa tramite la unit di import Pascal
ExeWatchSDKv1Imports.pasinDLLSDKCommons/. Stesse chiamate, stessa dashboard, solo collegate alla DLL invece che compilate dentro. - C++Builder (vecchio e nuovo) carica la stessa DLL dinamicamente: l’esempio
CPPBuilderWithDLLSDK/compila senza modifiche sotto bcc32, bcc64 e bcc64x, così un progetto C++Builder 10 e uno 13 usano codice identico. - Altri linguaggi consumano la DLL tramite la sua ABI Windows standard: gli esempi MSVC e Python ctypes dimostrano il pattern, che poi si porta su Rust, Go, MinGW, Clang e oltre.
Così, quando qualcuno chiede “posso mettere ExeWatch su questo vecchio compilatore / quel linguaggio insolito?”, la risposta onesta è quasi sempre “sì, ed ecco l’esempio che ti mostra come”.
Prima di iniziare: una API key, niente carta di credito
Ogni esempio richiede una API key valida. Registrati su exewatch.com, crea un’applicazione nella dashboard e copia la sua key (il prefisso dipende dalla piattaforma di destinazione: ew_win_ Windows, ew_lin_ Linux, ew_mac_ macOS, ew_and_ Android, ew_ios_ iOS, ew_web_ browser). Il piano Hobby gratuito non chiede carta di credito e include un’applicazione, 10.000 eventi al mese, 7 giorni di retention e due alert: più che sufficienti per eseguire tutto.
Poi il ciclo è sempre lo stesso: apri il progetto, incolli la tua key dove c’è il placeholder, compili, esegui, e guardi gli eventi arrivare nella dashboard in tempo reale.
Client desktop e mobile
Sono gli esempi “client sulla macchina di qualcun altro”: app con interfaccia grafica dove la cattura delle eccezioni e i breadcrumb contano di più, perché di solito il crash non lo riproduci in locale.
Delphi VCL (DelphiVCL/) è il punto di partenza canonico. Una form desktop Windows con un pulsante per ogni funzionalità: i cinque livelli di log, timing, breadcrumb-poi-errore, identità utente, tag, contatori e gauge, più la cattura automatica delle eccezioni VCL via ExeWatchSDKv1.VCL. I log vengono persistiti su disco prima dell’invio, così non si perde nulla se l’app crasha. Usalo quando sviluppi software desktop Windows classico in Delphi e vuoi la strada più breve da zero ai dati.
uses ExeWatchSDKv1, ExeWatchSDKv1.VCL; // hook VCL = cattura automatica eccezioni GUI
InitializeExeWatch(EXEWATCH_API_KEY, 'SampleCustomer');
EW.Info('User logged in', 'auth');
Delphi FMX (DelphiFMX/) rispecchia l’esempio VCL funzionalità per funzionalità, ma su FireMonkey, quindi può mirare a Windows, macOS, Linux, iOS e Android. L’unica vera differenza è la clausola uses: ExeWatchSDKv1.FMX al posto dell’hook VCL. Usalo quando distribuisci un’app FireMonkey multipiattaforma.
uses ExeWatchSDKv1, ExeWatchSDKv1.FMX; // hook FMX al posto di quello VCL
InitializeExeWatch(EXEWATCH_API_KEY, 'SampleCustomer');
EW.Info('User logged in', 'auth');
Delphi Android (DelphiAndroid/) è l’SDK FMX puntato dritto su un telefono. Una UI stretta e scrollabile costruita via codice esercita ogni entry point, incluso l’uso da thread in background e il flush, e affronta le specificità mobile: device info in versione Android, cattura di un’eccezione non gestita prima che il processo venga distrutto, e prova di thread-safety fuori dal thread UI. Usalo quando sviluppi per Android e vuoi provare l’intera API su un dispositivo reale o emulatore.
uses ExeWatchSDKv1, ExeWatchSDKv1.FMX;
InitializeExeWatch(EXEWATCH_API_KEY, 'AndroidSample'); // key Android: ew_and_
EW.Info('Info message from Android', 'test');
.NET Windows Forms (DotNetWindowsForms/) è la controparte C#: una GUI a tab dove incolli la API key a runtime (niente ricompilazione) ed esplori logging, timing annidati e paralleli, device info, metriche e upgrade di versione simulati. Installa ExeWatch.WinForms per catturare automaticamente Application.ThreadException. Usalo quando la tua app desktop è in WinForms.
ExeWatchWinForms.Install(); // cattura Application.ThreadException, prima di Application.Run()
ExeWatchSdk.Initialize(new ExeWatchConfig(apiKey, customerId));
EW.Info("User logged in", "auth");
Server, servizi e web app
Codice long-running, headless o lato server, dove timing, contatori e contesto strutturato sugli errori diventano visibilità operativa.
Delphi WebBroker (DelphiWebBroker/) è un piccolo server REST che avvolge ogni richiesta in un unico helper HandleRequest: incrementa un contatore di richieste, aggiunge un breadcrumb, avvia un timing, esegue l’handler, poi registra successo o fallimento (e in caso di errore lo conta, logga l’eccezione e restituisce HTTP 500). Sei endpoint demo, incluso un delay ?ms= per generare risposte lente. Usalo quando hai un servizio WebBroker e vuoi monitoraggio a livello di richiesta con un solo wrapper.
InitializeExeWatch(TExeWatchConfig.Create(EXEWATCH_API_KEY, 'demo_customer'));
EW.SetTag('app', 'WebBrokerSample');
// dentro il wrapper per-richiesta:
EW.IncrementCounter('http.requests', 1);
EW.StartTiming(Endpoint);
try
Handler;
EW.EndTiming(Endpoint, nil, True); // successo
except
on E: Exception do
EW.EndTiming(Endpoint, nil, False); // fallimento
end;
Delphi DMVCFramework (DelphiDMVCFramework/) è l’esempio lato server più completo: una web app vera con TemplatePro e HTMX, CRUD di persone con ricerca live e import batch, report pesanti con timing annidati, servizi esterni simulati con modalità di fallimento realistiche (timeout dei pagamenti, rate limit 429, errori 502), extra data strutturati, breadcrumb, contatori e gauge periodici. Il punto forte è quanto poco serve: tre righe nel .dpr e nessuna modifica ai controller. Instradi l’output di LoggerPro di DMVCFramework verso ExeWatch con un appender a callback, chiami InitializeExeWatch, e colleghi al logger il Profiler integrato del framework. Da lì ogni richiesta viene loggata e cronometrata gratis. Usalo quando sviluppi API o web app con DMVCFramework e vuoi visibilità profonda con quasi zero codice.
// 1. instrada l'output di LoggerPro di DMVCFramework verso ExeWatch
SetDefaultLogger(CreateLogBuilderWithDefaultConfiguration.WriteToCallback
.WithCallback(procedure(const ALogItem: TLogItem; const AFormattedMessage: string)
begin
if ExeWatchIsInitialized and (ALogItem.LogType > TLogType.Debug) then
EW.Log(TEWLogLevel(Ord(ALogItem.LogType)), ALogItem.LogMessage,
ALogItem.LogTag, ALogItem.TimeStamp, ALogItem.ThreadID);
end).Done.Build);
// 2. inizializza, poi 3. collega il profiler integrato al logger
InitializeExeWatch(TExeWatchConfig.Create(EXEWATCH_API_KEY, 'dmvc_sample_customer'));
Profiler.ProfileLogger := Log; // ogni action cronometrata, senza toccare i controller
Profiler.WarningThreshold := 500; // avvisa se un'action supera i 500 ms
Ricevitore WebHook Delphi (DelphiWebHookSample/) ribalta la relazione: invece di inviare dati a ExeWatch, riceve i webhook degli alert di ExeWatch. Un controller DMVCFramework valida il token del webhook ed elabora il payload dell’alert, e un endpoint trace-demo di accompagnamento emette su richiesta un nested timing trace. Usalo quando vuoi che gli alert attivino la tua automazione (notifiche in chat, ticketing, auto-remediation) e non solo l’email.
// valida il secret condiviso, poi agisci sul payload dell'alert
if Context.Request.Headers['X-ExeWatch-Token'] <> EXEWATCH_WEBHOOK_TOKEN then
Exit(UnauthorizedResponse('Invalid token'));
AlertType := Payload.S['alert_type']; // 'log_level', 'timing', 'health_critical'...
LogI('ExeWatch [%s] %s: %s', [AlertType, Payload.S['app_name'], Payload.S['message']]);
Result := OKResponse('Webhook received');
.NET Windows Service (DotNetWindowsService/) è un Worker Service con un ciclo di elaborazione ogni 10 secondi. Mostra il pattern consigliato per i servizi long-running: inizializzazione in StartAsync, ogni ciclo avvolto in un timing esterno con sotto-timing annidati, la convenzione del timing con try/catch così che i cicli falliti vengano segnati come falliti senza far crashare il servizio, contatori e gauge, e flush in StopAsync. Può girare come console app o essere installato con sc create. Usalo quando gestisci servizi in background o demoni.
// StartAsync - una sola volta all'avvio del servizio
ExeWatchSdk.Initialize(new ExeWatchConfig(ApiKey, CustomerId) { AppVersion = "1.0.0-service-demo" });
EW.SetTag("service_name", "ExeWatchDemoService");
EW.Info("Service started", "lifecycle");
// ogni ciclo - cronometrato, i fallimenti segnati senza far crashare il servizio
EW.StartTiming("process_cycle", "worker");
try { /* ... lavoro ... */ EW.EndTiming("process_cycle"); }
catch (Exception ex) {
EW.EndTiming("process_cycle", new Dictionary<string, object> { ["error"] = ex.Message }, false);
}
.NET Console (DotNetConsole/) percorre l’intera superficie dell’SDK in sequenza, incluse 20 iterazioni cronometrate con fallimenti casuali, così la dashboard mostra subito Avg / Min / Max / P95 e success rate realistici. Usalo quando vuoi uno smoke test da 60 secondi dell’SDK .NET, o un job CLI/batch da strumentare.
var config = new ExeWatchConfig(ApiKey, CustomerId) { AppVersion = "1.0.0-console-demo" };
ExeWatchSdk.Initialize(config);
EW.SetTag("environment", "development");
EW.Info("Configuration loaded successfully", "config");
Nel browser
JavaScript (JS/) è un singolo index.html: niente npm, niente step di build. Imposti window.ewConfig con la tua key ew_web_, carichi l’SDK dal CDN, e clicchi i pulsanti per logging, timing, breadcrumb-poi-errore, identità utente, tag e metriche. Usalo quando vuoi tracciare errori e performance front-end su una pagina web semplice o dentro un sito esistente.
<script>
window.ewConfig = { apiKey: 'ew_web_...', customerId: 'SampleCustomer', appVersion: '1.0.0' };
</script>
<script src="https://exewatch.com/static/js/exewatch.v1.min.js"></script>
<script>
ew.info('User signed in', 'auth'); // il globale 'ew' è pronto dopo il caricamento dell'SDK
</script>
C, C++ e qualsiasi linguaggio capace di chiamare una DLL
ExeWatch include una DLL nativa che espone una ABI Windows volutamente banale: extern "C" + __stdcall + wchar_t* + #pragma pack(1). Questo la rende utilizzabile da quasi qualunque cosa. Tutti questi esempi la caricano dinamicamente con LoadLibrary + GetProcAddress, il che evita il classico mismatch tra import library .lib e .a e permette all’app di avviarsi pulita anche quando la DLL manca.
C++Builder (CPPBuilderWithDLLSDK/) è un’app VCL che pilota la DLL tramite la coppia condivisa ExeWatchSDKv1.h + ExeWatchSDKv1.dynload.c. Un solo #define EW_DYNAMIC_LOAD trasforma ogni ew_* in un puntatore a funzione, e lo stesso sorgente compila sotto bcc32, bcc64 e bcc64x. Usalo quando lavori in C++Builder e vuoi evitare battaglie col linker.
#define EW_DYNAMIC_LOAD // ogni ew_* diventa un puntatore a funzione
#include "ExeWatchSDKv1.h"
if (ew_LoadSDK() != EW_OK) { /* DLL mancante: mostra un messaggio chiaro */ }
ew_Initialize(EXEWATCH_API_KEY, L"Sample C++ Customer", L"");
ew_Info(L"This is an INFO message", L"sample");
Microsoft Visual C++ (MSVCWithDLLSDK/) dimostra che il DLL SDK non ha limiti né dipendenze e può essere usato dappertutto e da chiunque, anche senza nulla dell’ecosistema Embarcadero: una console app in puro cl.exe, con un run_msvc.cmd che trova vcvars64.bat, compila ed esegue. Percorre la superficie comune (init, utente, tag, breadcrumb, timing, contatore, gauge, errore con breadcrumb auto-allegati, flush, shutdown). Usalo quando il tuo codebase è MSVC, o vuoi semplicemente un quickstart autonomo.
#define EW_DYNAMIC_LOAD
#include "ExeWatchSDKv1.h"
ew_LoadSDK();
ew_Initialize(EXEWATCH_API_KEY, CUSTOMER_ID, APP_VERSION);
ew_SetTag(L"environment", L"dev");
ew_Info(L"Sample app started", L"startup");
La DLL da altri linguaggi (SpecificScenarios/DllFromOtherLanguages/) è l’angolo della portabilità dimostrata. Uno smoke test in puro Python ctypes valida tutti e cinque gli assi della ABI (calling convention, nomi non decorati, marshalling UTF-16, packing delle struct e ABI delle callback) senza alcuna impronta Embarcadero. Il README è esplicito: per un’app Python vera dovresti usare il modulo dell’SDK Python nativo, che scarichi dalla pagina Integration della dashboard esattamente come scarichi le unit Delphi (non è ancora su PyPI, quindi niente pip install); questo esempio esiste come riferimento di porting per Rust, Go, MinGW, Clang e altri runtime capaci di FFI. Usalo quando devi chiamare ExeWatch da un toolchain insolito e vuoi un template affidabile.
dll = ctypes.WinDLL(dll_path) # ABI stdcall, nomi non decorati
cfg = TEWDLLConfig(); cfg.StructSize = sizeof(TEWDLLConfig)
cfg.ApiKey = EXEWATCH_API_KEY; cfg.CustomerId = CUSTOMER_ID; cfg.SampleRate = 1.0
dll.ew_InitializeEx(byref(cfg))
dll.ew_Info('Hello from Python ctypes', 'smoke')
Architettura e scenari how-to mirati
L’ultimo gruppo risponde a domande specifiche che emergono una volta che le basi funzionano.
Runtime package (DelphiVCLWithPackages/) dimostra che ExeWatch funziona con i BPL Delphi caricati dinamicamente via LoadPackage. Il trucco è compilare l’SDK in un package a sé (ExeWatchSDKPkg.bpl) così che l’istanza globale EW, i breadcrumb, i tag e l’identità utente siano davvero condivisi tra l’EXE host e ogni BPL modulo. Due moduli demo (Customers, Orders) loggano, cronometrano e catturano errori usando esattamente la stessa API di un’app normale. Usalo quando hai un’applicazione Delphi modulare, in stile plugin.
// HostApp: inizializza una volta; l'SDK vive in ExeWatchSDKPkg.bpl, condiviso con ogni modulo
InitializeExeWatch(TExeWatchConfig.Create(APP_API_KEY, APP_CUSTOMER_ID));
EW.SetTag('app_type', 'runtime_packages');
// dentro un BPL modulo caricato dinamicamente - stesso EW globale, nessun setup extra
EW.Info('Customer added: ' + CustomerName, 'customers');
Uso dei breadcrumb (SpecificScenarios/BreadcrumbsUsage/) chiarisce in un solo progetto le tre domande più comuni sui breadcrumb: distribuiscili dove accadono le azioni (non accorparli), le eccezioni non gestite li allegano automaticamente mentre quelle catturate richiedono la tua chiamata a EW.Error, e solo i log Error e Fatal portano i breadcrumb (Info / Warning / Debug no). Quattro pulsanti rendono ogni regola visibile nella dashboard. Usalo quando vuoi azzeccare i breadcrumb la prima volta.
EW.AddBreadcrumb(btClick, 'ui', 'Clicked "Save" button');
try
FakeSaveToDatabase; // solleva un'eccezione
except
on E: Exception do
EW.ErrorWithException(E, 'settings'); // i breadcrumb si allegano a questo Error
end;
Device info personalizzata iniziale (SpecificScenarios/InitialCustomDeviceInfo/) risponde a un problema sottile di avvio: come alleghi tag e metadati d’ambiente (sessione RDP, Terminal Server, modalità desktop) al primo evento in assoluto, quello emesso durante l’inizializzazione? La risposta sono due campi di configurazione, GlobalTags per i dati su cui filtri i log e InitialCustomDeviceInfo per i dettagli che descrivono il device. Usalo quando ti serve il contesto presente fin dalla prima riga di log.
Config := TExeWatchConfig.Create(EXEWATCH_API_KEY, 'SampleCustomer');
Config.GlobalTags := [TPair<string, string>.Create('session_type', SessionType)];
Config.InitialCustomDeviceInfo := [
TPair<string, string>.Create('screen_res', DetectScreenResolution),
TPair<string, string>.Create('color_depth', DetectColorDepth)];
InitializeExeWatch(Config); // i tag presenti già dal primo evento
Integrazione madExcept (SpecificScenarios/madExceptIntegration/) è per chi usa già madExcept. Una singola unit ponte registra una callback di madExcept e inoltra ogni eccezione a ExeWatch con lo stack già simbolicato di madExcept (nomi delle unit e numeri di riga) invece degli indirizzi grezzi che l’SDK catturerebbe in una build di release. Mostra anche l’equivalente per EurekaLog. Usalo quando vuoi stack leggibili e ricercabili nella dashboard e paghi già la simbolicazione al momento del link.
procedure ExeWatchMadExceptHandler(const ExceptIntf: IMEException; var Handled: Boolean);
var ExtraData: TJSONObject;
begin
ExtraData := TJSONObject.Create;
ExtraData.AddPair('stack_trace', ExceptIntf.BugReport); // stack risolto da madExcept
EW.Log(llError, ExceptIntf.ExceptMessage, 'exception', ExtraData);
end;
initialization
RegisterExceptionHandler(ExeWatchMadExceptHandler, stDontSync);
Una sola API, tanti runtime
Il motivo per cui un tour come questo resta breve è che l’API è volutamente la stessa ovunque. Initialize, Info / Warning / Error, AddBreadcrumb, StartTiming / EndTiming, SetUser, SetTag, IncrementCounter / RecordGauge, e la cattura automatica delle eccezioni: la grafia cambia un po’ tra Delphi, C#, JavaScript e la DLL C, ma i concetti e la dashboard sono identici. La impari in un esempio e la conosci in tutti.
Clona il repo, scegli il progetto più vicino al tuo stack, inserisci la tua key, e avrai dati reali davanti agli occhi in un paio di minuti.
Link e risorse
- Repository degli esempi: github.com/danieleteti/ExeWatchSamples
- Sito ufficiale: exewatch.com
- Documentazione: exewatch.com/ui/docs
- Prezzi & On Premise: exewatch.com/ui/pricing
- Changelog: exewatch.com/ui/changelog
- Contatto On Premise: exewatch@bittime.it
- Articolo correlato: ExeWatch 1.35: Nested Timing Traces, il profiling gerarchico delle operazioni
ExeWatch: Application Performance Monitoring per applicazioni server, desktop e web, con un motore di Intelligenza Artificiale integrato. Creato da bit Time Professionals.
Comments
comments powered by Disqus