diff --git a/src/include/pmapi.h b/src/include/pmapi.h index 91139e2..0e6a285 100644 --- a/src/include/pmapi.h +++ b/src/include/pmapi.h @@ -693,12 +693,18 @@ typedef struct { typedef struct { __pmTimeval er_timestamp; /* must be 2 x 32-bit format */ - int er_flags; /* type of event record */ + int er_flags; /* event record characteristics */ int er_nparams; /* number of er_param[] entries */ pmEventParameter er_param[1]; } pmEventRecord; -#define PM_EVENT_FLAG_MISSED 0x80000000 +/* potential flags bits set in er_flags (above) */ +#define PM_EVENT_FLAG_POINT (0) /* an observation, default type */ +#define PM_EVENT_FLAG_START (1<<0) /* marking start of a new event */ +#define PM_EVENT_FLAG_END (1<<1) /* completion of a traced event */ +#define PM_EVENT_FLAG_ID (1<<2) /* 1st parameter is a trace ID */ +#define PM_EVENT_FLAG_PARENT (1<<3) /* 2nd parameter is parents ID */ +#define PM_EVENT_FLAG_MISSED (1<<31) /* nparams shows #missed events */ typedef struct { /* align initial declarations with start of pmValueBlock */ diff --git a/src/pmdas/sample/src/events.c b/src/pmdas/sample/src/events.c index 9f5f3cc..c8d9e42 100644 --- a/src/pmdas/sample/src/events.c +++ b/src/pmdas/sample/src/events.c @@ -1,7 +1,6 @@ /* - * The "event" records here are all fake. But the logic does show - * how a real PMDA could deliver values for metrics of type - * PM_TYPE_EVENT. + * The "event" records here are all fake. But the logic does show how + * a real PMDA could deliver values for metrics of type PM_TYPE_EVENT. * * Copyright (c) 2010 Ken McDonell. All Rights Reserved. * @@ -21,13 +20,11 @@ #include "pmda.h" #include "events.h" -static int nfetch = 0; +static int nfetch; static char *ebuf; static int ebuflen; -static char *eptr = NULL; +static char *eptr; static char *ebufend; -static pmEventArray *eap; -static pmEventRecord *erp; static int check_buf(int need) @@ -45,13 +42,13 @@ check_buf(int need) } static int -add_param(pmID pmid, int type, pmAtomValue *avp) +add_param(pmEventRecord *erp, pmID pmid, int type, pmAtomValue *avp) { - int need; /* bytes in the buffer */ - int vlen; /* value only length */ int sts; - pmEventParameter *epp; + int need; /* bytes in the buffer */ + int vlen; /* value only length */ void *src; + pmEventParameter *epp; need = sizeof(pmEventParameter); switch (type) { @@ -103,18 +100,23 @@ add_param(pmID pmid, int type, pmAtomValue *avp) } static void -reset(void) +reset_array(pmEventArray **eapp) { + pmEventArray *eap; + eptr = ebuf; eap = (pmEventArray *)eptr; eap->ea_nrecords = 0; + *eapp = eap; eptr += sizeof(pmEventArray) - sizeof(pmEventRecord); } static int -add_record(struct timeval *tp, int flags) +add_record(pmEventArray *eap, struct timeval *tp, int missed, int flags, + pmEventRecord **erpp) { - int sts; + int sts; + pmEventRecord *erp; if ((sts = check_buf(sizeof(pmEventRecord) - sizeof(pmEventParameter))) < 0) return sts; @@ -122,20 +124,21 @@ add_record(struct timeval *tp, int flags) erp = (pmEventRecord *)eptr; erp->er_timestamp.tv_sec = (__int32_t)tp->tv_sec; erp->er_timestamp.tv_usec = (__int32_t)tp->tv_usec; - erp->er_nparams = 0; + erp->er_nparams = (flags & PM_EVENT_FLAG_MISSED) ? missed : 0; erp->er_flags = flags; + *erpp = erp; eptr += sizeof(pmEventRecord) - sizeof(pmEventParameter); return 0; } int -event_get_c(void) +event_get_fetch_count(void) { return nfetch % 4; } void -event_set_c(int c) +event_set_fetch_count(int c) { nfetch = c; } @@ -143,10 +146,14 @@ event_set_c(int c) int sample_fetch_events(pmEventArray **eapp) { + int c; int sts; + int flags; struct timeval stamp; - int c; pmAtomValue atom; + pmEventArray *events; + pmEventRecord *record; + static char aggr[] = { '\01', '\03', '\07', '\017', '\037', '\077', '\177', '\377' }; static pmID pmid_type = PMDA_PMID(0,127); /* event.type */ static pmID pmid_32 = PMDA_PMID(0,128); /* event.param_32 */ @@ -187,7 +194,7 @@ sample_fetch_events(pmEventArray **eapp) ((__pmID_int *)&pmid_string)->domain = mydomain; ((__pmID_int *)&pmid_aggregate)->domain = mydomain; } - reset(); + reset_array(&events); gettimeofday(&stamp, NULL); /* rebase event records 10 secs in past, add 1 sec for each new record */ stamp.tv_sec -= 10; @@ -204,7 +211,8 @@ sample_fetch_events(pmEventArray **eapp) * 2nd fetch * 1 event with NO parameters */ - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_POINT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; break; @@ -214,104 +222,110 @@ sample_fetch_events(pmEventArray **eapp) * 1 event with one U32 parameter * 1 event with 2 parameters(U32 and 64 types) */ - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_POINT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 1; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; - if ((sts = add_record(&stamp, 1)) < 0) + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 2; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; atom.ll = -3; - if ((sts = add_param(pmid_64, PM_TYPE_64, &atom)) < 0) + if ((sts = add_param(record, pmid_64, PM_TYPE_64, &atom)) < 0) return sts; break; case 3: /* * 4th fetch - * 1 event with 3 parameters (U32, U64 and STRING types) + * 1 event start with 3 parameters (U32, U64 and STRING types) * 1 event with 3 parameters (U32 and 2 DOUBLE types) - * 1 event with 6 (U32, U64, STRING, STRING, 32 and U32 types) + * 1 event end with 6 (U32, U64, STRING, STRING, 32 and U32 types) * 7 "missed" events * 1 event with 3 parameters (U32, FLOAT and AGGREGATE types) */ - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_START|PM_EVENT_FLAG_ID|PM_EVENT_FLAG_PARENT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 4; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; atom.ull = 5; - if ((sts = add_param(pmid_u64, PM_TYPE_U64, &atom)) < 0) + if ((sts = add_param(record, pmid_u64, PM_TYPE_U64, &atom)) < 0) return sts; atom.cp = "6"; - if ((sts = add_param(pmid_string, PM_TYPE_STRING, &atom)) < 0) + if ((sts = add_param(record, pmid_string, PM_TYPE_STRING, &atom)) < 0) return sts; - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_POINT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 7; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; atom.d = 8; - if ((sts = add_param(pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + if ((sts = add_param(record, pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) return sts; atom.d = -9; - if ((sts = add_param(pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) + if ((sts = add_param(record, pmid_double, PM_TYPE_DOUBLE, &atom)) < 0) return sts; - if ((sts = add_record(&stamp, 2)) < 0) + flags = PM_EVENT_FLAG_END; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 10; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; atom.ull = 11; - if ((sts = add_param(pmid_u64, PM_TYPE_U64, &atom)) < 0) + if ((sts = add_param(record, pmid_u64, PM_TYPE_U64, &atom)) < 0) return sts; atom.cp = "twelve"; - if ((sts = add_param(pmid_string, PM_TYPE_STRING, &atom)) < 0) + if ((sts = add_param(record, pmid_string, PM_TYPE_STRING, &atom)) < 0) return sts; atom.cp = "thirteen"; - if ((sts = add_param(pmid_string, PM_TYPE_STRING, &atom)) < 0) + if ((sts = add_param(record, pmid_string, PM_TYPE_STRING, &atom)) < 0) return sts; atom.l = -14; - if ((sts = add_param(pmid_32, PM_TYPE_32, &atom)) < 0) + if ((sts = add_param(record, pmid_32, PM_TYPE_32, &atom)) < 0) return sts; atom.ul = 15; - if ((sts = add_param(pmid_u32, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_u32, PM_TYPE_U32, &atom)) < 0) return sts; - /* "missed 7 records */ - if ((sts = add_record(&stamp, PM_EVENT_FLAG_MISSED)) < 0) + /* "missed" 7 records */ + flags = PM_EVENT_FLAG_MISSED; + if ((sts = add_record(events, &stamp, 7, flags, &record)) < 0) return sts; stamp.tv_sec++; - erp->er_nparams = 7; - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_POINT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = 16; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; atom.f = -17; - if ((sts = add_param(pmid_float, PM_TYPE_FLOAT, &atom)) < 0) + if ((sts = add_param(record, pmid_float, PM_TYPE_FLOAT, &atom)) < 0) return sts; atom.vp = (void *)aggr; - if ((sts = add_param(pmid_aggregate, PM_TYPE_AGGREGATE, &atom)) < 0) + if ((sts = add_param(record, pmid_aggregate, PM_TYPE_AGGREGATE, &atom)) < 0) return sts; break; case -1: /* error injection */ - if ((sts = add_record(&stamp, 0)) < 0) + flags = PM_EVENT_FLAG_POINT; + if ((sts = add_record(events, &stamp, 0, flags, &record)) < 0) return sts; stamp.tv_sec++; atom.ul = c; - if ((sts = add_param(pmid_type, PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, pmid_type, PM_TYPE_U32, &atom)) < 0) return sts; /* pmid that is not in PMNS and not known to the PMDA */ - if ((sts = add_param(PMDA_PMID(100,200), PM_TYPE_U32, &atom)) < 0) + if ((sts = add_param(record, PMDA_PMID(100,200), PM_TYPE_U32, &atom)) < 0) return sts; break; } diff --git a/src/pmdas/sample/src/events.h b/src/pmdas/sample/src/events.h index ba724b8..2829774 100644 --- a/src/pmdas/sample/src/events.h +++ b/src/pmdas/sample/src/events.h @@ -1,7 +1,6 @@ /* - * The "event" records here are all fake. But the logic does show - * how a real PMDA could deliver values for metrics of type - * PM_TYPE_EVENT. + * The "event" records here are all fake. But the logic does show how + * a real PMDA could deliver values for metrics of type PM_TYPE_EVENT. * * Copyright (c) 2010 Ken McDonell. All Rights Reserved. * @@ -22,7 +21,7 @@ extern int mydomain; extern int sample_fetch_events(pmEventArray **); -extern void event_set_c(int); -extern int event_get_c(void); +extern void event_set_fetch_count(int); +extern int event_get_fetch_count(void); #endif /* _EVENTS_H */ diff --git a/src/pmdas/sample/src/sample.c b/src/pmdas/sample/src/sample.c index d6b6df2..79da4f5 100644 --- a/src/pmdas/sample/src/sample.c +++ b/src/pmdas/sample/src/sample.c @@ -2277,7 +2277,7 @@ doit: atom.ll = scramble_ver; break; case 126: /* event.reset */ - atom.l = event_get_c(); + atom.l = event_get_fetch_count(); break; case 1000: /* secret.bar */ atom.cp = "foo"; @@ -2617,7 +2617,7 @@ sample_store(pmResult *result, pmdaExt *ep) indomtab[SCRAMBLE_INDOM].it_numinst = indomtab[BIN_INDOM].it_numinst; break; case 126: /* event.reset */ - event_set_c(av.l); + event_set_fetch_count(av.l); break; default: sts = -EACCES; diff --git a/src/pminfo/pminfo.c b/src/pminfo/pminfo.c index 2766570..e297cd8 100644 --- a/src/pminfo/pminfo.c +++ b/src/pminfo/pminfo.c @@ -46,6 +46,8 @@ static int zflag; /* for -z */ static char *tz; /* for -Z timezone */ static struct timeval start; /* start of time window */ +static void myeventdump(pmValueSet *vsp); + /* * stolen from pmprobe.c ... cache all of the most recently requested * pmInDom ... @@ -79,7 +81,7 @@ lookup(pmInDom indom, int inst) /* * we only ever have one metric */ -void +static void mydump(pmDesc *dp, pmValueSet *vsp, char *indent) { int j; @@ -120,100 +122,141 @@ mydump(pmDesc *dp, pmValueSet *vsp, char *indent) printf(" value "); pmPrintValue(stdout, vsp->valfmt, dp->type, vp, 1); putchar('\n'); - if (dp->type == PM_TYPE_EVENT && xflag) { - int r; /* event records */ - int p; /* event parameters */ - int nrecords; - int flags; - static pmID pmid_flags; - static pmID pmid_missed; - pmResult **res; - - nrecords = pmUnpackEventRecords(vsp, &res); - - if (nrecords < 0) { - fprintf(stderr, "pmUnpackEventRecords: %s\n", pmErrStr(nrecords)); - continue; - } + if (dp->type == PM_TYPE_EVENT && xflag) + myeventdump(vsp); + } +} - if (pmid_flags == 0) { - /* - * get PMID for event.flags and event.missed - * note that pmUnpackEventRecords() will have called - * __pmRegisterAnon(), so the anon metrics - * should now be in the PMNS - */ - char *name_flags = "event.flags"; - char *name_missed = "event.missed"; - int sts; - sts = pmLookupName(1, &name_flags, &pmid_flags); - if (sts < 0) { - /* should not happen! */ - fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", name_flags, pmErrStr(sts)); - /* avoid subsequent warnings ... */ - __pmid_int(&pmid_flags)->item = 1; - } - sts = pmLookupName(1, &name_missed, &pmid_missed); - if (sts < 0) { - /* should not happen! */ - fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", name_missed, pmErrStr(sts)); - /* avoid subsequent warnings ... */ - __pmid_int(&pmid_missed)->item = 1; - } - } +static char * +myeventflags(int flags) +{ + static char buffer[64]; + int started = 0; - for (r = 0; r < nrecords; r++) { - printf(" --- event record [%d] timestamp ", r); - __pmPrintStamp(stdout, &res[r]->timestamp); - if (res[r]->numpmid == 0) { - printf(" ---\n"); - printf(" No parameters\n"); - continue; - } - if (res[r]->numpmid < 0) { - printf(" ---\n"); - printf(" Error: illegal number of parameters (%d)\n", res[r]->numpmid); - continue; - } - flags = 0; - for (p = 0; p < res[r]->numpmid; p++) { - pmValueSet *xvsp = res[r]->vset[p]; - int sts; - pmDesc desc; - char *name; - if (pmNameID(xvsp->pmid, &name) >= 0) { - if (p == 0) { - if (xvsp->pmid == pmid_flags) { - flags = xvsp->vlist[0].value.lval; - printf(" flags 0x%x", flags); - printf(" ---\n"); - free(name); - continue; - } - else - printf(" ---\n"); - } - if ((flags & PM_EVENT_FLAG_MISSED) && p == 1 && xvsp->pmid == pmid_missed) { - printf(" ==> %d missed event records\n", xvsp->vlist[0].value.lval); - free(name); - continue; - } - printf(" %s (%s)\n", name, pmIDStr(xvsp->pmid)); + if (flags & PM_EVENT_FLAG_MISSED) + return strcpy(buffer, "missed"); + + buffer[0] = '\0'; + if (flags & PM_EVENT_FLAG_START) { + if (started++) strcat(buffer, ","); + strcat(buffer, "start"); + } + if (flags & PM_EVENT_FLAG_END) { + if (started++) strcat(buffer, ","); + strcat(buffer, "end"); + } + if (flags & PM_EVENT_FLAG_ID) { + if (started++) strcat(buffer, ","); + strcat(buffer, "id"); + } + if (flags & PM_EVENT_FLAG_PARENT) { + if (started++) strcat(buffer, ","); + strcat(buffer, "parent"); + } + return buffer; +} + +static void +myeventdump(pmValueSet *vsp) +{ + int r; /* event records */ + int p; /* event parameters */ + int nrecords; + int flags; + pmResult **res; + static pmID pmid_flags; + static pmID pmid_missed; + + nrecords = pmUnpackEventRecords(vsp, &res); + if (nrecords < 0) { + fprintf(stderr, "pmUnpackEventRecords: %s\n", pmErrStr(nrecords)); + return; + } + + if (pmid_flags == 0) { + /* + * get PMID for event.flags and event.missed + * note that pmUnpackEventRecords() will have called + * __pmRegisterAnon(), so the anonymous metrics + * should now be in the PMNS + */ + char *name_flags = "event.flags"; + char *name_missed = "event.missed"; + int sts; + + sts = pmLookupName(1, &name_flags, &pmid_flags); + if (sts < 0) { + /* should not happen! */ + fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", + name_flags, pmErrStr(sts)); + /* avoid subsequent warnings ... */ + __pmid_int(&pmid_flags)->item = 1; + } + sts = pmLookupName(1, &name_missed, &pmid_missed); + if (sts < 0) { + /* should not happen! */ + fprintf(stderr, "Warning: cannot get PMID for %s: %s\n", + name_missed, pmErrStr(sts)); + /* avoid subsequent warnings ... */ + __pmid_int(&pmid_missed)->item = 1; + } + } + + for (r = 0; r < nrecords; r++) { + printf(" --- event record [%d] timestamp ", r); + __pmPrintStamp(stdout, &res[r]->timestamp); + if (res[r]->numpmid == 0) { + printf(" ---\n"); + printf(" No parameters\n"); + continue; + } + if (res[r]->numpmid < 0) { + printf(" ---\n"); + printf(" Error: illegal number of parameters (%d)\n", + res[r]->numpmid); + continue; + } + flags = 0; + for (p = 0; p < res[r]->numpmid; p++) { + pmValueSet *xvsp = res[r]->vset[p]; + int sts; + pmDesc desc; + char *name; + + if (pmNameID(xvsp->pmid, &name) >= 0) { + if (p == 0) { + if (xvsp->pmid == pmid_flags) { + flags = xvsp->vlist[0].value.lval; + printf(" flags 0x%x", flags); + printf(" (%s) ---\n", myeventflags(flags)); free(name); - } - else - printf(" PMID: %s\n", pmIDStr(xvsp->pmid)); - if ((sts = pmLookupDesc(xvsp->pmid, &desc)) < 0) { - printf(" pmLookupDesc: %s\n", pmErrStr(sts)); continue; } - mydump(&desc, xvsp, " "); + else + printf(" ---\n"); + } + if ((flags & PM_EVENT_FLAG_MISSED) && + (p == 1) && + (xvsp->pmid == pmid_missed)) { + printf(" ==> %d missed event records\n", + xvsp->vlist[0].value.lval); + free(name); + continue; } + printf(" %s (%s)\n", name, pmIDStr(xvsp->pmid)); + free(name); + } + else + printf(" PMID: %s\n", pmIDStr(xvsp->pmid)); + if ((sts = pmLookupDesc(xvsp->pmid, &desc)) < 0) { + printf(" pmLookupDesc: %s\n", pmErrStr(sts)); + continue; } - if (nrecords >= 0) - pmFreeEventResult(res); + mydump(&desc, xvsp, " "); } } + if (nrecords >= 0) + pmFreeEventResult(res); } static void