1. Agent API

If you want to provide your own, non-JVM, data and store them in the Flopsar environment, you can do it using the agent API. This functionality is embedded in the Flopsar Agent. In order to make use of the API, you must add flopsar-agent-2.4.jar as a dependency to your project. The API contains a single class com.flopsar.agent.api.Agent with the following methods:

public static Agent createConnection(String flopsarId,String fsmHost,
                                        int fsmPort,long outboundQueueSize);

public static void setupLogger(String loggerDirectory,int logSize,
                                AbstractLoggerLevel level);

public boolean isConnected();

public final void close();

public final void submitAsKV(String key,long timestamp,long value);

public final String buildKey(String... element);

public final void submitAsStack(String name,String signature,long timestamp,
                                int duration,Map<String, String> parameters);

The first method is used to create a new Agent object. When you call this method, a new connection to your manager is established asynchronously. That means the method returns immediately, so you must make sure the connection is established by calling the isConnected method.

There is a simple example below:

/* First you must setup a logger */
Agent.setupLogger("/some/directory",10,AbstractLoggerLevel.INFO);

/* Next, connect to the manager */
Agent a = Agent.createConnection("myAgentId","192.168.0.10",9000,100);

/* Wait, until the connection is established */
while (a.isConnected()){
        Thread.sleep(1000);
}

/* Now, you can produce your data and send it to the manager */

2. Agent Formatters

The formatters enable to extend agent functionalities. Unlike other vendors, we provide a mechanism which you can use to extend your application diagnosis and trace your data flow. It makes Flopsar an open tool, that can be extended. There are two types of formatters, which can be used: standard and custom.

2.1. Standard

The standard formatter is embedded in agent. This formatter 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 identifier 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.
RET
Only if the instrumented method does not return void and the instrumentation is performed at the method exit.

2.2. Custom

If you are not satisfied with the standard formatter and you want to extract some additional information (or make some preprocessing) you must implement your own, custom formatter.

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 formatter 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();
        }
}

You can give any name to the formatter method, but the signature of the method must be preserved. Otherwise, it will not work. The argument of the formatter is an array of the instrumented method arguments delivered to your formatter. These are your original application objects, not clones. When you set up the configuration correctly, 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 formatter code is executed inside your instrumented method, so make sure your formatter code generates minimal overhead.

Important

Please, use U+001E as a separator in your formatters. Otherwise, the result will not be formatted properly in the Workstation.

Please, use try-catch block to protect your application from any errors you can make in your formatter implementation. Otherwise, any errors inside the formatter can interfere your application processing.

Note

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

Your result should always consist of pairs of key and value. U+001E separates each entry in the result, that 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 formatters:

  • do not modify arguments delivered to your formatter 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 formatter classes into separate jar files. This can save you a lot of trouble when dealing with class loading issues.

Important

No formatter implementation is supported by Flopsar Technology.

3. Database API

Flopsar provides API, which you can use to access your collected data. fdbc enables only local access to the database.

3.1. Java

For Java API, please refer to http://docs.flopsar.com/fdbc/index.html

3.2. C/C++

For C/C++ API, please refer to an fdbc(3) man page.

4. Plugins

Flopsar provides a few functionalities implemented as plugins. These implementations can be easily replaced with user defined implementations. In this version of Flopsar only manager supports plugins. There is one plugin currently available: authentication and it can be replaced.

Flopsar provides a C API for writing custom implementations of plugins. In order to write a plugin, you need to include in your project the main header fs2plugin_api.h file, which can be found in /usr/include/flopsar/ directory. This file contains prototypes of functions to implement. The function below is the most important one and must be implemented. This function is called only once when the application loads the plugin.

int init_plugin(struct plugin_fs2 *p, const char *home_dir, const char *plugins_conf_dir);

When you call the function above you will be provided with three arguments. The p argument is a structure representing your plugin. You should keep it, since it is required when you register your plugin hooks. The home_dir argument is a path to your manager environment directory. The last argument plugins_conf_dir is a path to your manager configuration directory. This can be used to add any additonal configuration to your plugin (see ref{plg-ntfy} as an example).

Important

Do not change the name of the function above. It must stay init_plugin, otherwise a plugin will not be loaded.

Implement your own plugin initialization and register your functions to the application within this function.

There is an optional function to implement:

typedef int (*fs2_plugin_test)(void);

which can be registered by executing the function below:

void fs2_register_test_hook(struct plugin_fs2 *p,fs2_plugin_test hook);

This is a test function, which can be used to implement some test that will help you to check if your plugin work as expected in runtime. If the test succeeds the function should return 0, otherwise -1. In order to trigger the test you must execute the following command:

$ fs2mgr set --plugins-test <manager_home>

This command will execute all the registered plugins test hooks.

4.1. Plugin: Authentication

If you want to use your own authentication system, you must implement a plugin in order to be able to authenticate your users against this system. In order to write a custom authentication plugin, you must include an additional header fs2plugin_api_auth.h file. All you have to do is to implement the function below:

typedef int (*fs2_user_auth)(const char *username, const char *password);

and then register it by means of the function

void fs2_register_user_auth_hook(struct plugin_fs2 *p, fs2_user_auth hook);

in the init_plugin function. The fs2_user_auth takes two arguments: username and password. It should return 0 if the credentials are valid or -1 otherwise.

If your implementation is done, compile the code to a library and put it into the FLOPSAR_HOME/lib directory. You must also update the manager configuration file and replace the plugins option value libfs2plg_authbasic.so with the full name of your library.