See: Description
Enum | Description |
---|---|
FilterType |
Filter type for filter expressions in
Inheritance.filter() . |
Inheritance.Mode |
Mode for handling derived classes.
|
PackageMode |
Specifies the way package names are treated when adding class names to a transaction name.
|
Part.Type |
The kind of information that is added by a
Part . |
ReentryInhibition |
Limits the creation of nested transactions.
|
Annotation Type | Description |
---|---|
ClassTransaction |
Create transactions for all public instance methods of the annotated class.
|
Inheritance |
Controls the way overridden methods will be handled by
MethodTransaction and
ClassTransaction . |
MethodTransaction |
Create transactions for the annotated method.
|
NoTransaction |
Excludes the annotated method or class from the transaction detection.
|
Part |
Specifies a single part of a transaction name.
|
Telemetry |
Create a custom telemetry from the numeric return value of the annotated static method.
|
In perfino, you can create transactions from any method invocation. When you configure these transactions in the UI, they are called POJO 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 perfino API to configure transactions. In perfino, these are called DevOps transactions. The annotations provided by perfino only control the naming of the transactions, the policies have to be configured in the perfino 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 perfino has zero impact at runtime: no additional classes are loaded and no code is executed. If your code is monitored by perfino, the annotations are read by the monitoring agent while the classes are loaded.
How do I define a transaction?
Defining a transaction is simple. Add @MethodTransaction
to a
method, then each method call will be shown as a transaction in perfino. 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 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 = 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 perfino UI together. Then, it sets up a composite name consisting of
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 perfino UI, the telemetry is shown in the VM data views under "Custom telemetries". 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
perfino.logUser=1
to the monitored VM, e.g. by adding the VM parameter -Dperfino.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/.perfino/log/[VM name].log
To write the log file to a different location, you can set the system property
perfino.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:
inheritance
specification rejects the
instrumentation of a candidate method.
Part.Type.PARAMETER
.