Custom probes
A resource document of the JProfiler MCP server. Back to the tool and resource reference.
For agent consumption, this page is also available as raw Markdown.
Content of the MCP resource jprofiler://probes/custom of the JProfiler MCP server, see the tool and resource reference for the full list of tools and resources.
Custom probes are Java classes shipped with the profiled application that JProfiler records like built-in
probes: aggregated payload hot spots, call tree splitting, optionally individual events, control objects
and telemetries. This server records and queries them as custom:<fully qualified probe class name>
subsystems - the probe class name is the probe id in recordingConfig.subsystems, in probeConfig, in
the subsystem argument of the query datasets and in the customProbes section of check_status.
When not to write a custom probe
A custom probe is code that has to be compiled and deployed with the profiled application. Cheaper options first:
- The built-in probes cover common technologies (jdbc, jpa, http_server, http_client, mongo_db, kafka, files, sockets, processes and more) and need no code at all.
- To split the CPU call tree by a runtime value such as a URL or a tenant id, a
recordingConfig.advanced.splitMethodsscript is enough. - To turn selected methods into separately measured groups, use
recordingConfig.advanced.complexityMethods. - To record payload hot spots and events of application-specific methods without any deployment,
define a script probe in
recordingConfig.advanced.scriptProbes: the script text is compiled by this server and pushed to the profiled JVM, also on attach.
Write a custom probe when script probes are not enough: they cannot split the call tree, access return values or create control objects, custom event types or telemetries.
Embedded or injected
- Embedded probe: the application calls the probe API itself, for code you own. Extend
PayloadProbeorSplitProbefromcom.jprofiler.api.probe.embeddedand bracket the measured operations with the staticPayload/Splitmethods. Embedded probes self-register on the first API call and need no further deployment step. API reference:jprofiler://api/probe-embedded. - Injected probe: bytecode instrumentation adds the measurement to methods of classes you may not
own. Annotate a class with
@Probefromcom.jprofiler.api.probe.injectedand declare interceptions. The agent must be told the probe class names, see deployment below. API reference:jprofiler://api/probe-injected.
Build setup
Both APIs are published as Maven artifacts, com.jprofiler:jprofiler-probe-embedded:<version> and
com.jprofiler:jprofiler-probe-injected:<version> where <version> is the JProfiler version - use
provided scope, the profiling agent carries the implementation. The same JARs ship in the api
directory of a JProfiler installation. The API references show the exact coordinates.
Minimal examples
Embedded payload probe:
public class ImportProbe extends PayloadProbe {
@Override
public String getName() { return "Imports"; }
@Telemetry("Open imports")
public static int openImports() { return ImportService.openCount(); }
}
// in the application code, around the measured operation:
Payload.execute(ImportProbe.class, "import " + file, () -> doImport(file));
Injected probe intercepting a method without touching its code:
@Probe(name = "Order processing")
public class OrderProbe {
@PayloadInterception(invokeOn = InvocationType.ENTER, method = @MethodSpec(
className = "com.example.Shop", methodName = "processOrder",
parameterTypes = {"int"}, returnType = "void"))
public static String payload(@Parameter(0) int orderId) { return "order " + orderId; }
}
Deployment
Embedded probes need nothing extra: the probe class is on the application classpath and registers on
first use. Injected probes are discovered through the -Djprofiler.customProbes=<probe classes> VM
parameter:
- With
prepare_profiling, set"injected": truein the probeConfig entry of every injected probe. The response then contains anadditionalJvmParametersarray with the discovery parameter - add each element as a separate VM argument to the Java command line, together with the returnedjvmParameter. - With
attach, the server passes the discovery property into the running JVM for probes marked"injected": true, no command line change is needed.
-Djprofiler.customProbes names probe classes that are loaded from the class path of the application,
so the JAR with the probe classes must be on it. For probes shipped in a separate JAR that is not on
the class path, use -Djprofiler.probeClassPath=<jar or directory> instead: the agent scans those
paths itself and registers every probe class it finds, and the probe classes must then not be on the
class path.
Recording and analysis
Record a custom probe like a built-in one:
"recordingConfig": {
"subsystems": ["cpu", "custom:com.example.ImportProbe"],
"advanced": {"probeConfig": {"custom:com.example.ImportProbe": {"events": true}}}
}
events records individual events in addition to the default aggregated hot spots. Trigger start/stop
actions and the startRecording/stopRecording attached actions take the same subsystem name. Starting a
probe that is not registered yet is stored by the agent and applied when it registers, attach reports a
warning in that case. Application code can also start and stop the probe recording itself with
Controller.startProbeRecording(probeClassName, ...), see jprofiler://api/controller.
Recorded custom probes are listed in check_status in the customProbes section with their display name
and recording state, and in availableSubsystems. The query datasets serve their data per subsystem:
performance.hotspots and performance.callTree (payload nodes appear as custom_split nodes),
probe.events, probe.eventTimeline, probe.eventHistogram, probe.controlObjects and
telemetry.list (custom probe telemetries with custom:<class>/<telemetry> ids). Custom probes do not
exist in JFR recordings.