.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "PMDA 3pm"
.TH PMDA 3pm "2023-05-07" "perl v5.36.0" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
PCP::PMDA \- Perl extension for Performance Metrics Domain Agents
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 1
\&  use PCP::PMDA;
\&
\&  $pmda = PCP::PMDA\->new(\*(Aqmyname\*(Aq, $MYDOMAIN);
\&
\&  $pmda\->connect_pmcd;
\&
\&  $pmda\->add_metric($pmid, $type, $indom, $sem, $units, \*(Aqname\*(Aq, \*(Aq\*(Aq, \*(Aq\*(Aq);
\&  $pmda\->add_indom($indom, [0 => \*(Aqwhite\*(Aq, 1 => \*(Aqblack\*(Aq, ...], \*(Aq\*(Aq, \*(Aq\*(Aq);
\&
\&  $pmda\->set_fetch(\e&fetch_method);
\&  $pmda\->set_refresh(\e&refresh_method);
\&  $pmda\->set_instance(\e&instance_method);
\&  $pmda\->set_fetch_callback(\e&fetch_callback_method);
\&  $pmda\->set_store_callback(\e&store_callback_method);
\&
\&  $pmda\->set_user(\*(Aqpcp\*(Aq);
\&
\&  $pmda\->run;
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
The \s-1PCP::PMDA\s0 Perl module contains the language bindings for
building Performance Metric Domain Agents (PMDAs) using Perl.
Each \s-1PMDA\s0 exports performance data for one specific domain, for
example the operating system kernel, Cisco routers, a database,
an application, etc.
.SH "METHODS"
.IX Header "METHODS"
.IP "\s-1PCP::PMDA\-\s0>new(name, domain)" 4
.IX Item "PCP::PMDA->new(name, domain)"
\&\s-1PCP::PMDA\s0 class constructor.  \fIname\fR is a string that becomes the
name of the \s-1PMDA\s0 for messages and default prefix for the names of
external files used by the \s-1PMDA.\s0  \fIdomain\fR is an integer domain
number for the \s-1PMDA,\s0 usually from the register of domain numbers
found in \fB\f(CB$PCP_VAR_DIR\fB/pmns/stdpmid\fR.
.ie n .IP "$pmda\->\fBrun()\fR" 4
.el .IP "\f(CW$pmda\fR\->\fBrun()\fR" 4
.IX Item "$pmda->run()"
Once all local setup is complete (i.e. instance domains and metrics
are registered, callbacks registered \- as discussed below) the \s-1PMDA\s0
must connect to \fBpmcd\fR(1) to complete its initialisation and begin
answering client requests for its metrics.  This is the role performed
by \fIrun\fR, and upon invoking it all interaction within the \s-1PMDA\s0 is
done via callback routines (that is to say, under normal cicrumstances,
the \fIrun\fR routine does not return).
.Sp
The behaviour of the \fIrun\fR method is different in the presence of
either the \fB\s-1PCP_PERL_PMNS\s0\fR or \fB\s-1PCP_PERL_DOMAIN\s0\fR environment variables.
These can be used to generate the namespace or domain number files,
which are used as part of the \s-1PMDA\s0 installation process.
.ie n .IP "$pmda\->\fBconnect_pmcd()\fR" 4
.el .IP "\f(CW$pmda\fR\->\fBconnect_pmcd()\fR" 4
.IX Item "$pmda->connect_pmcd()"
Allows the \s-1PMDA\s0 to set up the \s-1IPC\s0 channel to \fBpmcd\fR(1) and complete
the credentials handshake with \fBpmcd\fR(1).  If \fIconnect_pmcd\fR is not
explicitly called the setup and handshake will be done when the
\&\fIrun\fR method is called.
.Sp
The advantage of explicitly calling \fIconnect_pmcd\fR early in the life
of the \s-1PMDA\s0 is that this reduces the risk of a fatal timeout during
the credentials handshake, which may be an issue if the \s-1PMDA\s0 has
considerable work to do, e.g. determining which metrics and
instance domains are available, before calling \fIrun\fR.
.ie n .IP "$pmda\->add_indom(indom, insts, help, longhelp)" 4
.el .IP "\f(CW$pmda\fR\->add_indom(indom, insts, help, longhelp)" 4
.IX Item "$pmda->add_indom(indom, insts, help, longhelp)"
Define a new instance domain.  The instance domain identifier is
\&\fIindom\fR, which is an integer and unique across all instance domains
for single \s-1PMDA.\s0
.Sp
The instances of the instance domain are defined by \fIinsts\fR which
can be specified as either a list or a hash.
.Sp
In list form, the contents of the list must provide consecutive pairs
of identifier (a integer, unique across all instances in the instance
domain) and external instance name (a string, must by unique up to the
first space, if any, across all instances in the instance domain).
For example:
.Sp
.Vb 1
\& @colours = [0 => \*(Aqred\*(Aq, 1 => \*(Aqgreen\*(Aq, 2 => \*(Aqblue\*(Aq];
.Ve
.Sp
In hash form, the external instance identifier (string) is used as the
hash key.  An arbitrary value can be stored along with the key (this
value is often used as a convenient place to hold the latest value for
each metric instance, for example).
.Sp
.Vb 1
\& %timeslices = (\*(Aqsec\*(Aq => 42, \*(Aqmin\*(Aq => \e&min_func, \*(Aqhour\*(Aq => \*(Aq0\*(Aq);
.Ve
.Sp
The \fIhelp\fR and \fIlonghelp\fR strings are interpreted as the one-line and
expanded help text to be used for this instance domain as further
described in \fBpmLookupInDomText\fR(3).
.Sp
Refer also to the \fBreplace_indom\fR() discussion below for further details
about manipulating instance domains.
.ie n .IP "$pmda\->add_metric(pmid, type, indom, sem, units, name, help, longhelp)" 4
.el .IP "\f(CW$pmda\fR\->add_metric(pmid, type, indom, sem, units, name, help, longhelp)" 4
.IX Item "$pmda->add_metric(pmid, type, indom, sem, units, name, help, longhelp)"
Define a new metric identified by the \s-1PMID\s0 \fIpmid\fR and the full
metric name \fIname\fR.
.Sp
The metric's metadata is defined by \fItype\fR, \fIindom\fR, \fIsem\fR and
\&\fIunits\fR and these parameters are used to set up the \fIpmDesc\fR
structure as described in \fBpmLookupDesc\fR(3).
.Sp
The \fIhelp\fR and \fIlonghelp\fR strings are interpreted as the one-line
and expanded help text to be used for the metric as further described
in \fBpmLookupText\fR(3).
.ie n .IP "$pmda\->replace_indom(index, insts)" 4
.el .IP "\f(CW$pmda\fR\->replace_indom(index, insts)" 4
.IX Item "$pmda->replace_indom(index, insts)"
Whenever an instance domain identified by \fIindex\fR,
previously registered using \fBadd_indom\fR(),
changes in any way, this change must be reflected by replacing the
existing mapping with a new one (\fIinsts\fR).
.Sp
The replacement mapping must be a hash if the instance domain 
was registered initially with \fBadd_indom\fR() as a hash, otherwise it must be
a list.
.Sp
Refer to the earlier \fBadd_indom\fR() discussion concerning these two
different types of instance domains definitions.
.ie n .IP "$pmda\->load_indom(index)" 4
.el .IP "\f(CW$pmda\fR\->load_indom(index)" 4
.IX Item "$pmda->load_indom(index)"
When hash-based instance domains are in use, changes are
automatically persisted when using \fBreplace_indom\fR() \-
this persisted indom can be restored (e.g. on startup)
using this interface.
.Sp
The instance domain to be loaded is identified by \fIindex\fR,
previously registered using \fBadd_indom\fR().
.Sp
Refer to the earlier \fBadd_indom\fR() discussion concerning the
two different types of instance domains definitions \- only
hash-based instance domains are persisted.
.ie n .IP "$pmda\->add_pipe(command, callback, data)" 4
.el .IP "\f(CW$pmda\fR\->add_pipe(command, callback, data)" 4
.IX Item "$pmda->add_pipe(command, callback, data)"
Allow data to be injected into the \s-1PMDA\s0 using a \fBpipe\fR(2).
.Sp
The given \fIcommand\fR is run early in the life of the \s-1PMDA,\s0 and a pipe
is formed between the \s-1PMDA\s0 and the \fIcommand\fR.  Line-oriented output
is assumed (else truncation will occur), and on receipt of each line
of text on the pipe, the \fIcallback\fR function will be called.
.Sp
The optional \fIdata\fR parameter can be used to specify extra data to
pass into the \fIcallback\fR routine.
.ie n .IP "$pmda\->add_sock(hostname, port, callback, data)" 4
.el .IP "\f(CW$pmda\fR\->add_sock(hostname, port, callback, data)" 4
.IX Item "$pmda->add_sock(hostname, port, callback, data)"
Create a \fBsocket\fR(2) connection to the \fIhostname\fR, \fIport\fR pair.
Whenever data arrives (as above, a line-oriented protocol is best)
the \fIcallback\fR function will be called.
.Sp
The optional \fIdata\fR parameter can be used to specify extra data to
pass into the \fIcallback\fR routine.
.Sp
An opaque integer-sized identifier for the socket will be returned,
which can later be used in calls to \fBput_sock\fR() as discussed below.
.ie n .IP "$pmda\->put_sock(id, output)" 4
.el .IP "\f(CW$pmda\fR\->put_sock(id, output)" 4
.IX Item "$pmda->put_sock(id, output)"
Write an \fIoutput\fR string to the socket identified by \fIid\fR, which
must refer to a socket previously registered using \fBadd_sock\fR().
.ie n .IP "$pmda\->add_tail(filename, callback, data)" 4
.el .IP "\f(CW$pmda\fR\->add_tail(filename, callback, data)" 4
.IX Item "$pmda->add_tail(filename, callback, data)"
Monitor the given \fIfilename\fR for the arrival of newly appended
information.  Line-oriented input is assumed (else truncation
will occur), and on receipt of each line of text on the pipe,
the \fIcallback\fR function will be called.
.Sp
The optional \fIdata\fR parameter can be used to specify extra data to
pass into the \fIcallback\fR routine.
.Sp
This interface deals with the issue of the file being renamed (such
as on daily log file rotation), and will attempt to automatically
re-route information from the new log file if this occurs.
.ie n .IP "$pmda\->add_timer(timeout, callback, data)" 4
.el .IP "\f(CW$pmda\fR\->add_timer(timeout, callback, data)" 4
.IX Item "$pmda->add_timer(timeout, callback, data)"
Registers a timer with the \s-1PMDA,\s0 such that on expiry of a \fItimeout\fR
a \fIcallback\fR routine will be called.  This is a repeating timer.
.Sp
The optional \fIdata\fR parameter can be used to specify extra data to
pass into the \fIcallback\fR routine.
.ie n .IP "$pmda\->err(message)" 4
.el .IP "\f(CW$pmda\fR\->err(message)" 4
.IX Item "$pmda->err(message)"
Report a timestamped error message into the \s-1PMDA\s0 log file.
.ie n .IP "$pmda\->error(message)" 4
.el .IP "\f(CW$pmda\fR\->error(message)" 4
.IX Item "$pmda->error(message)"
Report a timestamped error message into the \s-1PMDA\s0 log file.
.ie n .IP "$pmda\->log(message)" 4
.el .IP "\f(CW$pmda\fR\->log(message)" 4
.IX Item "$pmda->log(message)"
Report a timestamped informational message into the \s-1PMDA\s0 log file.
.ie n .IP "$pmda\->set_fetch_callback(cb_function)" 4
.el .IP "\f(CW$pmda\fR\->set_fetch_callback(cb_function)" 4
.IX Item "$pmda->set_fetch_callback(cb_function)"
Register a callback function akin to \fBpmdaSetFetchCallBack\fR(3).
.ie n .IP "$pmda\->set_fetch(function)" 4
.el .IP "\f(CW$pmda\fR\->set_fetch(function)" 4
.IX Item "$pmda->set_fetch(function)"
Register a fetch function, as used by \fBpmdaInit\fR(3).
.ie n .IP "$pmda\->set_instance(function)" 4
.el .IP "\f(CW$pmda\fR\->set_instance(function)" 4
.IX Item "$pmda->set_instance(function)"
Register an instance function, as used by \fBpmdaInit\fR(3).
.ie n .IP "$pmda\->set_refresh(function)" 4
.el .IP "\f(CW$pmda\fR\->set_refresh(function)" 4
.IX Item "$pmda->set_refresh(function)"
Register a refresh function, which will be called once per metric
cluster, during the fetch operation.  Only clusters being requested
during this fetch will be refreshed, allowing selective metric value
updates within the \s-1PMDA.\s0
.ie n .IP "$pmda\->set_store_callback(cb_function)" 4
.el .IP "\f(CW$pmda\fR\->set_store_callback(cb_function)" 4
.IX Item "$pmda->set_store_callback(cb_function)"
Register an store function, used indirectly by \fBpmdaInit\fR(3).
The \fIcb_function\fR is called once for each metric/instance pair
into which a \fBpmStore\fR(3) is performed.
.ie n .IP "$pmda\->set_inet_socket(port)" 4
.el .IP "\f(CW$pmda\fR\->set_inet_socket(port)" 4
.IX Item "$pmda->set_inet_socket(port)"
Specify the IPv4 socket \fIport\fR to be used to communicate with \fBpmcd\fR(1).
.ie n .IP "$pmda\->set_ipv6_socket(port)" 4
.el .IP "\f(CW$pmda\fR\->set_ipv6_socket(port)" 4
.IX Item "$pmda->set_ipv6_socket(port)"
Specify the IPv6 socket \fIport\fR to be used to communicate with \fBpmcd\fR(1).
.ie n .IP "$pmda\->set_unix_socket(socket_name)" 4
.el .IP "\f(CW$pmda\fR\->set_unix_socket(socket_name)" 4
.IX Item "$pmda->set_unix_socket(socket_name)"
Specify the filesystem \fIsocket_name\fR path to be used for communication
with \fBpmcd\fR(1).
.ie n .IP "$pmda\->set_user(username)" 4
.el .IP "\f(CW$pmda\fR\->set_user(username)" 4
.IX Item "$pmda->set_user(username)"
Run the \s-1PMDA\s0 under the \fIusername\fR user account, instead of the
default (root) user.
.SH "HELPER METHODS"
.IX Header "HELPER METHODS"
.IP "pmda_pmid(cluster, item)" 4
.IX Item "pmda_pmid(cluster, item)"
Construct a Performance Metric Identifier (\s-1PMID\s0) from the domain
number (passed as an argument to the \fInew\fR constructor), the
\&\fIcluster\fR (an integer in the range 0 to 2^12\-1) and the
\&\fIitem\fR (an integer in the range 0 to 2^10\-1).
.Sp
Every performance metric exported from a \s-1PMDA\s0 must have a unique
\&\s-1PMID.\s0
.IP "pmda_pmid_name(cluster, item)" 4
.IX Item "pmda_pmid_name(cluster, item)"
Perform a reverse metric identifier to name lookup \- given the metric
\&\fIcluster\fR and \fIitem\fR numbers, returns the metric name string.
.IP "pmda_pmid_text(cluster, item)" 4
.IX Item "pmda_pmid_text(cluster, item)"
Returns the one-line metric help text string \- given the metric
\&\fIcluster\fR and \fIitem\fR numbers, returns the help text string.
.IP "pmda_inst_name(index, instance)" 4
.IX Item "pmda_inst_name(index, instance)"
Perform a reverse instance identifier to instance name lookup
for the instance domain identified by \fIindex\fR.
Given the
internal \fIinstance\fR identifier, returns the external instance name string.
.IP "pmda_inst_lookup(index, instance)" 4
.IX Item "pmda_inst_lookup(index, instance)"
Given an internal \fIinstance\fR identifier (key) for the
instance domain identified by \fIindex\fR with an associated indom hash,
return the value associated with that key.
The value can be any scalar value (this includes references, of course,
so complex data structures can be referenced).
.IP "pmda_units(dim_space, dim_time, dim_count, scale_space, scale_time, scale_count)" 4
.IX Item "pmda_units(dim_space, dim_time, dim_count, scale_space, scale_time, scale_count)"
Construct a \fBpmUnits\fR structure suitable for registering a metrics metadata
via \fBadd_metric\fR().
.IP "pmda_config(name)" 4
.IX Item "pmda_config(name)"
Lookup the value for configuration variable \fIname\fR from the
\&\fI/etc/pcp.conf\fR file,
using \fBpmGetConfig\fR(3).
.IP "pmda_uptime(now)" 4
.IX Item "pmda_uptime(now)"
Return a human-readable uptime string, based on \fInow\fR seconds since the epoch.
.IP "\fBpmda_long()\fR" 4
.IX Item "pmda_long()"
Return either \s-1PM_TYPE_32\s0 or \s-1PM_TYPE_64\s0 depending on the platform size for a
signed long integer.
.IP "\fBpmda_ulong()\fR" 4
.IX Item "pmda_ulong()"
Return either \s-1PM_TYPE_U32\s0 or \s-1PM_TYPE_U64\s0 depending on the platform size for an
unsigned long integer.
.IP "\fBpmda_install()\fR" 4
.IX Item "pmda_install()"
Boolean result indicating whether \s-1PMDA\s0 installation is in progress, or if this
is an actual \s-1PMDA\s0 invocation via \fBpmcd\fR(1).
.SH "MACROS"
.IX Header "MACROS"
Most of the PM_* macros from the \s-1PCP C\s0 headers are available.
.PP
For example the \fItype\fR of a metric's value may be directly
specified as one of 
\&\fB\s-1PM_TYPE_32\s0\fR, \fB\s-1PM_TYPE_U32\s0\fR, \fB\s-1PM_TYPE_64\s0\fR, \fB\s-1PM_TYPE_U64\s0\fR,
\&\fB\s-1PM_TYPE_FLOAT\s0\fR, \fB\s-1PM_TYPE_DOUBLE\s0\fR, \fB\s-1PM_TYPE_STRING\s0\fR or
\&\fB\s-1PM_TYPE_NOSUPPORT\s0\fR.
.SH "DEBUGGING"
.IX Header "DEBUGGING"
Perl PMDAs do not follow the \fB\-D\fR convention of other \s-1PCP\s0 applications
for enabling run-time diagnostics and tracing.  Rather the environment
variable \fB\s-1PCP_PERL_DEBUG\s0\fR needs to be set to a string value matching
the syntax accepted for the option value for \fB\-D\fR elsewhere, see
\&\fBpmSetDebug\fR(3).
.PP
This requires a little trickery.  The \fBpmcd\fR(1) configuration file
(\fB\s-1PCP_PMCDCONF_PATH\s0\fR from \fI/etc/pcp.conf\fR) needs hand editing.
This is best demonstrated by example.
.PP
Replace this line
.PP
.Vb 1
\& foo  242  pipe  binary  python  /somepath/foo.py
.Ve
.PP
with
.PP
.Vb 2
\& foo  242  pipe  binary  python  \e
\&     sh \-c "PCP_PERL_DEBUG=pdu,fetch /usr/bin/python /somepath/foo.py"
.Ve
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fBperl\fR\|(1) and \fBPCPIntro\fR\|(1).
.PP
The \s-1PCP\s0 mailing list pcp@groups.io can be used for questions about
this module.
.PP
Further details can be found at https://pcp.io
.SH "AUTHOR"
.IX Header "AUTHOR"
The Performance Co-Pilot development team.
.PP
Copyright (C) 2014 Red Hat.
Copyright (C) 2008\-2010 Aconex.
Copyright (C) 2004 Silicon Graphics, Inc.
.PP
This library is free software; you can redistribute it and/or modify
it under the terms of the \s-1GNU\s0 General Public License, version 2 (see
the \*(L"\s-1COPYING\*(R"\s0 file in the \s-1PCP\s0 source tree for further details).