DBPMDA(1)

πŸ’– DBPMDA πŸ’– β€” General Commands Manual, section 1

okay so bestie, welcome to dbpmda, and no cap this page is a whole journey. it's long, so buckle up β€” this is part 1, and more is coming. πŸŽ€


✨ NAME ✨

dbpmda β€” debugger for Performance Co-Pilot PMDAs. yes, that's the whole name section, she's concise. πŸ’…


🌸 SYNOPSIS 🌸

dbpmda [-D debug] [-efiv?] [-n pmnsfile] [-q timeout] [-U username]

πŸ¦‹ DESCRIPTION πŸ¦‹

so dbpmda is literally an interactive interface to the whole situationship between a Performance Metric Domain Agent (PMDA(3)) and the Performance Metric Collector Daemon (pmcd(1)). the vibe? it lets PMDAs get attached, initialized, and exercised so you can test them for correctness. it's giving quality control, it's giving "let me poke this and see what happens". πŸ”₯

dbpmda interactively prompts you for commands, and many of those commands emulate the Protocol Data Units (PDUs) that a pmcd(1) process might send. after you run dbpmda, just type the command help to get a list of everything available. the example section down below walks you through a whole session using dbpmda to test a PMDA, so if you're a visual learner, that's your moment. ✨

now, to make repetitive testing of a PMDA less of a chore, there's the file .dbpmdarc in the current working directory β€” it can hold a list of commands that dbpmda will run on startup, before you ever get prompted to type anything interactively. while .dbpmdarc is being processed, interactive mode and command echoing are both enabled, and then they get reset at the end of the file (peep the -i and -e command line options below for the deets).

the -f command line option straight up prevents that startup processing of a .dbpmdarc file (if one even exists). πŸ™ˆ

if your system supports readline(3) then that's what gets used to read commands when input is coming from a tty device, which means history and command line editing are both available. iconic behaviour, honestly.

and here's a fun one: because there are no timeout constraints on a PMDA while you're using dbpmda (unlike with pmcd(1)), you can totally use another debugger like gdb(1) on the PMDA process once it's been attached to dbpmda. team up your debuggers, they don't mind. πŸ‘‘


πŸŽ€ OPTIONS πŸŽ€

here's the full lineup of command line options, bestie:

  • -e, --echo-input β€” echoes the input to stdout. super handy when your input is being redirected from a file.
  • -f, --norc β€” do not process the .dbpmdarc file. skipping the rc, periodt.
  • -i, --interactive β€” emulates interactive behavior and prompts for new commands, even if standard input isn't a tty device.
  • -n pmnsfile, --namespace=pmnsfile β€” loads an alternative Performance Metrics Name Space (PMNS(5)) from the file pmnsfile.
  • -q timeout, --creds-timeout=timeout β€” so the pmcd-to-agent version exchange protocol (new in PCP 2.0 β€” it was introduced to provide backward compatibility) uses this timeout to specify how long dbpmda should wait before assuming that no version response is coming from an agent. if this timeout is reached, the agent is assumed to be an agent that doesn't understand the PCP 2.0 protocol. the default timeout interval is three seconds, but the -q option lets you specify an alternative timeout interval (which must be greater than zero). the unit of time is seconds.
  • -U username, --username=username β€” the user account under which to run dbpmda.
  • -v, --valgrind β€” useful when running dbpmda under the control of valgrind(1) to triage problems in a DSO PMDA. if the -v option is used then dbpmda will do not call dlclose(3) before exiting β€” and the reason is that this allows valgrind(1) to access the symbol table of the DSO PMDA when reporting, which makes debugging so much easier.
  • -?, --help β€” display usage message and exit.

🌈 EXAMPLES 🌈

okay bestie this is the good part. below is a dbpmda session using the simple PMDA. a .dbpmdarc file is used to set the debugging option, open the PMDA, and display the current status of the debugger:

$ cat .dbpmdarc
debug libpmda
open dso pmda_simple.so simple_init 253
status

when dbpmda is run, the commands in the .dbpmdarc file get executed first:

$ dbpmda
.dbpmdarc> debug libpmda
.dbpmdarc> open dso pmda_simple.so simple_init 253
[Fri Sep 19 10:19:55] dbpmda(11651) Debug: pmdaInit: PMDA simple DSO: Metric 0.0.1(1) matched to indom 253.0(0)
[Fri Sep 19 10:19:55] dbpmda(11651) Debug: pmdaInit: PMDA simple DSO: help file $PCP_PMDAS_DIR/simple/help opened
[Fri Sep 19 10:19:55] dbpmda(11651) Info: name        = simple DSO
[Fri Sep 19 10:19:55] dbpmda(11651) Info: domain      = 253
[Fri Sep 19 10:19:55] dbpmda(11651) Info: num metrics = 4
[Fri Sep 19 10:19:55] dbpmda(11651) Info: num indom   = 1
[Fri Sep 19 10:19:55] dbpmda(11651) Info: direct map  = 1
.dbpmdarc> status

Namespace:              (default)
PMDA:                   ./pmda_simple.so
Connection:             dso
DSO Interface Version:  7
PMDA PMAPI Version:     2
Debug options:          libpmda
Timer:                  off
Getdesc:                off
Getiname:               off

Dump Instance Profile state=INCLUDE, 0 profiles

.dbpmdarc>

to examine the metric and instance domain metadata, you can use the desc and instance commands. metrics may be identified either by name, or by using the numeric "dotted" notation to specify the domain, cluster and item fields of a PMID. instance domains must be identified using a numeric "dotted" notation to specify the domain and serial fields. and for most commands, the syntax will be displayed if you give the command without any arguments at all β€” she's helpful like that:

dbpmda> desc 253.0.0
PMID: 253.0.0
    Data Type: 32-bit unsigned int  InDom: PM_INDOM_NULL 0xffffffff
    Semantics: instant  Units: none
dbpmda> instance
instance indom# [ number | name | "name" ]
dbpmda> instance 253.0
pmInDom: 253.0
[  0] inst: 0 name: "red"
[  1] inst: 1 name: "green"
[  2] inst: 2 name: "blue"

to test the most important component of a PMDA β€” the fetch β€” it's often useful to figure out how long the PMDA takes to respond. the timer can be turned on before giving a fetch:

dbpmda> timer on
dbpmda> fetch simple.numfetch 253.0.1
PMID(s): 253.0.0 253.0.1
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 2
  253.0.0 (simple.numfetch): numval: 1 valfmt: 0 vlist[]:
   value 1 1.4012985e-45 0x1
  253.0.1 (simple.color): numval: 3 valfmt: 0 vlist[]:
    inst [0 or ???] value 1 1 1.4012985e-45 0x1
    inst [1 or ???] value 101 1.4153114e-43 0x65
    inst [2 or ???] value 201 2.8166099e-43 0xc9
Timer: 0.003921 seconds
dbpmda> timer off

the integer, floating point and hex translations of the values in the pmResult structure are dumped if getdesc is set to off (which is the default). setting getdesc to on also fetches the metric metadata (or pmDesc), and that would result in only integer values being dumped in the above fetch, since the metric metadata describes the metric type to be 32-bit unsigned integers. the way that detail changes the whole output… 😭

similarly, the getiname setting controls the lookup of external instance names for metrics that have an associated instance domain. when it's off (the default) the output is exactly as shown above. when it's on, the instance "names" ??? get translated into their external instance names by the PMDA, and reported like this:

dbpmda> getiname on
dbpmda> fetch simple.color
PMID(s): 253.0.1
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 1
  253.0.1 (simple.color): numval: 3 valfmt: 0 vlist[]:
    inst [0 or "red"] value 4
    inst [1 or "green"] value 104
    inst [2 or "blue"] value 204

and because the metric metadata is required to do that instance name lookup, setting getiname to on implicitly sets getdesc to on. two-for-one, slay. πŸ’…

heads up bestie: note that if either getdesc or getiname are set on, then each fetch involves additional calls on the PMDA. for a PMDA that's under development this may not be a good idea β€” which is exactly why both settings default to off.

the simple PMDA also supports the store operation, which you can test with subsequent fetch commands:

dbpmda> store simple.numfetch "42"
PMID: 253.0.0
Getting description...
Getting Result Structure...
253.0.0: 2 -> 42
dbpmda> fetch simple.numfetch
PMID(s): 253.0.0
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 1
  253.0.0 (simple.numfetch): numval: 1 valfmt: 0 vlist[]:
   value 43

the value argument in the store command must be a string, and it's enclosed in either single quotes (') or double quotes ("). don't forget the quotes, she will not forgive you. 🫢

a profile can be specified for each instance domain, and it can include all, some, or no instances:

dbpmda> help profile

profile indom# [ all | none ]
profile indom# [ add | delete ] number

For the instance domain specified, the profile may be changed to
include 'all' instances, no instances, add an instance or delete
an instance.

dbpmda> profile 253.0 none
dbpmda> getdesc on
dbpmda> fetch 253.0.1
PMID(s): 253.0.1
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 1
  253.0.1 (simple.color): No values returned!
dbpmda> profile 253.0 add 2
dbpmda> fetch 253.0.1
PMID(s): 253.0.1
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 1
  253.0.1 (simple.color): numval: 1 valfmt: 0 vlist[]:
   value 202
dbpmda> profile 253.0 add 0
dbpmda> fetch 253.0.1
PMID(s): 253.0.1
pmResult dump from 0x100078e0 timestamp: 0.000000 11:00:00.000 numpmid: 1
  253.0.1 (simple.color): numval: 2 valfmt: 0 vlist[]:
    inst [0 or ???] value 2
    inst [2 or ???] value 203
dbpmda> status

Namespace:              (default)
PMDA:                   ./pmda_simple.so
Connection:             dso
DSO Interface Version:  7
PMDA PMAPI Version:     2
Debug options:          (none)
Timer:                  off
Getdesc:                off
Getiname:               off

Dump Instance Profile state=INCLUDE, 1 profiles
        Profile [0] indom=1061158913 [253.0] state=EXCLUDE 2 instances
                Instances: [2] [0]
dbpmda> quit

the watch command (usage: watch filename ) opens an xterm window that tails the specified log file. that window must be closed by the user when it's no longer required β€” it will not close itself, so don't leave it hanging, bestie.

the wait command is equivalent to sleep(1) and takes a single integer argument (wait time in seconds).

and here's where it gets spicy: the introduction of dynamic subtrees in the PMNS and PMDA_INTERFACE_4 in libpcp_pmda has led to additional commands being supported in dbpmda to exercise the associated dynamic PMNS services. the examples below are based on the sample PMDA.


🌸 okay that's the end of part 1 β€” the dynamic PMNS examples are up next, so don't go anywhere πŸ’–

$ dbpmda
dbpmda> open pipe /var/lib/pcp/pmdas/sample/pmdasample -d 29
Start pmdasample PMDA: /var/lib/pcp/pmdas/sample/pmdasample -d 29
dbpmda> children sample.secret
Metric: sample.secret
   non-leaf foo
       leaf bar
dbpmda> traverse sample.secret.foo
Metric: sample.secret.foo
   sample.secret.foo.bar.max.redirect
   sample.secret.foo.one
   sample.secret.foo.two
   sample.secret.foo.bar.three
   sample.secret.foo.bar.four
   sample.secret.foo.bar.grunt.five
   sample.secret.foo.bar.grunt.snort.six
   sample.secret.foo.bar.grunt.snort.huff.puff.seven
dbpmda> pmid sample.secret.foo.bar.four
Metric: sample.secret.foo.bar.four
   29.0.1004
dbpmda> name 29.0.1006
PMID: 29.0.1006
   sample.secret.foo.bar.grunt.snort.six

okay so children? it hands you the next name component for every direct descendant of a node inside a dynamic subtree of the PMNS 🫢 and the glow-up sibling traverse gives you the full metric names for all the leaf nodes in the PMNS underneath that non-leaf node you named β€” again, only within a dynamic subtree of the PMNS πŸ’«

and name + pmid are the little translation girlies: they exercise turning metric names into PMIDs (and yes, the other way round too πŸ”) for metrics inside a dynamic subtree of the PMNS.

⚠️ real talk though β€” if you use children, traverse, pmid or name with a PMDA that isn't using PMDA_INTERFACE_4, or with performance metric names that aren't part of a dynamic subtree of the PMNS, then the PMDA is expected to return errors (PM_ERR_NAME or PM_ERR_PMID) β€” because that operation is genuinely in error, bestie. outside a dynamic subtree of the PMNS it's pmcd(1) and not the PMDA that's responsible for implementing these functions πŸ‘‘

🌸 the auth era

Client authentication mechanisms have been baked into the PMCS, serving up per-user (and per-connection) info that PMDAs can actually see. A PMDA using PMDA_INTERFACE_6 or later in libpcp_pmda gets to use the "attribute" method to gain visibility into these authenticated connections, with access to info like user and group identifiers, user name, and so on. And because the need to exercise + debug this interface was so real, we got a brand new dbpmda command πŸŽ€ The following example is based on the sample PMDA:

$ dbpmda
dbpmda> open pipe pmdasample -D AUTH -l logfile
Start pmdasample PMDA: pmdasample -D AUTH -l logfile
dbpmda> attr "username" "tanya"
Attribute: username=tanya
Success
dbpmda> attr 11 "0"
Attribute: userid=0
Success
dbpmda>

The attr command passes connection attributes (PCP_ATTR_XXXX keys) and their values into a PMDA pretty much exactly the way PMCD would for a client connection πŸ’… dbpmda always passes a client context identifier of zero, and while no validity checking on values is performed, only recognised attributes can be set. no cap.

In the example above the AUTH debugging option is set for the PMDA, which uses this in its attribute callback and records each attribute and value pair sent to it in its logfile πŸ“

🫢 heads up: authentication checks have already been performed by PMCD by the time a PMDA is presented with these attributes, so no further verification is necessary by the PMDA. periodt.

πŸ’€ the debug command

The debug command takes one or more debug options separated by whitespace or a comma. Use it to selectively enable debugging output from various modules of the PCP libraries that the PMDA will be linked with. If the option is prefixed by a minus -, the corresponding debugging option gets disabled. The options are the same debug names as reported by the -l option to pmdbg(1) and/or their deprecated equivalent numeric values as reported by the -ol options to pmdbg(1). The special "option" none turns all debugging off, and the special "option" all enables all the debugging options πŸ”₯


😭 CAVEATS 😭

A value cannot be stored into metrics of type PM_TYPE_AGGREGATE or PM_TYPE_EVENT. nope. not happening. πŸ™ˆ

dbpmda uses fork(2) and exec(2) to attach to daemon PMDAs. And here's the tea: dbpmda makes no attempt to detect the termination of the daemon PMDA process, so it is possible for a PMDA to exit unexpectedly without any notification 😳 however, any further communication attempts with the PMDA will result in errors which will indicate that the PMDA is no longer responding. so you'll find out. eventually. πŸ’€


πŸ“ FILES πŸ“

  • ./.dbpmdarc β€” List of commands to do on startup. cute little starter pack fr fr πŸŽ€

🌈 PCP ENVIRONMENT 🌈

Environment variables with the prefix PCP_ are used to parameterize the file and directory names used by PCP. On each installation, the file /etc/pcp.conf contains the local values for these variables. The $PCP_CONF variable may be used to specify an alternative configuration file, as described in pcp.conf(5).

For environment variables affecting PCP tools, see pmGetOptions(3) πŸ‘‘


πŸ” DEBUGGING OPTIONS πŸ”

The -D or --debug option enables the output of additional diagnostics on stderr to help triage problems, although ngl the information is sometimes cryptic and primarily intended to provide guidance for developers rather than for end-users πŸ™ˆ debug is a comma separated list of debugging options; use pmdbg(1) with the -l option to obtain a list of the available debugging options and their meaning ✨


πŸ‘€ SEE ALSO πŸ‘€

gdb(1), pmcd(1), pmdbg(1), exec(2), fork(2), PMAPI(3), PMDA(3), pcp.conf(5), pcp.env(5) and PMNS(5) β€” the whole friend group, go say hi 🫢


and that's the page, bestie πŸ’– this was Performance Co-Pilot (that's the source), PCP (that's the version), and the page itself is DBPMDA(1). slay, go debug something, you got this πŸ‘‘βœ¨

πŸ“¦ where this page comes from