Package dev.jvmguard.annotation
Annotations for configuring transactions and telemetries in your own code.
What is this API for?In jvmguard, you can create transactions from any method invocation. When you configure these transactions in the UI, they are called Matched transactions. They are most suitable for classes that you cannot modify. In your own code, it is easier and more maintainable to use annotations from the jvmguard API to configure transactions. In jvmguard, these are called Declared transactions. The annotations provided by jvmguard only control the naming of the transactions, the policies have to be configured in the jvmguard UI. See the corresponding help topics for more information on these concepts.
What is the impact of this API package at runtime?All annotations have a class retention policy, so using them without jvmguard has zero impact at runtime: no additional classes are loaded, and no code is executed. If your code is monitored by jvmguard, the annotations are read by the monitoring agent while the JVM is loading the classes.
How do I define a transaction?
Defining a transaction is straightforward. Add @MethodTransaction to a
method, then each method call will be shown as a transaction in jvmguard. If you have a class where all public methods
should be a transaction, annotate that class with @ClassTransaction.
If some public methods in that class should be excluded, annotate them with
@NoTransaction.
In the above case, the transaction name for the @ClassTransaction is the class name, for the
@MethodTransaction it is the method name prepended by the class name. In some cases
you will want to customize this name and capture parameters that are passed to a method. This is done by passing a list of
@Part annotations as parameters to @ClassTransaction and
@MethodTransaction. Each @Part results in a string and all strings are concatenated to form
the entire transaction name.
A simple example with one part is
@MethodTransaction(naming=@Part(text="My transaction"))
If you have more than one part, you have to pass the parts as an array:
@MethodTransaction(naming = {@Part(text="Plugin "), @Part(Type.INSTANCE_CLASS)})
Another configuration aspect is inheritance. Should any overridden methods be considered as well, and what class names
should be used for naming in that case? The @Inheritance annotation is
used as a parameter to configure this behavior. By default, overridden methods are not instrumented.
A complex example looks like this:
@MethodTransaction(group = "db", naming = {
@Part(value = Type.CLASS, packageMode = Part.PackageMode.ABBREVIATED),
@Part(text=" query "),
@Part(value = Type.PARAMETER, parameterIndex = 1, getterChain = "getQuery().getName()"),
@Part(text=" count "),
@Part(value = Type.PARAMETER, parameterIndex = 2)},
inheritance = @Inheritance(value = Mode.WITH_SUPERCLASS_NAME, filter = "*Executor")
)
It puts the transaction in a group, so you can define the policies for multiple annotations with the same group in the jvmguard UI together. Then, it sets up a composite name consisting of
- The simple class name of the surrounding class
- The text "query" surrounded by spaces
- The result of calling
getQuery().getName()on the second parameter of the annotated method - A space followed by the text "count"
- The third parameter of the annotated method
The result might look like this: "c.e.a.DbExecutor query SIMPLE_QUERY count 5"
The inheritance filter specifies that methods in all classes that match the wildcard filter "*Executor" should be instrumented. However, the class name for the naming should remain that of the class where the annotation is present.
How do I define a telemetry?
A custom telemetry is defined by annotating a static parameterless method with @Telemetry.
The static method must return a numeric value, either a primitive value like int or double or a
primitive wrapper instance like java.lang.Integer or java.lang.Double.
You can configure multiple lines to be shown in the same telemetry.
In the jvmguard UI, the telemetry is shown in the "Telemetries" view. In addition, you can choose custom telemetries as data sources for sparklines in the dashboard or in the VMs view.
How can I debug the effects of my annotations?If your annotations do not have the desired effect, you can switch on logging to debug the problem. This could be the case if you are missing transactions or your transaction names are not as expected. To enable logging, pass the system property
jvmguard.logUser=1
to the monitored VM, for example, by adding the VM parameter -Djvmguard.logUser=1 to the java invocation.
The log file is on the machine where the monitored VM is running and is located in the directory
$HOME/.jvmguard/log/[VM name].log
To write the log file to a different location, you can set the system property
jvmguard.logFile=/path/to/file.log
The log file is only created if there is any logging output. Things you can see in the log file include:
- The methods are actually instrumented by your transaction definitions
-
If a filter of an
inheritancespecification rejects the instrumentation of a candidate method. -
If an invalid parameter index is requested by a naming @Part of type
Part.Type.PARAMETER.
-
ClassDescriptionCreate transactions for all public instance methods of the annotated class.Controls the way overridden methods will be handled by
MethodTransactionandClassTransaction.Filter type for filter expressions inInheritance.filter().Mode for handling derived classes.Create transactions for the annotated method.Excludes the annotated method or class from the transaction detection.Specifies a single part of a transaction name.Specifies the way package names are treated when adding class names to a transaction name.The kind of information that is added by aPart.Limits the creation of nested transactions.Create a Declared telemetry from the numeric return value of the annotated static method.Display options for aTelemetryannotation.Telemetry unit used in theTelemetryFormatannotation.