1. Agent API

If you want to provide your own, non-JVM, data and store them in the Flopsar Suite 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.2.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.

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. The standard formatter is embedded in agent and all you need to do is to select which arguments you want to dump. This formatter will execute the following method on each of your selected arguments

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

and return a result in a form of concatenated pairs of argument number and the corresponding valueOf function result. However, if you want to extract some additional information 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.Object1 obj1 = (foo.bar.Object1)args[0];
                foo.bar.Object2 obj2 = (foo.bar.Object2)args[1];
                /*
                 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. FDBC

workstation makes use of fdbc in order to access data stored in both manager and database. fdbc is a single jar file flopsar-fdbc-2.2.jar and it provides whatever is necessary to access data from any client. This includes remote access to manager and database instances, managing Flopsar environment and querying data. You can even write your own GUI client to manage your entire Flopsar environment without using workstation. Beside the fdbc jar file, the Flopsar distribution contains the FDBC API documentation in the flopsar-fdbc-2.2-javadoc.jar file.

3.1. API

The fdbc API is divided into two parts with respect to the instance it wants to access. The com.flopsar.fdbc.api.fsm package contains classes reponsible for accessing manager instances, while com.flopsar.fdbc.api.fdb package database instances.

3.1.1. Manager API

In order to access some manager instance, you must use the following method:

public static ConnectionFSM createConnection(String host,\
        int port,\
        String username,\
        String password,\
        EventHandlerFSM notification,\
        long requestTimeout);

When the above method succeeds, you have a valid connection object that can be used to manage your Flopsar environment. Please, refer to the API documentation for usage details.

3.1.2. Database API

In order to access some database instance, you must use the following method:

public static ConnectionFDB createConnection(String host,\
        int port,\
        EventHandlerFDB handler,\
        long requestTimeout);

When the above method succeeds, you have a valid connection object that can be used to query data from the database instance. This connection does not require authentication. Please, refer to the API documentation for usage details.

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 are two plugins currently available: authentication and notification and each of them can be replaced.

Flopsar provides a C API for writing custom implementations of plugins. In order to write a pluginfootnote{Every plugin should include this header.}, you need to include in your project the main header fs2plugin_api.h file, which can be found in FLOPSAR_HOME/resources/api 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 --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.

4.2. Plugin: Notification

Flopsar provides the SMTP plugin used for notification purposes. However, you can always implement your own plugin to replace our implementation with a new one. In order to write a custom notification plugin, you must include an additional header fs2plugin_api_notify.h file. All you have to do is implement the function below:

typedef void (*fs2plg_notify)(uint64_t uuid1,\
                      uint64_t uuid2,\
                      uint64_t value,\
                      const char *agent,\
                      const char *component,\
                      uint64_t time_window);

where uuid1 and uuid2 arguments identify an alert rule, value denotes the evaluated rule value, agent denotes the agents name, component denotes a component name and time_window denotes the rule time window. This function should be registered then using the function below:

void fs2_register_notify_hook(struct plugin_fs2 *p,fs2plg_notify hook);

in the init_plugin function.