Embedded probe API
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://api/probe-embedded of the JProfiler MCP server, see the tool and resource reference for the full list of tools and resources.
API reference of com.jprofiler.api.probe.embedded for writing embedded custom probes: the probe base
classes PayloadProbe and SplitProbe, the measurement entry points Payload and Split and the
telemetry annotations. Read jprofiler://probes/custom first for the embedded/injected decision, build
setup, deployment and recording.
Types
Flat alphabetical index of every type in the API. Use this when you know the qualified name and want to skip package navigation.
| Qualified name | Kind | File |
|---|---|---|
com.jprofiler.api.probe.embedded.Payload | class | Payload |
com.jprofiler.api.probe.embedded.PayloadProbe | class | PayloadProbe |
com.jprofiler.api.probe.embedded.Split | class | Split |
com.jprofiler.api.probe.embedded.SplitProbe | class | SplitProbe |
com.jprofiler.api.probe.embedded.ThreadState | enum | ThreadState |
com.jprofiler.api.probe.embedded.TypeCustomizer | interface | TypeCustomizer |
com.jprofiler.api.probe.embedded.telemetry.Telemetry | annotation | Telemetry |
com.jprofiler.api.probe.embedded.telemetry.TelemetryFormat | annotation | TelemetryFormat |
com.jprofiler.api.probe.embedded.telemetry.TelemetryUnit | enum | TelemetryUnit |
Package com.jprofiler.api.probe.embedded
Contains the classes for creating an embedded probe.
Purpose of embedded probes
Please read the "Probe concepts" chapter in the documentation (directory $JPROFILER_HOME/doc) for
an overview on the different types of custom probes in JProfiler and the "Embedded probes" chapter
for an extended discussion of embedded probes.
Embedded probes allow you to add functionality similar to the built-in probes in JProfiler. In contrast to the "injected" probe API, the "embedded" probe API is called directly from the monitored software. If you want to monitor software components whose source code is not under your control, use the injected probe API instead.
Getting started
There are two types of embedded probes, split probes and payload probes.
Please see Split and Payload
for further information.
To get started with writing embedded probes, have a look at the $JPROFILER_HOME/api/samples/simple-embedded-probe
example project. Open the gradle build file build.gradle in an editor for instructions on how to run it.
JAR file and dependency
All classes in this package are contained in $JPROFILER_HOME/api/jprofiler-probe-embedded.jar.
The embedded probe API is also available as a dependency. In the snippets below, "VERSION"
should be replaced with the corresponding JProfiler version.
Maven
<dependency>
<groupId>com.jprofiler</groupId>
<artifactId>jprofiler-probe-embedded</artifactId>
<version>VERSION</version>
</dependency>
Gradle
dependencies {
implementation group: 'com.jprofiler', name: 'jprofiler-probe-embedded', version: 'VERSION'
}
License
Classes in this package and its sub-packages are licensed under the Apache License, version 2.0.
Payload
Import: import com.jprofiler.api.probe.embedded.Payload;
@JProfilerEmbeddedClass
public class Payload
By calling this class you can add entries to the payload call tree and hotspots of your probe.
You can either use a pair of Payload.enter and Payload.exit calls or the execute wrappers. If you write your own
wrapper in another JVM language it is advisable to use the Payload.enter and Payload.exit primitives.
When using the primitives, it is very important that a matching Payload.exit is always called, so the exit call must be put in a finally block like this:
Payload.enter(MyProbe.class);
try {
// your code
} finally {
Payload.exit("my payload string");
}
If you use control objects in your probe (for example to record connections like in the JDBC probe) you can use the Payload.enter or the similarly overloaded execute wrappers
to associate a payload with a control object. With the Payload.openControlObject, Payload.closeControlObject and
PayloadProbe.getControlObjectName methods you can further customize control object recording. Your configuration subclass of PayloadProbe must override
PayloadProbe.isControlObjects and return true to enable control object recording as a capability for the probe.
If you want to record different event types which also correspond to different control object states, you have to override PayloadProbe.getCustomTypes and return a custom enum class.
Objects of this class can then be passed to Payload.enter.
The toString() method of the enums will be used to get the event name. If you want to control the event color, the enum class can implement the TypeCustomizer interface.
Methods
##### enter(Class<? extends PayloadProbe>)
public static void enter(Class<? extends PayloadProbe> probe)
Start a payload. A matching Payload.exit call must always be called.
Parameters:
probe— the configuration class. Must not benull.
##### enter(Class extends PayloadProbe>, Object, Enum>)
public static void enter(Class<? extends PayloadProbe> probe, Object controlObject, Enum<?> type)
Start a payload. A matching Payload.exit call must always be called.
Parameters:
probe— the configuration class. Must not benull.controlObject— the control object this payload belongs to ornull. If control objects should be recorded you have to overridePayloadProbe.isControlObjects.type— the payload type. Must be an object of your custom enum class registered by overridingPayloadProbe.getCustomTypesornull.
public static void exit(String name)
Finishes recording of a payload. A matching enter call must have been called first.
Parameters:
name— the name of the recorded payload. Ifnull, the payload recording will be discarded.
##### execute(Class<? extends PayloadProbe>, String, Runnable)
public static void execute(Class<? extends PayloadProbe> probe, String name, Runnable runnable)
A wrapper for the Payload.enter and Payload.exit primitives for a Runnable.
Parameters:
probe— the configuration class. Must not benull.name— the name of the recorded payload. Ifnull, the payload recording will be discarded.runnable— the runnable that will be timed for the payload recording.
##### execute(Class extends PayloadProbe>, String, Object, Enum>, Runnable)
public static void execute(Class<? extends PayloadProbe> probe, String name, Object controlObject, Enum<?> type, Runnable runnable)
A wrapper for the Payload.enter and Payload.exit primitives for a Runnable.
Parameters:
probe— the configuration class. Must not benull.name— the name of the recorded payload. Ifnull, the payload recording will be discarded.controlObject— the control object this payload belongs to ornull. If control objects should be recorded you have to overridePayloadProbe.isControlObjects.type— the payload type. Must be an object of your custom enum class registered by overridingPayloadProbe.getCustomTypesornull.runnable— the runnable that will be timed for the payload recording.
##### execute(Class<? extends PayloadProbe>, String, Callable
public static <T> T execute(Class<? extends PayloadProbe> probe, String name, Callable<T> callable) throws Exception
A wrapper for the Payload.enter and Payload.exit primitives for a Callable.
Parameters:
probe— the configuration class. Must not benull.name— the name of the recorded payload. Ifnull, the payload recording will be discarded.callable— the callable that will be timed for the payload recording.
##### execute(Class extends PayloadProbe>, String, Object, Enum>, Callable
public static <T> T execute(Class<? extends PayloadProbe> probe, String name, Object controlObject, Enum<?> type, Callable<T> callable) throws Exception
A wrapper for the Payload.enter and Payload.exit primitives for a Callable.
Parameters:
probe— the configuration class. Must not benull.name— the name of the recorded payload. Ifnull, the payload recording will be discarded.controlObject— the control object this payload belongs to ornull. If control objects should be recorded you have to overridePayloadProbe.isControlObjects.type— the payload type. Must be an object of your custom enum class registered by overridingPayloadProbe.getCustomTypesornull.callable— the callable that will be timed for the payload recording.
##### openControlObject(Class<? extends PayloadProbe>, Object, String)
public static void openControlObject(Class<? extends PayloadProbe> probe, Object controlObject, String name)
Records an open event for a control object and assigns a name to it. The control object will be displayed in the control objects view and the timeline.
Your configuration subclass of PayloadProbe must override PayloadProbe.isControlObjects and return true to enable control object
recording as a capability for the probe.
If you don't use this method and a previously unknown control object is used in the enter or execute methods and
you have overridden the PayloadProbe.getControlObjectName method of your configuration class, it will be called to assign a name to the new control object.
No open event will be created in the events view in that case.
Parameters:
probe— the configuration class. Must not benull.controlObject— the control objectname— the name of the control object
##### closeControlObject(Class<? extends PayloadProbe>, Object)
public static void closeControlObject(Class<? extends PayloadProbe> probe, Object controlObject)
Closes a control object. If the control object is not currently open, this method has no effect.
Parameters:
probe— the configuration class. Must not benull.controlObject— the control object
##### register(Class<? extends PayloadProbe>)
public static void register(Class<? extends PayloadProbe> probe)
You can register your probe independently of enter and execute calls. As soon as the probe is registered
it will be displayed in the JProfiler UI and telemetries can be recorded.
You don't have to call this method if you don't want to start telemetry recording before an enter or execute call
takes place. enter or execute and all control object methods will automatically register your probe.
Parameters:
probe— the configuration class. Must not benull.
Constructors
| Signature | Description |
|---|---|
Payload() |
public Payload()
PayloadProbe
Import: import com.jprofiler.api.probe.embedded.PayloadProbe;
@JProfilerEmbeddedClass
public abstract class PayloadProbe
For each payload probe, you have to create a subtype of this class and pass it as a class literal
to the methods in Payload.
You can override the methods of this class to configure your probe. The only method you have to implement is
PayloadProbe.getName.
You can add additional custom telemetries by adding public static methods to your subclass that return a number type and are annotated with Telemetry.
Methods
| Signature | Returns | Description |
|---|---|---|
getName() | String | Implement this method to specify the display name of your probe. |
getDescription() | String | You can override this method to add a description to your probe in the JProfiler UI. |
isEvents() | boolean | You can override this method and return false if you want to remove the events view. |
isDefaultTelemetries() | boolean | You can override this method and return false if you want to remove the default telemetries. |
isControlObjects() | boolean | If your probe supports control objects, you have to override this method and return true. |
getCustomTypes() | Class<? extends Enum> | You can specify custom types for events. |
getControlObjectName(Object) | String | If you use control objects and a previously unknown control object is passed to Payload.enter, Payload.execute or Payload.execute, the JProfiler agent will call this method to associate a name with the control object. |
public abstract String getName()
Implement this method to specify the display name of your probe. In the JProfiler UI, this string is used for the view name in the "JVM & Custom Probes" section of the view selector.
Returns: the name of your probe
public String getDescription()
You can override this method to add a description to your probe in the JProfiler UI. It is shown in the probe view below the probe name.
Returns: your optional description
public boolean isEvents()
You can override this method and return false if you want to remove the events view.
Returns: if the events view should be displayed
public boolean isDefaultTelemetries()
You can override this method and return false if you want to remove the default telemetries.
The default telemetries are the event frequency and the average duration telemetries as well as the open control
object telemetry if PayloadProbe.isControlObjects returns true.
Returns: if the default telemetries will be recorded
public boolean isControlObjects()
If your probe supports control objects, you have to override this method and return true.
Returns: if control objects can be recorded
public Class<? extends Enum> getCustomTypes()
You can specify custom types for events. If control objects are recorded, the same types are used for the associated control object states. In the overridden method,
return an Enum class with all your states as constants. The toString() method is used for
the event display name. You can further customize your events by implementing TypeCustomizer in the enum class.
Returns: the class of your event enum
##### getControlObjectName(Object)
public String getControlObjectName(Object controlObject)
If you use control objects and a previously unknown control object is passed to Payload.enter, Payload.execute or
Payload.execute, the JProfiler agent will call this method to associate a name with the control object. You can alternatively associate a name
with a control object by calling Payload.openControlObject.
Parameters:
controlObject— the control object that has no name associated yet
Returns: a name that will be displayed in the JProfiler UI for this object
Constructors
| Signature | Description |
|---|---|
PayloadProbe() |
public PayloadProbe()
Split
Import: import com.jprofiler.api.probe.embedded.Split;
@JProfilerEmbeddedClass
public class Split
By calling this class you can add an arbitrary split in the call tree, just like the URL splitting of JProfiler's built-in "HTTP server" probe.
You can either use a pair of Split.enter and Split.exit calls or the two execute wrappers. If you write your own
wrapper in another JVM language it is advisable to use the Split.enter and Split.exit primitives.
When using the primitives, it is very important that a matching Split.exit is always called, so the exit call must be put in a finally block like this:
Split.enter(MyProbe.class, "my split string");
try {
// your code
} finally {
Split.exit();
}
Methods
| Signature | Returns | Description |
|---|---|---|
enter(Class<? extends SplitProbe>, String) | void | Split the call tree with the given name. |
exit() | void | Marks the end of a split. |
execute(Class<? extends SplitProbe>, String, Runnable) | void | A wrapper for the Split.enter and Split.exit primitives for a Runnable. |
execute(Class<? extends SplitProbe>, String, Callable<T>) | T | A wrapper for the Split.enter and Split.exit primitives for a Callable. |
register(Class<? extends SplitProbe>) | void | You can register your probe independently of Split.enter and execute calls. |
##### enter(Class<? extends SplitProbe>, String)
public static void enter(Class<? extends SplitProbe> probe, String name)
Split the call tree with the given name. A matching Split.exit call must always be called.
Parameters:
probe— the configuration class. Must not benull.name— the line that should show up in the call tree. Ifnull, the call tree won't be split.
public static void exit()
Marks the end of a split. A matching Split.enter call must have been called first.
##### execute(Class<? extends SplitProbe>, String, Runnable)
public static void execute(Class<? extends SplitProbe> probe, String name, Runnable runnable)
A wrapper for the Split.enter and Split.exit primitives for a Runnable.
Parameters:
probe— the configuration class. Must not benull.name— the line that should show up in the call tree. Ifnull, the call tree won't be split.runnable— the runnable that will be executed inside the split.
##### execute(Class<? extends SplitProbe>, String, Callable
public static <T> T execute(Class<? extends SplitProbe> probe, String name, Callable<T> callable) throws Exception
A wrapper for the Split.enter and Split.exit primitives for a Callable.
Parameters:
probe— the configuration class. Must not benull.name— the line that should show up in the call tree. Ifnull, the call tree won't be split.callable— the callable that will be executed inside the split.
##### register(Class<? extends SplitProbe>)
public static void register(Class<? extends SplitProbe> probe)
You can register your probe independently of Split.enter and execute calls. As soon as the probe is registered
it will be displayed in the JProfiler UI and telemetries can be recorded.
You don't have to call this method if you don't want to start telemetry recording before an Split.enter or execute call
takes place. Split.enter or execute will automatically register your probe.
Parameters:
probe— the configuration class. Must not benull.
Constructors
| Signature | Description |
|---|---|
Split() |
public Split()
SplitProbe
Import: import com.jprofiler.api.probe.embedded.SplitProbe;
@JProfilerEmbeddedClass
public abstract class SplitProbe
For each split probe, you have to create a subtype of this class and pass it as a class literal
to the methods in Split. You can override the methods of this class to configure your probe.
If you return true in SplitProbe.isPayloads you can add additional custom telemetries by adding public
static methods to your subclass that return a number type and are annotated with Telemetry.
Methods
| Signature | Returns | Description |
|---|---|---|
isReentrant() | boolean | If you want to create nested splits with this probe you can override this method and return true. |
isPayloads() | boolean | You can override this method and return true to create an entry in the probes section and record your top level splits as payloads. |
getName() | String | If you return true in SplitProbe.isPayloads you can override this method to specify the display name of your probe. |
getDescription() | String | If you return true in SplitProbe.isPayloads you can override this method to add a description for your probe in JProfiler's probe section. |
isEvents() | boolean | If you return true in SplitProbe.isPayloads, but want to hide the events view you can override this method and return false. |
isDefaultTelemetries() | boolean | If you return true in SplitProbe.isPayloads but want to remove the default payload telemetries you can override this method and return false. |
public boolean isReentrant()
If you want to create nested splits with this probe you can override this method and return true. Otherwise, only the
top level call in the stack to the methods in Split will have an effect.
Returns: if nested splits will be recorded
public boolean isPayloads()
You can override this method and return true to create an entry in the probes section and record your top level
splits as payloads.
Returns: if the top level splits should also be recorded as payloads in the probes section
public String getName()
If you return true in SplitProbe.isPayloads you can override this method to specify the display name of your probe.
In the JProfiler UI, this string is used for the view name in the "JVM & Custom Probes" section of the view selector.
If you do not override this method, the simple class name of the probe is used.
Returns: the name of your probe
public String getDescription()
If you return true in SplitProbe.isPayloads you can override this method to add a description for your probe in JProfiler's probe section.
Returns: the description of your probe
public boolean isEvents()
If you return true in SplitProbe.isPayloads, but want to hide the events view you can override this method and return false.
Returns: if events are recorded for payloads
public boolean isDefaultTelemetries()
If you return true in SplitProbe.isPayloads but want to remove the default payload telemetries you can override this method and return false.
The default telemetries are the event frequency and the average duration telemetries.
Returns: if the default telemetries will be recorded
Constructors
| Signature | Description |
|---|---|
SplitProbe() |
public SplitProbe()
ThreadState
Import: import com.jprofiler.api.probe.embedded.ThreadState;
@JProfilerEmbeddedClass
public final enum ThreadState
Allows you to override the thread state recorded in JProfiler.
You can nest calls to ThreadState.enter and ThreadState.exit, but only the outermost call is used for recording.
It is very important that a matching ThreadState.exit is always called, so the exit call must be put in a finally block like this:
ThreadState.NETIO.enter();
try {
// your code
} finally {
ThreadState.exit();
}
Constants
The current thread is runnable.
The current thread is waiting.
The current thread is blocked on a monitor.
The current thread is in a Net IO operation.
Methods
| Signature | Returns | Description |
|---|---|---|
values() | ThreadState[] | |
valueOf(String) | ThreadState | |
enter() | void | Enters a thread state. |
exit() | void | Exits the current override state and resets the state to the value reported by the JVM. |
public static ThreadState[] values()
public static ThreadState valueOf(String name)
public void enter()
Enters a thread state. This state will be recorded until the matching exit is called.
public static void exit()
Exits the current override state and resets the state to the value reported by the JVM.
TypeCustomizer
Import: import com.jprofiler.api.probe.embedded.TypeCustomizer;
interface TypeCustomizer
Interface to further customize event enums registered with PayloadProbe.getCustomTypes.
Your enum class can implement this interface to customize the color of your types.
Methods
| Signature | Returns | Description |
|---|---|---|
getColor() | int | The color of your enum constant. |
int getColor()
The color of your enum constant.
Returns: the RGB int value of a color, for example 0xCCAA00
Package com.jprofiler.api.probe.embedded.telemetry
Contains the classes for adding custom telemetries to an embedded probe.
The Telemetry class contains further information.
Telemetry
Import: import com.jprofiler.api.probe.embedded.telemetry.Telemetry;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@interface Telemetry implements Annotation
Create a custom telemetry from the numeric return value of the annotated static method in your subclasses of PayloadProbe or SplitProbe.
Only public static parameterless methods can be used for creating custom telemetries, annotating instance methods or non-public
static methods will not have any effect.
The method must return a numeric value, either a primitive value like int or double, a
java.math.BigDecimal or a primitive wrapper instance like java.lang.Integer or java.lang.Double.
The method is called periodically on a dedicated thread. This may have implications for the requirements of
thread safety in your code. If the numeric value is calculated on the fly, access to the data structures
must be made thread-safe by making access to those data structures synchronized. Alternatively, you could
calculate a cached value when convenient and save it to a volatile atomic value, like an int or a
class from the java.util.concurrent.atomic package.
For example, the following code snippet defines a custom telemetry with the name "Connection count":
@Telemetry("Connection count")
public static int getConnectionCount() {
return connectionCount;
}
Multiple lines in a single custom telemetry
If you want to compare several measurements in the same telemetry, you can annotate multiple methods with the
same Telemetry.value for the telemetry name, but with a different Telemetry.line parameter.
For example:
@Telemetry(value = "Queries", line = "Successful queries")
public static int getSuccessCount() {
return successCount;
}
@Telemetry(value = "Queries", line = "Failed queries")
public static int getErrorCount() {
return errorCount;
}
This will create a single custom telemetry with the name "Queries" and two data lines named "Successful queries" and "Failed queries".
Elements
| Element | Type | Default | Description |
|---|---|---|---|
value | String | — | The name of the telemetry. |
line | String | "" | The optional line name of the telemetry. |
format | TelemetryFormat | @com.jprofiler.api.probe.embedded.telemetry.TelemetryFormat | Optional display options for the telemetry. |
The name of the telemetry. Give different names to different telemetries. Reuse the same name when annotating different methods if you are creating a custom telemetry with multiple lines. If only a single line is used, you can omit the "value" parameter name, as in
@Telemetry("Connection count")
The optional line name of the telemetry. Only specify this parameter if you're creating a telemetry with
multiple lines. See Telemetry for an example.
Optional display options for the telemetry.
TelemetryFormat
Import: import com.jprofiler.api.probe.embedded.telemetry.TelemetryFormat;
@interface TelemetryFormat implements Annotation
Display options for a Telemetry annotation.
This annotation is used by the Telemetry.format parameter.
Elements
| Element | Type | Default | Description |
|---|---|---|---|
value | TelemetryUnit | PLAIN | The unit of the recorded values. |
scale | int | 0 | A scaling factor for the telemetry. |
stacked | boolean | false | Determines whether multiple lines in a telemetry should be stacked into an area graph. |
The unit of the recorded values. By default, telemetries are unitless.
A scaling factor for the telemetry. In the UI, recorded values will be multiplied with 10^-scale.
In JProfiler, probe telemetry data is stored in 32-bit ints. So this is especially useful for telemetries that
will show higher values than 2^31. For example, if you use the
TelemetryUnit.BYTES you can return kB instead and set the scale to -3.
This is also useful to show fractional values. For example, if you want to show a percentage with two decimal digits,
the returned value should be the percentage times 100 and the scale parameter should be set to 2.
Determines whether multiple lines in a telemetry should be stacked into an area graph. By default, multiple telemetry lines are not stacked. An example of a stacked graph is the "Heap usage" telemetry.
TelemetryUnit
Import: import com.jprofiler.api.probe.embedded.telemetry.TelemetryUnit;
public final enum TelemetryUnit
Telemetry unit used in the TelemetryFormat annotation.
Constants
The telemetry value is a unitless number.
The telemetry value has the unit "per second".
The telemetry value has the unit "percent".
The telemetry value has the unit "milliseconds". Conversion into higher unit prefixes such as seconds is done automatically as required.
The telemetry value has the unit "microseconds". Conversion into higher unit prefixes such as seconds is done automatically as required.
The telemetry value has the unit "bytes". Conversion into higher unit prefixes such as kB, MB or GB is done automatically as required.
In JProfiler, probe telemetry data is stored in 32-bit ints. If you expect higher values than 2^31 bytes, you can
for example return kB instead and set TelemetryFormat.scale to -3.
Methods
| Signature | Returns | Description |
|---|---|---|
values() | TelemetryUnit[] | |
valueOf(String) | TelemetryUnit |
public static TelemetryUnit[] values()
public static TelemetryUnit valueOf(String name)