PMTRACE(3)

πŸ“¦
version 7.2.2 Β· 3 versions
, in arch rolling, centos-stream 10, fedora 43, fedora 44

πŸ’… PMTRACE(3) β€” bestie edition

okay so this is a library functions manual page, section 3, for the family of pcp_trace calls β€” and honestly? it's giving ✨*observability*✨. We're talking pmtracebegin, pmtraceend, pmtraceabort, pmtracepoint, pmtraceobs, pmtracecounter, pmtracestate, pmtraceerrstr β€” application-level performance instrumentation services. no cap, these are the girlies that tell you how long stuff took. πŸŽ€


✨ NAME ✨

pmtracebegin, pmtraceend, pmtraceabort, pmtracepoint, pmtraceobs, pmtracecounter, pmtracestate, pmtraceerrstr β€” application-level performance instrumentation services πŸ¦‹


🌸 C SYNOPSIS 🌸

#include <pcp/trace.h>

int pmtracebegin(const char *tag);
int pmtraceend(const char *tag);
int pmtraceabort(const char *tag);
int pmtracepoint(const char *tag);
int pmtraceobs(const char *tag, double value);
int pmtracecounter(const char *tag, double value);
char *pmtraceerrstr(int code);
int pmtracestate(int flags);

cc ... -lpcp_trace

πŸ’œ FORTRAN SYNOPSIS πŸ’œ

character*(*) tag
integer code
integer flags
integer state
character*(*) estr
real*8 value

code = pmtracebegin(tag)
code = pmtraceend(tag)
code = pmtraceabort(tag)
code = pmtracepoint(tag)
code = pmtraceobs(tag, value)
code = pmtracecounter(tag, value)
pmtraceerrstr(code, estr)
state = pmtracestate(flags)

f77 ... -lpcp_trace  or  f90 ... -lpcp_trace

πŸ¦‹ JAVA SYNOPSIS πŸ¦‹

import sgi.pcp.trace;

int trace.pmtracebegin(String tag);
int trace.pmtraceend(String tag);
int trace.pmtraceabort(String tag);
int trace.pmtracepoint(String tag);
int trace.pmtraceobs(String tag, double value);
int trace.pmtracecounter(String tag, double value);
String trace.pmtraceerrstr(int code);
int trace.pmtracestate(int flags);

πŸ‘‘ DESCRIPTION πŸ‘‘

So the pcp_trace library functions are literally the mechanism for marking up sections of a program as transactions or events, so the trace Performance Metrics Domain Agent can vibe with them (go peek at pmdatrace(1) and PMDA(3) if you want the other side of the story 🫢).

Monitoring transactions through the Performance Co-Pilot (PCP) infrastructure kicks off when you call pmtracebegin. Time gets recorded from the end of each pmtracebegin call to the start of the following call to pmtraceend β€” and you have to use the same tag identifier in both calls, bestie, or the whole thing is giving nothing. Because of that, no visible recording happens until at least one call to pmtraceend references a tag that was previously used in a pmtracebegin call. patience, babe πŸ’…

A transaction that's currently in progress can be cancelled by calling pmtraceabort. No transaction data gathered for that particular transaction will be exported β€” but the data from previous and subsequent successful transactions with that same tag name still gets exported, so don't panic. This is peak useful when an error condition shows up mid-transaction and the transaction doesn't run to completion. it's giving "we don't talk about that one" 😭

The tag argument to pmtracebegin, pmtraceend and pmtraceabort uniquely identifies each transaction inside the pcp_trace library, and later the trace PMDA uses it as the instance domain identifiers for the transaction performance metrics it exports. These routines are at their best around blocks of code that are likely to be executed a bunch of times over some relatively long time period (a daemon process, for example πŸ‘€).

pmtracebegin has two distinct roles β€” first as the initiator of a new transaction, and second as a mechanism for setting a new start time. Similarly, pmtraceend is used to register a new tag and its initial state with the trace PMDA, or alternatively to update the statistics the PMDA currently associates with the given tag.


A second form of program instrumentation comes from pmtracepoint ✨. It's the simpler form of monitoring β€” it exports only the number of times that a particular point in a program has been passed. That's different from the transaction monitoring you get from pmtracebegin and pmtraceend, which exports a running count of successful transaction completions plus statistics on the time interval between the start and end points of each transaction. pmtracepoint is most useful when start and end points aren't well defined β€” like when the code branches in a way that a transaction can't be clearly identified, or when processing doesn't follow a transactional model, or when the instrumentation you want is more akin to event rates rather than event service times.

pmtraceobs and pmtracecounter have similar semantics to pmtracepoint, but they also let you pass an arbitrary numeric value to the trace PMDA. The most recent value for each tag is then immediately available from the PMDA πŸ”₯. The only difference between pmtraceobs and pmtracecounter is that the value exported via pmtracecounter is assumed to be a monotonically increasing counter value (e.g. the number of bytes read from a socket), whereas the value exported via pmtraceobs can be any value at all. one goes up only, one is free-spirited 🌈

pmtracestate lets the application set state flags which are honoured by subsequent calls to the pcp_trace library routines. There are currently two types of flag β€” debugging flags and the asynchronous protocol flag. A single call may specify a number of flags together, combined using a (bitwise) logical OR operation, and it overrides the previous state setting.

The debugging flags to pmtracestate cause pcp_trace to print diagnostic messages on the standard output stream at important processing points. The default protocol used between the trace PMDA and individual pcp_trace client applications is a synchronous protocol, which allows for dropped connections to be reestablished at a later stage should this become possible. An asynchronous protocol is also available, which does not provide the reconnection capability, but which does away with much of the overhead inherent in synchronous communication. This behaviour can be toggled using the pmtracestate call β€” but it must be called before other calls to the library. That's different from the debugging state behaviour, which can be altered at any time. pmtracestate returns the previous state (the setting prior to being called).


πŸŽ€ the pmtracestate flags, laid out cute πŸŽ€

The following describes each of the pmtracestate flags β€” examples of the use of these flags in each supported language are given in the demo applications (refer to the ``FILES'' section below πŸ‘‡).

  • 0 NONE β€” Synchronous PDUs and no diagnostics (default)
  • 1 API β€” Shows processing just below the API (debug)
  • 2 COMMS β€” Shows network-related activity (debug)
  • 4 PDU β€” Shows app<->PMDA IPC traffic (debug)
  • 8 PDUBUF β€” Shows internal IPC buffer management (debug)
  • 16 NOAGENT β€” No PMDA communications at all (debug)
  • 32 ASYNC β€” Use the asynchronous PDU protocol (control)

Should any of the pcp_trace library functions return a negative value, an error has occurred 🚨. You can diagnose it further with the pmtraceerrstr routine, which takes the negative return value as its code argument. In the C-callable interface it returns a pointer to the associated error message. That pointer points into a static error table, and should therefore not be passed to free(3) β€” do not do it, babe, that's a one-way ticket to chaos πŸ’€. The Fortran-callable interface has a slightly different syntax, requiring the destination character array to be passed in as the second argument. The Java-callable interface returns a UTF-8 string, created using the JNI (Java Native Interface) routine NewStringUTF.


🧚 NOTES 🧚

The pcp_trace Java class interface has been developed and verified using version 1.1 of the Java Native Interface (JNI) specification. retro but make it fashion ⭐


πŸ™ˆ CAVEAT πŸ™ˆ

Applications that use gethostbyname(3) should exercise caution, because the static fields in struct hostent may not be preserved across some pcp_trace calls. In particular, pmtracebegin, pmtraceend, pmtracepoint, pmtracecounter, and pmtraceobs may all call gethostbyname(3) internally.

so yeah. shared state, bestie. it's giving "we share everything" and not in a cute way 😭


πŸ’€ DIAGNOSTICS πŸ’€

A negative return value from a pcp_trace function means an error has occurred β€” and if that happens, you can pass the return value to pmtraceerrstr to obtain the associated error message.

Success is indicated by a return value of zero. periodt. βœ…

pmtracestate also returns an integer representing the state flags which were set prior to the call.


πŸ“ FILES πŸ“

  • $PCP_DEMOS_DIR/trace/*.c β€” Sample C programs and source for pmtrace(1). Use make(1) to build these programs.
  • $PCP_DEMOS_DIR/trace/fapp1.f β€” Sample Fortran program. Call make fortran77 or make fortran90 to build this program.
  • $PCP_DEMOS_DIR/trace/japp1.java β€” Sample Java program. make java builds the java class file.
  • /usr/java/classes/sgi/pcp/trace.java β€” Java trace class definition.

🌈 ENVIRONMENT 🌈

The pcp_trace routines talk to the trace PMDA over a socket connection, which by default uses TCP/IP port number 4323. You can over-ride that by setting PCP_TRACE_PORT to a different port number when the application is started.

The host where the trace PMDA is running is by default the localhost, but this can be changed using PCP_TRACE_HOST.

When you're attempting to connect to a remote trace PMDA, after some specified time interval has elapsed the connection attempt will be aborted and an error status will be returned. The default timeout interval is 3 seconds, and you can modify it by setting PCP_TRACE_TIMEOUT in the environment to a real number of seconds for the timeout you want. This is most useful when the remote host is at the end of a slow network, requiring longer latencies to establish the connection correctly. give it time, she's buffering 🐌


πŸ’– 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). Values for these variables may be obtained programmatically using the pmGetConfig(3) function.


🌸 SEE ALSO 🌸

(that Provided the fragment is just here, living its life, we keep it because the rules say every reference stays ✨)

Relevant information is also available from the on-line PCP Tutorial.


and that's the whole page, bestie!! 🫢 this manual page comes to you from Performance Co-Pilot, aka PCP β€” that's the source and the version, right there β€” and the date stamp on this beauty is tied to the PMTRACE(3) page itself. go forth and instrument everything, you main character πŸ‘‘πŸ’–

πŸ“¦ where this page comes from