Replaced silent error handling (.catch(() => {})) with structured logging in webhook delivery and retry paths. This ensures webhook failures are observable and debuggable.
Before:
attemptDelivery(delivery.id, sub.url, sub.secret, payload, 1).catch(() => {});After:
attemptDelivery(delivery.id, sub.url, sub.secret, payload, 1).catch((err) => {
logger.error('Webhook dispatch failed', { err, deliveryId: delivery.id, url: sub.url });
});Before:
).catch(() => {}),After:
).catch((err) => {
logger.error('Webhook retry failed', {
err,
deliveryId: d.id,
url: d.subscription.url,
});
}),import { createLogger } from '../lib/logger';const logger = createLogger('WebhooksController');Before:
dispatchEvent(delivery.eventType as any, JSON.parse(delivery.payload)).catch(() => {});After:
dispatchEvent(delivery.eventType as any, JSON.parse(delivery.payload)).catch((err) => {
logger.error('Webhook replay dispatch failed', { err, deliveryId: delivery.id });
});- Failed webhook deliveries are now logged with structured metadata (error, deliveryId, URL)
- Logs are captured by the application's logging pipeline (Winston, Elasticsearch, OpenTelemetry)
- On-call engineers receive alerts when webhook subsystem is degraded
- Error messages and stack traces are preserved for investigation
- Delivery IDs and URLs are included for correlation with database records
- Elasticsearch/Kibana can now index and search webhook failures
- No change to retry logic or persistence (already handled by
attemptDelivery()) - Errors are logged but do not block the async flow
- Existing BullMQ retry infrastructure remains intact
All changes maintain backward compatibility:
- Webhook delivery behavior unchanged
- Retry scheduling unchanged
- Only adds logging on error paths
- No new dependencies required