Local, offline Java APM with no external service.
PULSE attaches as a -javaagent when a Java/Spring Boot application starts, collects SQL/HTTP/JVM metrics, and exposes a simple local web UI.
- Zero external collector
- Single agent JAR
- 100% local execution
- SQL collection:
- JDBC query instrumentation (
Statement/PreparedStatement) - SQL type, duration, errors, Spring context
- SQL <-> HTTP endpoint correlation (
traceId, thread+time fallback)
- JDBC query instrumentation (
- HTTP collection:
- endpoint transactions (method + path)
- status, duration, errors
- sampled stack hotspots + call stacks
- request metadata: query params, headers (sensitive filtering), auth (masked), body (best effort)
- JVM collection:
- heap, process CPU, threads, GC count, GC pause
- average HTTP latency and p95
- Built-in local UI:
- Endpoint tab
- Database tab
- JVM tab
- Java 17 to 25
- Maven (or
./mvnw) - Target application: Spring Boot
>= 3.0(Jakarta Servlet only), started with-javaagent
./mvnw clean packageGenerated agent JAR:
target/pulse-1.0.0-agent.jar
cd /path/to/pulse
./mvnw clean packagejava \
-javaagent:/path/to/pulse/target/pulse-1.0.0-agent.jar=port=17321 \
-jar /path/to/your-app.jarFormat:
-javaagent:/path/pulse-agent.jar=key=value,key=value,...
Supported keys:
port(default17321)bind(default127.0.0.1)retentionMs(default900000, i.e. 15 min)slowMs(slow SQL threshold, default300)slowHttpMs(slow HTTP threshold, default500)sampleRate(0.0 to 1.0, default1.0)appName(monitored app name, fallback if auto-detection fails)
Important:
- If the port is already in use, PULSE fails fast with an explicit message.
- PULSE does not require any database to run.
Local base URL: http://127.0.0.1:<port>
GET /api/sql/snapshotGET /api/sql/configGET /api/http/snapshotGET /api/http/trace/{id}GET /api/jvm/snapshotGET /(UI)
- Sensitive headers excluded:
Authorization(masked value inauth)Proxy-AuthorizationCookieSet-Cookie
- Request body:
- best-effort capture (especially JSON)
- truncated to limit size
- binary content ignored
- SQL:
- bind values are intentionally not captured
- Agent bootstrap:
src/main/java/com/pulse/agent/PulseAgent.java
- Instrumentation:
- HTTP:
src/main/java/com/pulse/agent/instrumentation/HttpTransactionSupport.java - SQL:
src/main/java/com/pulse/agent/instrumentation/StatementExecutionAdvice.java
- HTTP:
- Runtime/metrics:
src/main/java/com/pulse/app/core/PulseRuntime.javasrc/main/java/com/pulse/app/core/SqlCollectorService.javasrc/main/java/com/pulse/app/core/HttpPerfCollectorService.javasrc/main/java/com/pulse/app/core/JvmMetricsService.java
- UI:
src/main/resources/static/index.html
Run tests:
./mvnw testVerify packaging:
./mvnw package- Ensure the target app is started with
-javaagent. - Fully restart the target JVM after changing the agent.
- Ensure the PULSE port is reachable.
- Capture is best effort and is not guaranteed for all flows/proxies/filters.
- Ensure the request goes through Spring MVC.
- Ensure content type is text/JSON (not binary).
- Change
portin-javaagentargs, for example:port=17322
Issues and PRs are welcome.
Recommended guidelines:
- Keep the project free of dependencies
- Preserve local startup simplicity
- Add/update tests for each instrumentation change
Apache License 2.0. See LICENSE.
