Package com.perfino.annotation
Annotations for configuring transactions and telemetries in your own code.
What is this API for?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 simple class name of the surrounding class
- The text " query "
- The result of calling
getQuery().getName()
on the second parameter of the annotated method - 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 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:
- Which methods are actually instrumented by your transaction definitions
-
If a filter of an
inheritance
specification 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.Filter type for filter expressions in
Inheritance.filter()
.Controls the way overridden methods will be handled byMethodTransaction
andClassTransaction
.Mode for handling derived classes.Create transactions for the annotated method.Excludes the annotated method or class from the transaction detection.Specifies the way package names are treated when adding class names to a transaction name.Specifies a single part of a transaction name.The kind of information that is added by aPart
.Limits the creation of nested transactions.Create a Devops telemetry from the numeric return value of the annotated static method.Display options for aTelemetry
annotation.Telemetry unit used in theTelemetryFormat
annotation.