aboutsummaryrefslogtreecommitdiffstats
path: root/src/trace.js
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
commitd80640d01eeb84907e36ff4af33add9081eda17c (patch)
tree27698b34e06e28d111c2196700015d9c82f78274 /src/trace.js
downloadwa-cli-main.tar.gz
wa-cli-main.zip
wa-cli: WhatsApp from the terminal, with a neomutt Maildir bridgeHEADmain
Diffstat (limited to 'src/trace.js')
-rw-r--r--src/trace.js79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/trace.js b/src/trace.js
new file mode 100644
index 0000000..8717ff1
--- /dev/null
+++ b/src/trace.js
@@ -0,0 +1,79 @@
+// Daemon diagnostic traces (WA_CLI_TRACE=1 or "trace": true in config.json).
+// Logs: CDP/evaluate calls still pending after >15 s, exceptions inside functions exposed
+// to the page (puppeteer swallows them), navigations and client events.
+// Useful to see where whatsapp-web.js hangs when it never reaches `ready`.
+
+import { createRequire } from 'node:module';
+
+const require = createRequire(import.meta.url);
+const QUIET = new Set(['loading_screen', 'message', 'message_create', 'message_ack', 'unread_count', 'media_uploaded']);
+
+export function enableTrace(log) {
+ const { CdpPage } = require('puppeteer-core/lib/cjs/puppeteer/cdp/Page.js');
+ const { CdpCDPSession } = require('puppeteer-core/lib/cjs/puppeteer/cdp/CdpSession.js');
+ const wweb = require('whatsapp-web.js');
+ const t = (...a) => log('trace:', ...a);
+
+ const pending = new Map();
+ let seq = 0;
+ const track = (desc, p) => {
+ const id = ++seq;
+ pending.set(id, { desc, start: Date.now() });
+ const done = () => pending.delete(id);
+ p.then(done, (e) => {
+ done();
+ t('error', desc, String(e?.message ?? e).slice(0, 200));
+ });
+ return p;
+ };
+ setInterval(() => {
+ for (const p of pending.values()) {
+ const s = Math.round((Date.now() - p.start) / 1000);
+ if (s >= 15 && s % 15 === 0) t(`pendiente ${s}s:`, p.desc);
+ }
+ }, 1000).unref();
+
+ const send = CdpCDPSession.prototype.send;
+ CdpCDPSession.prototype.send = function (method, ...args) {
+ return track(`cdp ${method}`, send.call(this, method, ...args));
+ };
+
+ const expose = CdpPage.prototype.exposeFunction;
+ CdpPage.prototype.exposeFunction = function (name, fn) {
+ const wrapped = async (...args) => {
+ try {
+ return await fn(...args);
+ } catch (e) {
+ t(`exception in ${name}:`, String(e?.stack ?? e).split('\n').slice(0, 4).join(' | '));
+ throw e;
+ }
+ };
+ return track(`exposeFunction(${name})`, expose.call(this, name, wrapped));
+ };
+
+ const emit = wweb.Client.prototype.emit;
+ wweb.Client.prototype.emit = function (event, ...args) {
+ if (!QUIET.has(event)) t('evento', event, event === 'disconnected' || event === 'change_state' ? args[0] : '');
+ return emit.call(this, event, ...args);
+ };
+
+ const init = wweb.Client.prototype.initialize;
+ wweb.Client.prototype.initialize = function (...args) {
+ const iv = setInterval(() => {
+ if (!this.pupPage) return;
+ clearInterval(iv);
+ const page = this.pupPage;
+ page.on('framenavigated', (f) => t('framenavigated', f === page.mainFrame() ? 'main' : 'iframe', f.url().slice(0, 60)));
+ page.on('load', () => t('load'));
+ page.on('pageerror', (e) => t('pageerror', String(e?.message ?? e).slice(0, 150)));
+ }, 20);
+ return init.apply(this, args);
+ };
+
+ const inject = wweb.Client.prototype.inject;
+ wweb.Client.prototype.inject = function (...args) {
+ t('inject()');
+ return track('inject()', inject.apply(this, args));
+ };
+ if (inject.waCompat) wweb.Client.prototype.inject.waCompat = true;
+}