Agent Extensions

An agent can be used standalone or it can be extended by user custom code. Flopsar Agent is a powerful engine, which is extensible by plugins. The extensions are some extra jar files, which consist of user-defined POJO classes. The jars can be then uploaded to the Flopsar server. The plugins enable to extend the agent capabilities. We provide a mechanism that you can use to extend your application diagnosis and trace your data flow. It makes Flopsar an open tool, that can be extended. The plugin allows for processing data inside instrumented methods.

There are two types of extensions, which can be used: standard and custom.

Standard

The standard extension is embedded in the agent. This extension will execute the following method on each argument it gets:

public static java.lang.String valueOf(java.lang.Object);

and return a result in a form of concatenated pairs of parameter identifiers and the corresponding valueOf function result. The following parameters are returned (in order of appearance):

  • THIS : If the instrumented method is static, this parameter is null, otherwise a class instance the method is executed on.

  • ARGS : List of all arguments of the instrumented method.

Custom

If you are not satisfied with standard extension and you want to extract some additional information (or make some preprocessing) you must implement your own, custom extension. In order to take advantage of this feature, all you have to do is set up a configuration, create a simple POJO class and implement a single method:

public static java.lang.String myFormatter(java.lang.Object[] args)

You can give any name to the above method but the signature of the method must be preserved. Otherwise, it will not work.

The args argument of the extension method is an array of the instrumented method arguments delivered to your method. These are your original application objects, not clones. When you set up the configuration correctly, the agent will inject your code into the instrumented methods during the instrumentation. It can be injected in one of the two places, i.e. at the beginning or the end of the method. Note, your formatter code is executed inside your instrumented method, so make sure your formatter code generates minimal overhead. The argument args is an array of the following objects (in order of appearance):

  • args[0] If the instrumented method is static this element is null, otherwise it is a reference to a class instance the instrumented method is executed on.

  • args[1..N] List of all arguments of the instrumented method in the same order as they appear in the method signature. These are the references to your original application objects, not some clones.

where N is the number of the instrumented method arguments.

When you set up the configuration correctly, the agent will inject your formatter code into the instrumented methods during the instrumentation. It can be injected in one of the two places, i.e. at the beginning or the end of the method. Note, your extension code is executed inside your instrumented method, so make sure your code generates minimal overhead.

In fact, it is up to you what extra features the agent will have. You can even extend your agent installation to cover a distributed transaction tracing.

Use U+001E as a separator in your code. Otherwise, the result will not be formatted properly in the workstation.

Your result should always consist of pairs of keys and values. U+001E separates each entry in the result, which means you should always have an odd number of separators. The resulting string size cannot be greater than 8192 B, otherwise it will be truncated.

There are some tips, you should take into account when writing extensions:

  • Design and implement extensions with performance in mind. If your code performs poorly, obviously the instrumented methods will perform poorly as well.

  • Use try-catch block to protect your application from any errors you can make in your extension implementation. Otherwise, any errors inside the extension code can interfere with your application processing.

  • Do not modify arguments delivered to your extension since they are your genuine application objects. Make sure that whatever you do with them will not cause any problem to your application flow.

  • Try not to use reflections, unless there is no other way.

  • Try not to create too many new objects, otherwise you risk increased GC overhead.

  • Deploy your extension classes into separate jar files. This can save you a lot of trouble when dealing with class loading issues.

  • Your extension code should be stateless.

Example

Suppose, you have some method:

public FooBar foo(foo.bar.Object1, foo.bar.Object2, ...);

and you are interested in some additional information extracted from the first and second arguments. Your extension implementation can look like the one below:

public static java.lang.String myFormatter(java.lang.Object[] args){

        final char SEPARATOR = 0x1E;

        try {
                foo.bar.Object0 _this = (foo.bar.Object0)args[0];
                foo.bar.Object1 obj1 = (foo.bar.Object1)args[1];
                foo.bar.Object2 obj2 = (foo.bar.Object2)args[2];
                /*
                 implement your logic here
                 to produce string output.
                */
                String output1 = some_logic1(obj1);
                String output2 = some_logic2(obj2);

                return "Object1"+SEPARATOR+output1+SEPARATOR+"Object2"+SEPARATOR+output2;

        } catch(Throwable ex){
                return "Error"+SEPARATOR+ex.getMessage();
        }
}

Flopsar Technology cannot be held responsible for any damage done by badly written user's extensions.