A Frappe app to track user interactions with your product. Events are posted
directly from the browser to Pulse (and server-side from the framework's telemetry
client), buffered through Redis, and persisted as Pulse Event records for
analysis.
You can install this app using the bench CLI:
cd $PATH_TO_YOUR_BENCH
bench get-app $URL_OF_THIS_REPO --branch develop
bench install-app pulseTo send real telemetry to a local Pulse from a bench, point the framework client at your Pulse site and give it a matching key:
# in the site that should emit events (can be the Pulse site itself)
bench --site $SITE set-config pulse_host "http://$SITE:8000"
bench --site $SITE set-config pulse_api_key "asdf1234"pulse_host is where the browser both loads the client
(/assets/pulse/js/pulse_client.js) and posts events; pulse_api_key is sent with
each event and must match Pulse Settings → API Key. On a local bench
is_enabled() is off (dev mode / not Frappe Cloud); pulse.e2e.setup flips
pulse_force_enabled, syncs the key into Pulse Settings, and points the client at
the local host for you:
bench --site $SITE execute pulse.e2e.setupThen rebuild assets so Desk picks up the telemetry provider, trigger activity
(create a doc, navigate Desk), drain the queues, and watch rows land — see the
quick check below. pulse_force_enabled is test-only; never set it in
production.
bench build --app frappeThe local setup is same-origin (the browser and Pulse share $SITE), so no CORS
is involved. A real cross-origin setup (browser on a product site posting to a
separate Pulse host) needs allow_cors set on the Pulse site, so nginx adds the
Access-Control-Allow-Origin header on /assets and the ingest response.
bench --site $SITE set-config allow_cors "*"An end-to-end test proves the full pipeline across the browser client and this app. The browser posts directly to Pulse (no framework relay):
browser frappe.telemetry.capture() [pulse_client.js from /assets/pulse/]
-> POST bulk_ingest -> Pulse Redis stream
-> consume_pulse_events() -> Pulse Event row
Run it against a site that has both frappe and pulse installed (e.g. one with
pulse_api_key / pulse_host pointing back at itself):
bench --site $SITE run-ui-tests pulse --headless \
--spec cypress/integration/pulse_telemetry.jsThe test calls pulse.e2e.setup itself, so no manual prep is needed.
Quick server-only check, no browser:
bench --site $SITE execute pulse.e2e.setup
bench --site $SITE execute frappe.utils.telemetry.pulse.client.capture \
--kwargs "{'event_name':'cypress_pulse_e2e','app':'frappe'}"
bench --site $SITE execute pulse.e2e.drain
bench --site $SITE execute pulse.e2e.count # -> count=1
bench --site $SITE execute pulse.e2e.cleanupCI runs the e2e on every PR (.github/workflows/e2e.yml). The framework-side
telemetry changes (boot config + direct-mode provider in pulse.js) live on frappe's
develop branch, which CI installs via FRAPPE_BRANCH (override with
workflow_dispatch to test against another branch).
This app uses pre-commit for code formatting and linting. Please install pre-commit and enable it for this repository:
cd apps/pulse
pre-commit installPre-commit is configured to use the following tools for checking and formatting your code:
- ruff
- eslint
- prettier
- pyupgrade
agpl-3.0