Developing new metrics plugins¶
It is possible to extend Optimizer Runtime by writing plugins for specific hardware or software applications.
The supplied header file metricsPlugin.h
can be used to develop a plugin to Optimizer Runtime for sampling metrics. Optimizer Runtime will
call this plugin's sample_*()
functions:
sample_system()
will be called for sampling system-wide eventssample_socket()
will be called for sampling socket-wide events. On a system with several physical chips, this function will be called concurrently for every socket. The calling thread will be affined by Optimizer Runtime to a logical cpu on the respective socket.sample_cpu()
will be called for sampling per-logical-cpu events. This function will be called concurrently for each logical cpu. The calling thread will be affined by Optimizer Runtime to the respective logical cpu.
The sample*()
functions will then send their sampled metrics to the MetricsPluginData object by using
the ::insert()
method of that class. The Metric struct, once passed to Optimizer Runtime, should not be
deleted as long as the plugin is alive.
Upon initialization, Optimizer Runtime will pass metrics parameters that were defined in the knobs.yaml file
by invoking calls to set_metric_parameter()
.
An example plugin¶
Below is an example of a plugin:
/*
* examplePlugin.h
*
* This example plugin returns an aggregated counter normalized by time,
* and will appear under "example.my_counter" metric name
*
*/
#include "metricsPlugin.h"
class examplePlugin : public MetricsPlugin {
public:
examplePlugin();
~examplePlugin();
void sample_system(MetricsPluginData *current_values, int phase) override;
std::string get_name();
private:
int m_counter;
MetricsPlugin::Metric m_metric;
};
examplePlugin::examplePlugin() {
m_metric.name="my_counter";
m_metric.aggregated=true;
m_metric.normalize_by="duration";
m_counter=0;
}
void examplePlugin::sample_system(MetricsPluginData *current_values, int phase) {
current_values->insert(m_metric,m_counter++);
}
std::string examplePlugin::get_name() {
return "example";
}
examplePlugin::~examplePlugin() {
}
extern "C" MetricsPlugin* create_object() {
return new examplePlugin;
}
extern "C" void destroy_object( MetricsPlugin* object ) {
delete (examplePlugin *) object;
}
Compiling a plugin library¶
To compile the example in examplePlugin.cpp:
$ g++ -fpic -shared -o libexample-metrics.so examplePlugin.cpp
Using a custom plugin¶
This will create a shared object by the name of libexample-metrics.so In order to load it, it needs to be specified in knobs.yaml:
domains:
common:
plugins: [/path/to/libexample-metrics.so]
include_metrics: [example.my_counter]
On startup, if the library was loaded successfully Optimizer Runtime will report:
Metrics plugin /path/to/libexample-metrics.so loaded successfully with name: example
Passing parameters to a plugin¶
It is possible to configure a custom plugin via knobs.yaml
as follows:
domains:
common:
metrics:
example.my_metric:
key: value
When the example
plugin is loaded, Optimizer Runtime will invoke:
`example_plugin->set_metric_parameter("my_metric","key","value");`
Using the "file" plugin¶
Metrics can be defined using the included file plugin libfile-metrics
. Below is an example of a metric that is read from a file:
domains:
common:
metrics:
mymetric:
kind: file
type: plaintext
path: /tmp/metric
aggregated: true
normalize_by: duration
plugins: [libfile-metrics.so]
The metric names should have at least kind
and path
parameters. kind
specifies the kind of an object, while path
specifies the path of file that has the metric value. The optional parameter type
can be either plaintext or text. The optional parameter aggregated
can be either true or false. The optional parameter normalize_by
defines how this metric will be normalized. It can either be by duration, performance, or by any other metric. The defaults for the optional parameters are: aggregated="false", normalize_by="" and type = "plaintext".
Using the "shell" plugin¶
It is also possible to define metrics using shell scripts using the included plugin libshell-metrics
. Below is an example of a metric that is read from a file:
domains:
common:
metrics:
mymetric:
kind: shell
sample_script: cat /tmp/metric
aggregated: true
normalize_by: duration
plugins: [libshell-metrics.so]
The metric names should have at least kind
and sample_script
parameters. kind
specifies the kind of an object, while sample_script
defines script that returns the value of the
metric. The optional parameter aggregated
can be either true or false. The optional parameter normalize_by
defines how this metric
will be normalized. It can either be by duration, performance, or by any other metric.