-
Notifications
You must be signed in to change notification settings - Fork 1
ldmsd sampler dev
ldmsd-sampler-dev - LDMSD sampler plugin development guide
#include "ldmsd_plugin.h"
#include "ldmsd_sampler.h"
ldmsd
(LDMS Daemon) uses sampler plugin instances to read data from the
sources and put them into LDMS sets. A sampler plugin instance is a C extended
structure of ldmsd_plugin_inst_s
. Each sampler instance has a copy of
ldmsd_sampler_type_s
structure (an extension of ldmsd_plugin_type_s
)
associated with it. ldmsd_plugin_inst_s.base
points to ldmsd_sampler_type_s
,
and ldmsd_sampler_type_s.base.inst
points back to the instance as depicted
below:
.-----------------------.
| inst extension |
|-----------------------| .-----------------------.
| .-------------------. | | ldmsd_sampler_type_s |
| |ldmsd_plugin_inst_s| | |-----------------------|
| |-------------------| | | .-------------------. |
| | base ------------+-+------->| |ldmsd_plugin_type_s| |
| | | | | |-------------------| |
| | INSTANCE APIs | |<-------+-+-inst | |
| '-------------------' | | | | |
| | | | PLUGIN APIs | |
| EXTENSION DATA | | '-------------------' |
'-----------------------' | |
| SAMPLER APIs |
'-----------------------'
ldmsd
uses APIs defined in ldmsd_plugin_inst_s
, ldmsd_plugin_type_s
and
ldmsd_sampler_type_s
(the sampler type extension) to communicate with the
plugin sampler instance. The inst extension part usually holds
plugin-instance-specific information such as states and file descriptors. The
extended instance structure serves an instnace object to the ldmsd
(it will
see the structure as ldmsd_plugin_inst_s
). The plugin implementation can see
the extended instance structure as self
in Python or this
in C++.
The interactions between ldmsd
and a sampler plugin instance can be summarized
as follows:
- instance creation
- `ldmsd` create a plugin instance upon a `load` user request (see [Creating an Instance](#creating-an-instance)) by calling `new()` function in the plugin library. The plugin then allocate the memory to hold the extended instance structure and setup INSTANCE APIs. At this point, the plugin instance does not have `ldmsd_sampler_type_s` associated with it yet. `ldmsd` will inspect the `ldmsd_plugin_inst_s.type` (must be `LDMSD_SAMPLER_TYPENAME` in this case) and create a copy of `ldmsd_sampler_type_s` after `new()` has returned.
- sampler instance initialization
- After `new()` has returned, and a copy of `ldmsd_sampler_type_s` has been created and linked with the instance by `ldmsd`, `ldmsd_plugin_inst_s.init()` is called to let the plugin further setup the SAMPLER APIs. Additional plugin resources could be initialized during the init call as well.
- configuration
- `ldmsd` configure the plugin instance when the user gave `config` command. The configuration attributes from the command are passed along to the plugin config function (see [Config](#config) subsection). After a successful config, the plugin became configured and is ready to be sampled by `smplr` sampler policy (see [ldmsd-sampler][ldmsd-sampler](7)). Some plugin may need multiple `config` call to be *configured*.
- sampling
- After the plugin instance became *configured*, and after `smplr` started, `sample()` API will be periodically called (see [Sample](#sample)). The periodic calls will keep coming until the associated `smplr` is stopped.
- deletion
- After the associated `smplr` stopped, and a user `term` request for the instance, the sampler instance will be deleted (see [Deletion of Sampler Plugin Instance](#deletion-of-sampler-plugin-instance)).
We will implement a thermal
sampler in the this guide to illustrate how to
implement an LDMSD sampler plugin in the following subsections:
Preparation
Conventions
Extending Plugin Instance
Creating an Instance
Help and Description
Initialization
Sampler APIs
Config
Createing a Schema and a Set
Sample
This step is for developing a sampler plugin in ovis development tree
(recommended). If you are developing a plugin outside of ovis development tree,
you can skip this step, and have to make sure that the plugin links with
libsampler.so
.
Please follow these steps to prepare a workspace for developing thermal
sampler:
1) Create a sub directory thermal
in ldms/src/ldmsd-samplers
.
2) Create a Makefile.am
and a (or several) C source file for the plugin
(thermal.c
for this example). The Makefile.am
should look like the
following:
# file: ldms/src/ldmsd-samplers/thermal/Makefile.am
include ../common.am
pkglib_LTLIBRARIES = libthermal.la
libthermal_la_SOURCES = thermal.c
libthermal_la_CFLAGS = $(SAMPLER_CFLAGS)
libthermal_la_LIBADD = $(SAMPLER_LIBADD)
libthermal_la_LDFLAGS = $(SAMPLER_LDFLAGS)
The ../common.am
defines SAMPLER_CFLAGS
, SAMPLER_LIBADD
and
SAMPLER_LDFLAGS
variables containing necessary artifacts to build the plugin.
3) Edit ldms/configure.ac
, add an option for the sampler, and add the
Makefile
in "2)" in the AC_CONFIG_FILES
list as follows:
dnl Options for sampler
...
OPTION_DEFAULT_DISABLE([thermal], [ENABLE_THERMAL])
...
AC_CONFIG_FILES([Makefile src/Makefile src/core/Makefile
...
src/thermal/Makefile
...
])
...
Please note that the paths in ldms/configure.ac
is relative to ldms/
directory (where the autoconf script resides).
OPTION_DEFAULT_DISABLE
macro is used so that the plugin won't be build unless
the user specify --enable-thermal
configure option. In the case that the
plugin does not depend on extra libraries other than those required by ldmsd
,
we may use OPTION_DEFAULT_ENABLE
macro to have it build by default (unless the
user specify --disable-thermal
configure option).
In the case of extra dependencies, please also add a library / header checking
logic in the ldms/configure.ac
.
4) Edit ldms/src/ldmsd-samplers/Makefile.am
and add thermal
as a
conditional build subdirectory:
# file: ldms/src/ldmsd-samplers/Makefile.am
...
if ENABLE_THERMAL
SUBDIRS += thermal
endif
...
5) (Optional) For convenience, the template
ldms/templates/sampler_template.c
can be copied to
ldms/src/ldmsd-samplers/thermal/thermal.c
as a starting point of development.
Functions of the plugin are static
, except for new()
function. The name
of the plugin functions are preferably prefixed with plugin name for
readability (e.g. static int thermal_init(ldmsd_plugin_inst_t pi)
).
The name of the extended instance structure is preferably struct <PLUGIN_NAME>_inst_s
(e.g. struct thermal_inst_s
).
To extend a sample plugin instance, simply define a new structure with struct ldmsd_plugin_inst_s
as the first member. It is conventional to name the element
base
. The following is an example for thermal
:
/* file: ldms/src/ldmsd-samplers/thermal/thermal.c */
...
typedef struct thermal_inst_s *thermal_inst_t;
struct thermal_inst_s {
struct ldmsd_plugin_inst_s base;
int zone; /* zone to monitor */
int fd; /* file descriptor to the thermal temperature file */
};
...
The sampler plugin implementation must implement ldmsd_plugin_inst_t new()
function. This function is called by ldmsd
when it needs to create an instance
of the plugin (when load
ldmsd config command is processed).
new()
function must allocate memory for the newly created instance and
setup the instance APIs. The following is an example for thermal
sampler:
/* file: ldms/src/ldmsd-samplers/thermal/thermal.c */
...
/* global structure for setting up instance APIs and some default values */
struct thermal_inst_s __inst = {
.base = {
/* must get version from this macro */
.version = LDMSD_PLUGIN_VERSION_INITIALIZER,
/* type must be LDMSD_SAMPLER_TYPENAME */
.type_name = LDMSD_SAMPLER_TYPENAME,
.plugin_name = "thermal",
/* Common Plugin APIs, these functions are to be implemented */
.desc = thermal_desc,
.help = thermal_help,
.init = thermal_init,
.del = thermal_del,
.config = thermal_config,
},
.zone = 0,
.fd = -1,
};
ldmsd_plugin_inst_t new()
{
thermal_inst_t inst = malloc(sizeof(*inst));
if (inst)
*inst = __inst; /* copy __inst value above */
return &inst->base;
}
...
At this point, the corresponding ldmsd_sampler_type_s
has not been created and
paired with this instance yet. ldmsd
will handle the creation and pairing
after new()
returned.
The ldmsd_plugin_inst_s.desc()
interface is for a short description of the
plugin, and ldmsd_plugin_inst_s.help()
interface is for a long help text
describing how to use/configure the plugin instance. The thermal
description
and help implemntation is as the following:
/* file: ldms/src/ldmsd-samplers/thermal/thermal.c */
...
static const char *thermal_desc(ldmsd_plugin_inst_t pi)
{
return "thermal - /sys/class/thermal sampler";
}
static const char *thermal_help(ldmsd_plugin_inst_t pi)
{
return "thermal config synopsis:\n"
" config name=INST [COMMON OPTIONS] zone=INT\n"
"\n"
"Descriptions:\n"
" `zone` option is an integer specifying the zone\n"
" in /sys/class/thermal/ to monitor\n";
}
...
After the plugin instance is created by new()
, and ldmsd
successfully link
it to a copy of ldmsd_sampler_type_s
, ldmsd_plugin_inst_s.init()
is called
to initialize the plugin instance. The plugin is expected to initialize its
resources during this call. Some plugin that relies on static files that
requires no configuration call may decide to open those files during init.
The sampler plugin must implement ldmsd_sampler_type_s.update_schema()
to
define plugin-specific metrics, and ldmsd_sampler_type_s.update_set()
to
update values of plugin-specific metrics in the set. These two functions need to
be set in ldmsd_plugin_inst_s.init()
. The following is an example of init
function of thermal
sampler:
static int thermal_init(ldmsd_plugin_inst_t pi)
{
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
samp->update_schema = thermal_update_schema;
samp->update_set = thermal_update_set;
/* ((thermal_inst_t)pi)->fd has already been initialized in `new()` */
return 0;
}
The APIs in ldmsd_sampler_type_s
are for ldmsd
to communicate to the sampler
plugin instance (e.g. tell plugin instance to populate data set), and for
sampler plugin to make a request to ldmsd
(e.g. creating a set). If the plugin
implementation decides to override an API, it should do so in
ldmsd_plugin_inst_s.init()
. The plugin implementation can access the
associated ldmsd_sampler_type_s
by using a convenient LDMSD_SAMPLER()
macro.
You will see the usage of these APIs in the upcoming subsections.
The following is a list of sampler APIs and their descriptions.
- ldmsd_sampler_type_s.create_schema()
-
This API is meant to be called by the sampler plugin implementation when it
needs to create and construct an LDMS schema (e.g. before creating a set). This
function will create a new LDMS schema object and add common metrics (e.g.
component_id
,job_id
) to the schema. Then, this function callsldmsd_sampler_type_s.update_schema()
which is expected to be overridden by sampler plugin implementation to add plugin-specific metrics into the schema.
The plugin implementation must not override this function. - ldmsd_sampler_type_s.update_schema()
-
The plugin implementation should override this function to add metrics to the
supplied schema. This function will be called as a subsequent call of
ldmsd_sampler_type_s.create_schema()
. - ldmsd_sampler_type_s.create_set()
-
This API is meant to be called by the sampler plugin, and not to be overridden.
The sampler plugin call this API to create an LDMS set (with schema created from
ldmsd_sampler_type_s.create_schema()
). A sampler plugin may create multiple sets. However, please mind that the set name must be unique in theldmsd
.
If the set has been created successfully, it is added into theldmsd_sampler_type_s.set_list
withldmsd_set_entry_s
wrapping theldms_set_t
. - ldmsd_sampler_type_s.sample()
-
This is an API that is called by
ldmsd
to populate data in the sets created by the sampler plugin instance. The default implementation is to go through sets inldmsd_sampler_type_s.set_list
. For each set, begin LDMS transaction then callldmsd_sampler_type_s.base_update_set()
to update the common metrics (e.g.job_id
). Next, callldmsd_sampler_type_s.update_set()
to update sample-specific metrics, and finally end the LDMS transaction.
The sampler plugin implementation can override this function. - ldmsd_sampler_type_s.base_update_set()
-
The sampler plugin must not override this function.
This function updates the common metrics portion of the set created byldmsd_sampler_type_s.create_set()
, which is called by the default implementation ofldmsd_sampler_type_s.sample()
. If the sampler plugin implementation overridesldmsd_sampler_type_s.sample()
, it should call this function to update the common metrics part of the set. - ldmsd_sampler_type_s.update_set()
-
The plugin implementation is expected to override this API to populate
plugin-specific metrics. This function is a subsequence call from the default
implementation of
ldmsd_sampler_type_s.sample()
. - ldmsd_sampler_type_s.delete_set()
-
The sampler plugin must not override this function.
This is an API for the sampler plugin implementation to call to delete an LDMS set created fromldmsd_sampler_type_s.create_set()
.
*NOTE:* The sets created byldmsd_sampler_type_s.create_set()
will also be automatically deleted when the plugin instance is deleted.
The following is thermal
implementation of sampler API:
...
static int
thermal_update_schema(ldmsd_plugin_inst_t pi, ldms_schema_t sch)
{
int rc;
rc = ldms_schema_metric_add(sch, "temp", LDMS_V_U64, "mC");
/* NOTE: ldms_schema_metric_add() returns metric index (>=0) on
* success, or `-errno` on error. */
if (rc < 0)
return -rc; /* rc == -errno */
return 0; /* succeeded, return no error */
}
static int
thermal_update_set(ldmsd_plugin_inst_t pi, ldms_set_t set, void *ctxt)
{
thermal_inst_t inst = (void*)pi;
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
char buff[64];
int rc;
uint64_t val;
rc = lseek(inst->fd, 0, SEEK_SET);
if (rc)
return errno; /* seek failed */
rc = read(inst->fd, buff, sizeof(buff));
if (rc < 0)
return errno; /* read failed */
val = strtoul(buff, NULL, 10);
/* `samp->first_idx` is the index of the first plugin-specific
* metric we added in thermal_update_schema(). This is
* maintained by `ldmsd`. */
ldms_metric_set_u64(set, samp->first_idx, val);
return 0;
}
...
After new()
and ldmsd_plugin_inst_s.init()
(corresponding to the user's
load
command), ldmsd_plugin_inst_s.config()
is called when the user gave
config
command. For example:
load name=t plugin=thermal
config name=t zone=0
The configuration attributes are passed along to ldmsd_plugin_inst_s.config()
API by ldmsd
via json
parameter (see json_util.h). If
ldmsd_plugin_inst_s.config()
is not implemented (NULL
), the base
ldmsd_plugin_type_s.config()
is called instead.
ldmsd_plugin_inst_s.config()
implementation should also call
ldmsd_plugin_type_s.config()
to process the common configuration attributes
(e.g. producer
and component_id
). It is quite common among samplers to
create LDMS sets in config function.
The following is the config implementaion of thermal
:
static int
thermal_config(ldmsd_plugin_inst_t pi, json_entity_t json,
char *ebuf, int ebufsz)
{
thermal_inst_t inst = (void*)pi;
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
ldms_schema_t sch;
ldms_set_t set;
const char *val;
char path[128];
int rc;
if (inst->fd >= 0) {
/* reconfigure detected */
snprintf(ebuf, ebufsz, "Reconfiguration is not supported.");
return EINVAL;
}
rc = samp->base.config(pi, json, ebuf, ebufsz);
if (rc)
return rc; /* base config should have `ebuf` filled */
val = json_attr_find_str(json, "zone");
if (val) {
/* `zone` is given */
inst->zone = atoi(val);
}
/* open temperature file */
snprintf(path, sizeof(path),
"/sys/class/thermal/thermal_zone%d/temp", inst->zone);
inst->fd = open(path, O_RDONLY);
if (inst->fd < 0) {
snprintf(ebuf, ebufsz, "Error %d opening file: %s",
errno, path);
return errno;
}
/* create schema and set */
sch = samp->create_schema(pi);
if (!sch) {
snprintf(ebuf, ebufsz, "Schema creation error: %d", errno);
return errno;
}
set = samp->create_set(pi, samp->set_inst_name, sch, NULL);
/* NOTE: samp->set_inst_name is the set instance name obtained from
* the `instance` config option (by samp->base.config()).
*/
ldms_schema_delete(sch); /* 1-time use */
if (!set) {
snprintf(ebuf, ebufsz, "Set creation failed: %d", errno);
return errno;
}
return 0;
}
An LDMS set of the sampler plugin should be created by
ldmsd_sampler_type_s.create_set()
API, with a schema created from
ldmsd_sampler_type_s.create_schema()
as the following snippet:
sch = samp->create_schema(pi);
set = samp->create_set(pi, SET_NAME, sch, CTXT);
The set usually get created in config function (as seen in Config subsection). However, the plugin implementation can create sets anytime.
ldmsd_sampler_type_s.create_schema()
subsequently calls
ldmsd_sampler_type_s.update_schema()
to add plugin-specific metrics to the
schema. The following is the update_schema()
implementation of thermal
sampler:
/* part of `thermal.c` */
static int
thermal_update_schema(ldmsd_plugin_inst_t pi, ldms_schema_t sch)
{
int rc;
rc = ldms_schema_metric_add(sch, "temp", LDMS_V_U64, "mC");
/* NOTE: ldms_schema_metric_add() returns metric index (>=0) on
* success, or `-errno` on error. */
if (rc < 0)
return -rc; /* rc == -errno */
return 0; /* succeeded, return no error */
}
If a sampler policy (see smplr
in ldmsd-sampler) is setup and
associates with the sampler plugin instance, the ldmsd_sampler_type_s.sample()
is called periodically by ldmsd
. The default implementation of the sample
function is to iterate through the ldmsd_sampler_type_s.set_list
, and update
the data for each set by calling ldmsd_sampler_type_s.base_update_set()
and
ldmsd_sampler_type_s.update_set()
for common metrics and plugin-specific
metrics respectively. The following is the update_set()
implementation of
thermal
sampler:
/* part of `thermal.c` */
static int
thermal_update_set(ldmsd_plugin_inst_t pi, ldms_set_t set, void *ctxt)
{
thermal_inst_t inst = (void*)pi;
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
char buff[64];
int rc;
uint64_t val;
rc = lseek(inst->fd, 0, SEEK_SET);
if (rc)
return errno; /* seek failed */
rc = read(inst->fd, buff, sizeof(buff));
if (rc < 0)
return errno; /* read failed */
val = strtoul(buff, NULL, 10);
/* `samp->first_idx` is the index of the first plugin-specific
* metric we added in thermal_update_schema(). This is
* maintained by `ldmsd`. */
ldms_metric_set_u64(set, samp->first_idx, val);
return 0;
}
A plugin instance can be deleted upon user request (term
command). The
ldmsd_plugin_inst_s.del()
is called to let the plugin implementation clear
instnace-specific resources. The plugin implementation must NOT free the
instance itself. ldmsd
will free the instance afterward.
The following is del()
implementation of thermal
sampler:
/* part of `thermal.c` */
static void
thermal_del(ldmsd_plugin_inst_t pi)
{
thermal_inst_t inst = (void*)pi;
if (inst->fd >= 0)
close(inst->fd);
}
This section contain the complete code that we have been building through the guide.
This is the full content of thermal.c
:
/* file: ldms/src/ldmsd-samplers/thermal/thermal.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ldmsd.h"
#include "ldmsd_sampler.h"
#define INST(x) ((ldmsd_plugin_inst_t)(x))
#define INST_LOG(inst, lvl, fmt, ...) \
ldmsd_log((lvl), "%s: " fmt, INST(inst)->inst_name, \
##__VA_ARGS__)
typedef struct thermal_inst_s *thermal_inst_t;
struct thermal_inst_s {
struct ldmsd_plugin_inst_s base;
int zone; /* zone to monitor */
int fd; /* file descriptor to the thermal temperature file */
};
/* ============== Sampler Plugin APIs ================= */
static int
thermal_update_schema(ldmsd_plugin_inst_t pi, ldms_schema_t sch)
{
int rc;
rc = ldms_schema_metric_add(sch, "temp", LDMS_V_U64, "mC");
/* NOTE: ldms_schema_metric_add() returns metric index (>=0) on
* success, or `-errno` on error. */
if (rc < 0)
return -rc; /* rc == -errno */
return 0; /* succeeded, return no error */
}
static int
thermal_update_set(ldmsd_plugin_inst_t pi, ldms_set_t set, void *ctxt)
{
thermal_inst_t inst = (void*)pi;
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
char buff[64];
int rc;
uint64_t val;
rc = lseek(inst->fd, 0, SEEK_SET);
if (rc)
return errno; /* seek failed */
rc = read(inst->fd, buff, sizeof(buff));
if (rc < 0)
return errno; /* read failed */
val = strtoul(buff, NULL, 10);
/* `samp->first_idx` is the index of the first plugin-specific
* metric we added in thermal_update_schema(). This is
* maintained by `ldmsd`. */
ldms_metric_set_u64(set, samp->first_idx, val);
return 0;
}
/* ============== Common Plugin APIs ================= */
static const char *
thermal_desc(ldmsd_plugin_inst_t pi)
{
return "thermal - /sys/class/thermal sampler";
}
static const char *
thermal_help(ldmsd_plugin_inst_t pi)
{
return "thermal config synopsis:\n"
" config name=INST [COMMON OPTIONS] zone=INT\n"
"\n"
"Descriptions:\n"
" `zone` option is an integer specifying the zone\n"
" in /sys/class/thermal/ to monitor\n";
}
static int
thermal_config(ldmsd_plugin_inst_t pi, json_entity_t json,
char *ebuf, int ebufsz)
{
thermal_inst_t inst = (void*)pi;
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
ldms_schema_t sch;
ldms_set_t set;
const char *val;
char path[128];
int rc;
if (inst->fd >= 0) {
/* reconfigure detected */
snprintf(ebuf, ebufsz, "Reconfiguration is not supported.");
return EINVAL;
}
rc = samp->base.config(pi, json, ebuf, ebufsz);
if (rc)
return rc; /* base config should have `ebuf` filled */
val = json_attr_find_str(json, "zone");
if (val) {
/* `zone` is given */
inst->zone = atoi(val);
}
/* open temperature file */
snprintf(path, sizeof(path),
"/sys/class/thermal/thermal_zone%d/temp", inst->zone);
inst->fd = open(path, O_RDONLY);
if (inst->fd < 0) {
snprintf(ebuf, ebufsz, "Error %d opening file: %s",
errno, path);
return errno;
}
/* create schema and set */
sch = samp->create_schema(pi);
if (!sch) {
snprintf(ebuf, ebufsz, "Schema creation error: %d", errno);
return errno;
}
set = samp->create_set(pi, samp->set_inst_name, sch, NULL);
/* NOTE: samp->set_inst_name is the set instance name obtained from
* the `instance` config option (by samp->base.config()).
*/
ldms_schema_delete(sch); /* 1-time use */
if (!set) {
snprintf(ebuf, ebufsz, "Set creation failed: %d", errno);
return errno;
}
return 0;
}
static void
thermal_del(ldmsd_plugin_inst_t pi)
{
thermal_inst_t inst = (void*)pi;
if (inst->fd >= 0)
close(inst->fd);
}
static int
thermal_init(ldmsd_plugin_inst_t pi)
{
ldmsd_sampler_type_t samp = LDMSD_SAMPLER(pi);
samp->update_schema = thermal_update_schema;
samp->update_set = thermal_update_set;
/* ((thermal_inst_t)pi)->fd has already been initialized in `new()` */
return 0;
}
/* global structure for setting up instance APIs and some default values */
struct thermal_inst_s __inst = {
.base = {
/* must get version from this macro */
.version = LDMSD_PLUGIN_VERSION_INITIALIZER,
/* type must be LDMSD_SAMPLER_TYPENAME */
.type_name = LDMSD_SAMPLER_TYPENAME,
.plugin_name = "thermal",
/* Common Plugin APIs, these functions are to be implemented */
.desc = thermal_desc,
.help = thermal_help,
.init = thermal_init,
.del = thermal_del,
.config = thermal_config,
},
.zone = 0,
.fd = -1,
};
ldmsd_plugin_inst_t new()
{
thermal_inst_t inst = malloc(sizeof(*inst));
if (inst)
*inst = __inst; /* copy __inst value above */
return &inst->base;
}
/* EOF */
This is the Makefile for building thermal
sampler:
# file: ldms/src/ldmsd-samplers/thermal/Makefile.am
include ../common.am
pkglib_LTLIBRARIES = libthermal.la
libthermal_la_SOURCES = thermal.c
libthermal_la_CFLAGS = $(SAMPLER_CFLAGS)
libthermal_la_LIBADD = $(SAMPLER_LIBADD)
libthermal_la_LDFLAGS = $(SAMPLER_LDFLAGS)
The following diff shows the modification to configure and Makefile relating to
the build of thermal
sampler:
--- a/ldms/configure.ac
+++ b/ldms/configure.ac
@@ -143,6 +143,8 @@ OPTION_DEFAULT_DISABLE([ibm_occ], [ENABLE_IBM_OCC_SAMPLER])
OPTION_DEFAULT_DISABLE([appinfo], [ENABLE_APPINFO])
OPTION_DEFAULT_DISABLE([test_sampler], [ENABLE_TEST_SAMPLER])
+OPTION_DEFAULT_DISABLE([thermal], [ENABLE_THERMAL])
+
dnl test_sampler will also build with --enable-ldms-test
AM_CONDITIONAL([ENABLE_TEST_SAMPLER_LDMS_TEST], [test "x$ENABLE_LDMS_TEST_FALSE" = "
OPTION_DEFAULT_DISABLE([grptest], [ENABLE_GRPTEST])
@@ -517,6 +519,7 @@ AC_CONFIG_FILES([Makefile src/Makefile src/core/Makefile
src/ldmsd-samplers/shm/shm_util/Makefile
src/ldmsd-samplers/shm/mpi_profiler/Makefile
src/ldmsd-samplers/filesingle/Makefile
+ src/ldmsd-samplers/thermal/Makefile
src/ldmsd-stores/Makefile
src/ldmsd-stores/store_sos/Makefile
src/ldmsd-stores/store_csv/Makefile
--- a/ldms/src/ldmsd-samplers/Makefile.am
+++ b/ldms/src/ldmsd-samplers/Makefile.am
@@ -129,3 +129,7 @@ endif
if ENABLE_FILESINGLE
SUBDIRS += filesingle
endif
+
+if ENABLE_THERMAL
+SUBDIRS += thermal
+endif
The following steps will build ldms with thermal
sampler.
$ cd ldms/
$ ./autogen.sh
$ mkdir build
$ cd build/
$ ../configure --prefix=/opt/ldms --with-ovis-lib=/opt/ovis-lib \
--enable-thermal
$ make && make install
The following is the config file for the ldmsd
sampler with one thermal
sampler monitoring zone2
:
# file: samp.conf
load name=zone2 plugin=thermal
config name=zone2 zone=2
smplr_add name=smplr instance=zone2
smplr_start name=smplr interval=1000000 offset=0
Then, we can test-run the sampler daemon in foreground mode as follows:
$ ldmsd -F -c samp.conf -x sock:10001 -v INFO
ldms_ls
to the daemon to verify the sampler result:
$ ldms_ls -x sock -p 10001 -l
bla:10001/zone2: consistent, last update: Thu May 16 15:47:20 2019 -0500 [82us]
D u64 component_id 0
D u64 job_id 0
D u64 app_id 0
D u64 temp 39000 mC
This is a list of files in the source tree related to this tutorial.
- ldms/templates/sampler_template.c
- The template to implement a sampler plugin.
- ldms/configure.ac
-
The
autoconf
file of ldms project that needs to be modified to include new option and Makefile for the new plugin. - ldms/src/ldmsd-samplers/
- The directory hosting ldmsd sampler plugin subdirectories.
- ldms/src/ldmsd-samplers/Makefile.am
-
The automake file containing conditional
SUBDIRS
list to build sampler plugins. - ldms/src/ldmsd-samplers/common.am
-
The automake file to be
include
, containing useful variables for building ldmsd sampler plugins.
ldmsd-sampler(7) ldmsd-store-dev(7)
- Home
- Search
- Feature Overview
- LDMS Data Facilitates Analysis
- Contributing patches
- User Group Meeting Notes - BiWeekly!
- Publications
- News - now in Discussions
- Mailing Lists
- Help
Tutorials are available at the conference websites
- Coming soon!
- Testing Overview
- Test Plans & Documentation: ldms-test
- Man pages currently not posted, but they are available in the source and build
V3 has been deprecated and will be removed soon
- Configuring
- Configuration Considerations
- Running