diff options
Diffstat (limited to 'src/collectors/windows.plugin/perflib-rrd.c')
-rw-r--r-- | src/collectors/windows.plugin/perflib-rrd.c | 822 |
1 files changed, 411 insertions, 411 deletions
diff --git a/src/collectors/windows.plugin/perflib-rrd.c b/src/collectors/windows.plugin/perflib-rrd.c index d425307ee..5af36ae35 100644 --- a/src/collectors/windows.plugin/perflib-rrd.c +++ b/src/collectors/windows.plugin/perflib-rrd.c @@ -1,411 +1,411 @@ -// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "perflib-rrd.h"
-
-#define COLLECTED_NUMBER_PRECISION 10000
-
-RRDDIM *perflib_rrddim_add(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divider, COUNTER_DATA *cd) {
- RRD_ALGORITHM algorithm = RRD_ALGORITHM_ABSOLUTE;
-
- switch (cd->current.CounterType) {
- case PERF_COUNTER_COUNTER:
- case PERF_SAMPLE_COUNTER:
- case PERF_COUNTER_BULK_COUNT:
- // (N1 - N0) / ((D1 - D0) / F)
- // multiplier *= cd->current.Frequency / 10000000;
- // tested, the frequency is not that useful for netdata
- // we get right results without it.
- algorithm = RRD_ALGORITHM_INCREMENTAL;
- break;
-
- case PERF_COUNTER_QUEUELEN_TYPE:
- case PERF_COUNTER_100NS_QUEUELEN_TYPE:
- case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
- case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
- case PERF_AVERAGE_BULK: // normally not displayed
- // (N1 - N0) / (D1 - D0)
- algorithm = RRD_ALGORITHM_INCREMENTAL;
- break;
-
- case PERF_OBJ_TIME_TIMER:
- case PERF_COUNTER_TIMER:
- case PERF_100NSEC_TIMER:
- case PERF_PRECISION_SYSTEM_TIMER:
- case PERF_PRECISION_100NS_TIMER:
- case PERF_PRECISION_OBJECT_TIMER:
- case PERF_SAMPLE_FRACTION:
- // 100 * (N1 - N0) / (D1 - D0)
- multiplier *= 100;
- algorithm = RRD_ALGORITHM_INCREMENTAL;
- break;
-
- case PERF_COUNTER_TIMER_INV:
- case PERF_100NSEC_TIMER_INV:
- // 100 * (1 - ((N1 - N0) / (D1 - D0)))
- divider *= COLLECTED_NUMBER_PRECISION;
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_MULTI_TIMER:
- // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1
- divider *= COLLECTED_NUMBER_PRECISION;
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_100NSEC_MULTI_TIMER:
- // 100 * ((N1 - N0) / (D1 - D0)) / B1
- divider *= COLLECTED_NUMBER_PRECISION;
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_MULTI_TIMER_INV:
- case PERF_100NSEC_MULTI_TIMER_INV:
- // 100 * (B1 - ((N1 - N0) / (D1 - D0)))
- divider *= COLLECTED_NUMBER_PRECISION;
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_RAWCOUNT:
- case PERF_COUNTER_LARGE_RAWCOUNT:
- // N as decimal
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_RAWCOUNT_HEX:
- case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
- // N as hexadecimal
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_DELTA:
- case PERF_COUNTER_LARGE_DELTA:
- // N1 - N0
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_RAW_FRACTION:
- case PERF_LARGE_RAW_FRACTION:
- // 100 * N / B
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- divider *= COLLECTED_NUMBER_PRECISION;
- break;
-
- case PERF_AVERAGE_TIMER:
- // ((N1 - N0) / TB) / (B1 - B0)
- // divider *= cd->current.Frequency / 10000000;
- algorithm = RRD_ALGORITHM_INCREMENTAL;
- break;
-
- case PERF_ELAPSED_TIME:
- // (D0 - N0) / F
- algorithm = RRD_ALGORITHM_ABSOLUTE;
- break;
-
- case PERF_COUNTER_TEXT:
- case PERF_SAMPLE_BASE:
- case PERF_AVERAGE_BASE:
- case PERF_COUNTER_MULTI_BASE:
- case PERF_RAW_BASE:
- case PERF_COUNTER_NODATA:
- case PERF_PRECISION_TIMESTAMP:
- default:
- break;
- }
-
- return rrddim_add(st, id, name, multiplier, divider, algorithm);
-}
-
-#define VALID_DELTA(cd) \
- ((cd)->previous.Time > 0 && (cd)->current.Data >= (cd)->previous.Data && (cd)->current.Time > (cd)->previous.Time)
-
-collected_number perflib_rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, COUNTER_DATA *cd) {
- ULONGLONG numerator = 0;
- LONGLONG denominator = 0;
- double doubleValue = 0.0;
- collected_number value;
-
- switch(cd->current.CounterType) {
- case PERF_COUNTER_COUNTER:
- case PERF_SAMPLE_COUNTER:
- case PERF_COUNTER_BULK_COUNT:
- // (N1 - N0) / ((D1 - D0) / F)
- value = (collected_number)cd->current.Data;
- break;
-
- case PERF_COUNTER_QUEUELEN_TYPE:
- case PERF_COUNTER_100NS_QUEUELEN_TYPE:
- case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
- case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
- case PERF_AVERAGE_BULK: // normally not displayed
- // (N1 - N0) / (D1 - D0)
- value = (collected_number)cd->current.Data;
- break;
-
- case PERF_OBJ_TIME_TIMER:
- case PERF_COUNTER_TIMER:
- case PERF_100NSEC_TIMER:
- case PERF_PRECISION_SYSTEM_TIMER:
- case PERF_PRECISION_100NS_TIMER:
- case PERF_PRECISION_OBJECT_TIMER:
- case PERF_SAMPLE_FRACTION:
- // 100 * (N1 - N0) / (D1 - D0)
- value = (collected_number)cd->current.Data;
- break;
-
- case PERF_COUNTER_TIMER_INV:
- case PERF_100NSEC_TIMER_INV:
- // 100 * (1 - ((N1 - N0) / (D1 - D0)))
- if(!VALID_DELTA(cd)) return 0;
- numerator = cd->current.Data - cd->previous.Data;
- denominator = cd->current.Time - cd->previous.Time;
- doubleValue = 100.0 * (1.0 - ((double)numerator / (double)denominator));
- // printf("Display value is (timer-inv): %f%%\n", doubleValue);
- value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION);
- break;
-
- case PERF_COUNTER_MULTI_TIMER:
- // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1
- if(!VALID_DELTA(cd)) return 0;
- numerator = cd->current.Data - cd->previous.Data;
- denominator = cd->current.Time - cd->previous.Time;
- denominator /= cd->current.Frequency;
- doubleValue = 100.0 * ((double)numerator / (double)denominator) / cd->current.MultiCounterData;
- // printf("Display value is (multi-timer): %f%%\n", doubleValue);
- value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION);
- break;
-
- case PERF_100NSEC_MULTI_TIMER:
- // 100 * ((N1 - N0) / (D1 - D0)) / B1
- if(!VALID_DELTA(cd)) return 0;
- numerator = cd->current.Data - cd->previous.Data;
- denominator = cd->current.Time - cd->previous.Time;
- doubleValue = 100.0 * ((double)numerator / (double)denominator) / (double)cd->current.MultiCounterData;
- // printf("Display value is (100ns multi-timer): %f%%\n", doubleValue);
- value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION);
- break;
-
- case PERF_COUNTER_MULTI_TIMER_INV:
- case PERF_100NSEC_MULTI_TIMER_INV:
- // 100 * (B1 - ((N1 - N0) / (D1 - D0)))
- if(!VALID_DELTA(cd)) return 0;
- numerator = cd->current.Data - cd->previous.Data;
- denominator = cd->current.Time - cd->previous.Time;
- doubleValue = 100.0 * ((double)cd->current.MultiCounterData - ((double)numerator / (double)denominator));
- // printf("Display value is (multi-timer-inv): %f%%\n", doubleValue);
- value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION);
- break;
-
- case PERF_COUNTER_RAWCOUNT:
- case PERF_COUNTER_LARGE_RAWCOUNT:
- // N as decimal
- value = (collected_number)cd->current.Data;
- break;
-
- case PERF_COUNTER_RAWCOUNT_HEX:
- case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
- // N as hexadecimal
- value = (collected_number)cd->current.Data;
- break;
-
- case PERF_COUNTER_DELTA:
- case PERF_COUNTER_LARGE_DELTA:
- if(!VALID_DELTA(cd)) return 0;
- value = (collected_number)(cd->current.Data - cd->previous.Data);
- break;
-
- case PERF_RAW_FRACTION:
- case PERF_LARGE_RAW_FRACTION:
- // 100 * N / B
- if(!cd->current.Time) return 0;
- doubleValue = 100.0 * (double)cd->current.Data / (double)cd->current.Time;
- // printf("Display value is (fraction): %f%%\n", doubleValue);
- value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION);
- break;
-
- default:
- return 0;
- }
-
- return rrddim_set_by_pointer(st, rd, value);
-}
-
-/*
-double perflibCalculateValue(RAW_DATA *current, RAW_DATA *previous) {
- ULONGLONG numerator = 0;
- LONGLONG denominator = 0;
- double doubleValue = 0.0;
- DWORD dwordValue = 0;
-
- if (NULL == previous) {
- // Return error if the counter type requires two samples to calculate the value.
- switch (current->CounterType) {
- default:
- if (PERF_DELTA_COUNTER != (current->CounterType & PERF_DELTA_COUNTER))
- break;
- __fallthrough;
- // fallthrough
-
- case PERF_AVERAGE_TIMER: // Special case.
- case PERF_AVERAGE_BULK: // Special case.
- // printf(" > The counter type requires two samples but only one sample was provided.\n");
- return NAN;
- }
- }
- else {
- if (current->CounterType != previous->CounterType) {
- // printf(" > The samples have inconsistent counter types.\n");
- return NAN;
- }
-
- // Check for integer overflow or bad data from provider (the data from
- // sample 2 must be greater than the data from sample 1).
- if (current->Data < previous->Data)
- {
- // Can happen for various reasons. Commonly occurs with the Process counterset when
- // multiple processes have the same name and one of them starts or stops.
- // Normally you'll just drop the older sample and continue.
- // printf("> current (%llu) is smaller than previous (%llu).\n", current->Data, previous->Data);
- return NAN;
- }
- }
-
- switch (current->CounterType) {
- case PERF_COUNTER_COUNTER:
- case PERF_SAMPLE_COUNTER:
- case PERF_COUNTER_BULK_COUNT:
- // (N1 - N0) / ((D1 - D0) / F)
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- dwordValue = (DWORD)(numerator / ((double)denominator / current->Frequency));
- //printf("Display value is (counter): %lu%s\n", (unsigned long)dwordValue,
- // (previous->CounterType == PERF_SAMPLE_COUNTER) ? "" : "/sec");
- return (double)dwordValue;
-
- case PERF_COUNTER_QUEUELEN_TYPE:
- case PERF_COUNTER_100NS_QUEUELEN_TYPE:
- case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
- case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
- case PERF_AVERAGE_BULK: // normally not displayed
- // (N1 - N0) / (D1 - D0)
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = (double)numerator / denominator;
- if (previous->CounterType != PERF_AVERAGE_BULK) {
- // printf("Display value is (queuelen): %f\n", doubleValue);
- return doubleValue;
- }
- return NAN;
-
- case PERF_OBJ_TIME_TIMER:
- case PERF_COUNTER_TIMER:
- case PERF_100NSEC_TIMER:
- case PERF_PRECISION_SYSTEM_TIMER:
- case PERF_PRECISION_100NS_TIMER:
- case PERF_PRECISION_OBJECT_TIMER:
- case PERF_SAMPLE_FRACTION:
- // 100 * (N1 - N0) / (D1 - D0)
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = (double)(100 * numerator) / denominator;
- // printf("Display value is (timer): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_COUNTER_TIMER_INV:
- // 100 * (1 - ((N1 - N0) / (D1 - D0)))
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = 100 * (1 - ((double)numerator / denominator));
- // printf("Display value is (timer-inv): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_100NSEC_TIMER_INV:
- // 100 * (1- (N1 - N0) / (D1 - D0))
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = 100 * (1 - (double)numerator / denominator);
- // printf("Display value is (100ns-timer-inv): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_COUNTER_MULTI_TIMER:
- // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- denominator /= current->Frequency;
- doubleValue = 100 * ((double)numerator / denominator) / current->MultiCounterData;
- // printf("Display value is (multi-timer): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_100NSEC_MULTI_TIMER:
- // 100 * ((N1 - N0) / (D1 - D0)) / B1
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = 100 * ((double)numerator / (double)denominator) / (double)current->MultiCounterData;
- // printf("Display value is (100ns multi-timer): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_COUNTER_MULTI_TIMER_INV:
- case PERF_100NSEC_MULTI_TIMER_INV:
- // 100 * (B1 - ((N1 - N0) / (D1 - D0)))
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = 100.0 * ((double)current->MultiCounterData - ((double)numerator / (double)denominator));
- // printf("Display value is (multi-timer-inv): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_COUNTER_RAWCOUNT:
- case PERF_COUNTER_LARGE_RAWCOUNT:
- // N as decimal
- // printf("Display value is (rawcount): %llu\n", current->Data);
- return (double)current->Data;
-
- case PERF_COUNTER_RAWCOUNT_HEX:
- case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
- // N as hexadecimal
- // printf("Display value is (hex): 0x%llx\n", current->Data);
- return (double)current->Data;
-
- case PERF_COUNTER_DELTA:
- case PERF_COUNTER_LARGE_DELTA:
- // N1 - N0
- // printf("Display value is (delta): %llu\n", current->Data - previous->Data);
- return (double)(current->Data - previous->Data);
-
- case PERF_RAW_FRACTION:
- case PERF_LARGE_RAW_FRACTION:
- // 100 * N / B
- doubleValue = 100.0 * (double)current->Data / (double)current->Time;
- // printf("Display value is (fraction): %f%%\n", doubleValue);
- return doubleValue;
-
- case PERF_AVERAGE_TIMER:
- // ((N1 - N0) / TB) / (B1 - B0)
- numerator = current->Data - previous->Data;
- denominator = current->Time - previous->Time;
- doubleValue = (double)numerator / (double)current->Frequency / (double)denominator;
- // printf("Display value is (average timer): %f seconds\n", doubleValue);
- return doubleValue;
-
- case PERF_ELAPSED_TIME:
- // (D0 - N0) / F
- doubleValue = (double)(current->Time - current->Data) / (double)current->Frequency;
- // printf("Display value is (elapsed time): %f seconds\n", doubleValue);
- return doubleValue;
-
- case PERF_COUNTER_TEXT:
- case PERF_SAMPLE_BASE:
- case PERF_AVERAGE_BASE:
- case PERF_COUNTER_MULTI_BASE:
- case PERF_RAW_BASE:
- case PERF_COUNTER_NODATA:
- case PERF_PRECISION_TIMESTAMP:
- // printf(" > Non-printing counter type: 0x%08x\n", current->CounterType);
- return NAN;
- break;
-
- default:
- // printf(" > Unrecognized counter type: 0x%08x\n", current->CounterType);
- return NAN;
- break;
- }
-}
-*/
+// SPDX-License-Identifier: GPL-3.0-or-later + +#include "perflib-rrd.h" + +#define COLLECTED_NUMBER_PRECISION 10000 + +RRDDIM *perflib_rrddim_add(RRDSET *st, const char *id, const char *name, collected_number multiplier, collected_number divider, COUNTER_DATA *cd) { + RRD_ALGORITHM algorithm = RRD_ALGORITHM_ABSOLUTE; + + switch (cd->current.CounterType) { + case PERF_COUNTER_COUNTER: + case PERF_SAMPLE_COUNTER: + case PERF_COUNTER_BULK_COUNT: + // (N1 - N0) / ((D1 - D0) / F) + // multiplier *= cd->current.Frequency / 10000000; + // tested, the frequency is not that useful for netdata + // we get right results without it. + algorithm = RRD_ALGORITHM_INCREMENTAL; + break; + + case PERF_COUNTER_QUEUELEN_TYPE: + case PERF_COUNTER_100NS_QUEUELEN_TYPE: + case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: + case PERF_COUNTER_LARGE_QUEUELEN_TYPE: + case PERF_AVERAGE_BULK: // normally not displayed + // (N1 - N0) / (D1 - D0) + algorithm = RRD_ALGORITHM_INCREMENTAL; + break; + + case PERF_OBJ_TIME_TIMER: + case PERF_COUNTER_TIMER: + case PERF_100NSEC_TIMER: + case PERF_PRECISION_SYSTEM_TIMER: + case PERF_PRECISION_100NS_TIMER: + case PERF_PRECISION_OBJECT_TIMER: + case PERF_SAMPLE_FRACTION: + // 100 * (N1 - N0) / (D1 - D0) + multiplier *= 100; + algorithm = RRD_ALGORITHM_INCREMENTAL; + break; + + case PERF_COUNTER_TIMER_INV: + case PERF_100NSEC_TIMER_INV: + // 100 * (1 - ((N1 - N0) / (D1 - D0))) + divider *= COLLECTED_NUMBER_PRECISION; + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_MULTI_TIMER: + // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1 + divider *= COLLECTED_NUMBER_PRECISION; + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_100NSEC_MULTI_TIMER: + // 100 * ((N1 - N0) / (D1 - D0)) / B1 + divider *= COLLECTED_NUMBER_PRECISION; + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_MULTI_TIMER_INV: + case PERF_100NSEC_MULTI_TIMER_INV: + // 100 * (B1 - ((N1 - N0) / (D1 - D0))) + divider *= COLLECTED_NUMBER_PRECISION; + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_RAWCOUNT: + case PERF_COUNTER_LARGE_RAWCOUNT: + // N as decimal + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_RAWCOUNT_HEX: + case PERF_COUNTER_LARGE_RAWCOUNT_HEX: + // N as hexadecimal + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_DELTA: + case PERF_COUNTER_LARGE_DELTA: + // N1 - N0 + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_RAW_FRACTION: + case PERF_LARGE_RAW_FRACTION: + // 100 * N / B + algorithm = RRD_ALGORITHM_ABSOLUTE; + divider *= COLLECTED_NUMBER_PRECISION; + break; + + case PERF_AVERAGE_TIMER: + // ((N1 - N0) / TB) / (B1 - B0) + // divider *= cd->current.Frequency / 10000000; + algorithm = RRD_ALGORITHM_INCREMENTAL; + break; + + case PERF_ELAPSED_TIME: + // (D0 - N0) / F + algorithm = RRD_ALGORITHM_ABSOLUTE; + break; + + case PERF_COUNTER_TEXT: + case PERF_SAMPLE_BASE: + case PERF_AVERAGE_BASE: + case PERF_COUNTER_MULTI_BASE: + case PERF_RAW_BASE: + case PERF_COUNTER_NODATA: + case PERF_PRECISION_TIMESTAMP: + default: + break; + } + + return rrddim_add(st, id, name, multiplier, divider, algorithm); +} + +#define VALID_DELTA(cd) \ + ((cd)->previous.Time > 0 && (cd)->current.Data >= (cd)->previous.Data && (cd)->current.Time > (cd)->previous.Time) + +collected_number perflib_rrddim_set_by_pointer(RRDSET *st, RRDDIM *rd, COUNTER_DATA *cd) { + ULONGLONG numerator = 0; + LONGLONG denominator = 0; + double doubleValue = 0.0; + collected_number value; + + switch(cd->current.CounterType) { + case PERF_COUNTER_COUNTER: + case PERF_SAMPLE_COUNTER: + case PERF_COUNTER_BULK_COUNT: + // (N1 - N0) / ((D1 - D0) / F) + value = (collected_number)cd->current.Data; + break; + + case PERF_COUNTER_QUEUELEN_TYPE: + case PERF_COUNTER_100NS_QUEUELEN_TYPE: + case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: + case PERF_COUNTER_LARGE_QUEUELEN_TYPE: + case PERF_AVERAGE_BULK: // normally not displayed + // (N1 - N0) / (D1 - D0) + value = (collected_number)cd->current.Data; + break; + + case PERF_OBJ_TIME_TIMER: + case PERF_COUNTER_TIMER: + case PERF_100NSEC_TIMER: + case PERF_PRECISION_SYSTEM_TIMER: + case PERF_PRECISION_100NS_TIMER: + case PERF_PRECISION_OBJECT_TIMER: + case PERF_SAMPLE_FRACTION: + // 100 * (N1 - N0) / (D1 - D0) + value = (collected_number)cd->current.Data; + break; + + case PERF_COUNTER_TIMER_INV: + case PERF_100NSEC_TIMER_INV: + // 100 * (1 - ((N1 - N0) / (D1 - D0))) + if(!VALID_DELTA(cd)) return 0; + numerator = cd->current.Data - cd->previous.Data; + denominator = cd->current.Time - cd->previous.Time; + doubleValue = 100.0 * (1.0 - ((double)numerator / (double)denominator)); + // printf("Display value is (timer-inv): %f%%\n", doubleValue); + value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION); + break; + + case PERF_COUNTER_MULTI_TIMER: + // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1 + if(!VALID_DELTA(cd)) return 0; + numerator = cd->current.Data - cd->previous.Data; + denominator = cd->current.Time - cd->previous.Time; + denominator /= cd->current.Frequency; + doubleValue = 100.0 * ((double)numerator / (double)denominator) / cd->current.MultiCounterData; + // printf("Display value is (multi-timer): %f%%\n", doubleValue); + value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION); + break; + + case PERF_100NSEC_MULTI_TIMER: + // 100 * ((N1 - N0) / (D1 - D0)) / B1 + if(!VALID_DELTA(cd)) return 0; + numerator = cd->current.Data - cd->previous.Data; + denominator = cd->current.Time - cd->previous.Time; + doubleValue = 100.0 * ((double)numerator / (double)denominator) / (double)cd->current.MultiCounterData; + // printf("Display value is (100ns multi-timer): %f%%\n", doubleValue); + value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION); + break; + + case PERF_COUNTER_MULTI_TIMER_INV: + case PERF_100NSEC_MULTI_TIMER_INV: + // 100 * (B1 - ((N1 - N0) / (D1 - D0))) + if(!VALID_DELTA(cd)) return 0; + numerator = cd->current.Data - cd->previous.Data; + denominator = cd->current.Time - cd->previous.Time; + doubleValue = 100.0 * ((double)cd->current.MultiCounterData - ((double)numerator / (double)denominator)); + // printf("Display value is (multi-timer-inv): %f%%\n", doubleValue); + value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION); + break; + + case PERF_COUNTER_RAWCOUNT: + case PERF_COUNTER_LARGE_RAWCOUNT: + // N as decimal + value = (collected_number)cd->current.Data; + break; + + case PERF_COUNTER_RAWCOUNT_HEX: + case PERF_COUNTER_LARGE_RAWCOUNT_HEX: + // N as hexadecimal + value = (collected_number)cd->current.Data; + break; + + case PERF_COUNTER_DELTA: + case PERF_COUNTER_LARGE_DELTA: + if(!VALID_DELTA(cd)) return 0; + value = (collected_number)(cd->current.Data - cd->previous.Data); + break; + + case PERF_RAW_FRACTION: + case PERF_LARGE_RAW_FRACTION: + // 100 * N / B + if(!cd->current.Time) return 0; + doubleValue = 100.0 * (double)cd->current.Data / (double)cd->current.Time; + // printf("Display value is (fraction): %f%%\n", doubleValue); + value = (collected_number)(doubleValue * COLLECTED_NUMBER_PRECISION); + break; + + default: + return 0; + } + + return rrddim_set_by_pointer(st, rd, value); +} + +/* +double perflibCalculateValue(RAW_DATA *current, RAW_DATA *previous) { + ULONGLONG numerator = 0; + LONGLONG denominator = 0; + double doubleValue = 0.0; + DWORD dwordValue = 0; + + if (NULL == previous) { + // Return error if the counter type requires two samples to calculate the value. + switch (current->CounterType) { + default: + if (PERF_DELTA_COUNTER != (current->CounterType & PERF_DELTA_COUNTER)) + break; + __fallthrough; + // fallthrough + + case PERF_AVERAGE_TIMER: // Special case. + case PERF_AVERAGE_BULK: // Special case. + // printf(" > The counter type requires two samples but only one sample was provided.\n"); + return NAN; + } + } + else { + if (current->CounterType != previous->CounterType) { + // printf(" > The samples have inconsistent counter types.\n"); + return NAN; + } + + // Check for integer overflow or bad data from provider (the data from + // sample 2 must be greater than the data from sample 1). + if (current->Data < previous->Data) + { + // Can happen for various reasons. Commonly occurs with the Process counterset when + // multiple processes have the same name and one of them starts or stops. + // Normally you'll just drop the older sample and continue. + // printf("> current (%llu) is smaller than previous (%llu).\n", current->Data, previous->Data); + return NAN; + } + } + + switch (current->CounterType) { + case PERF_COUNTER_COUNTER: + case PERF_SAMPLE_COUNTER: + case PERF_COUNTER_BULK_COUNT: + // (N1 - N0) / ((D1 - D0) / F) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + dwordValue = (DWORD)(numerator / ((double)denominator / current->Frequency)); + //printf("Display value is (counter): %lu%s\n", (unsigned long)dwordValue, + // (previous->CounterType == PERF_SAMPLE_COUNTER) ? "" : "/sec"); + return (double)dwordValue; + + case PERF_COUNTER_QUEUELEN_TYPE: + case PERF_COUNTER_100NS_QUEUELEN_TYPE: + case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: + case PERF_COUNTER_LARGE_QUEUELEN_TYPE: + case PERF_AVERAGE_BULK: // normally not displayed + // (N1 - N0) / (D1 - D0) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = (double)numerator / denominator; + if (previous->CounterType != PERF_AVERAGE_BULK) { + // printf("Display value is (queuelen): %f\n", doubleValue); + return doubleValue; + } + return NAN; + + case PERF_OBJ_TIME_TIMER: + case PERF_COUNTER_TIMER: + case PERF_100NSEC_TIMER: + case PERF_PRECISION_SYSTEM_TIMER: + case PERF_PRECISION_100NS_TIMER: + case PERF_PRECISION_OBJECT_TIMER: + case PERF_SAMPLE_FRACTION: + // 100 * (N1 - N0) / (D1 - D0) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = (double)(100 * numerator) / denominator; + // printf("Display value is (timer): %f%%\n", doubleValue); + return doubleValue; + + case PERF_COUNTER_TIMER_INV: + // 100 * (1 - ((N1 - N0) / (D1 - D0))) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = 100 * (1 - ((double)numerator / denominator)); + // printf("Display value is (timer-inv): %f%%\n", doubleValue); + return doubleValue; + + case PERF_100NSEC_TIMER_INV: + // 100 * (1- (N1 - N0) / (D1 - D0)) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = 100 * (1 - (double)numerator / denominator); + // printf("Display value is (100ns-timer-inv): %f%%\n", doubleValue); + return doubleValue; + + case PERF_COUNTER_MULTI_TIMER: + // 100 * ((N1 - N0) / ((D1 - D0) / TB)) / B1 + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + denominator /= current->Frequency; + doubleValue = 100 * ((double)numerator / denominator) / current->MultiCounterData; + // printf("Display value is (multi-timer): %f%%\n", doubleValue); + return doubleValue; + + case PERF_100NSEC_MULTI_TIMER: + // 100 * ((N1 - N0) / (D1 - D0)) / B1 + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = 100 * ((double)numerator / (double)denominator) / (double)current->MultiCounterData; + // printf("Display value is (100ns multi-timer): %f%%\n", doubleValue); + return doubleValue; + + case PERF_COUNTER_MULTI_TIMER_INV: + case PERF_100NSEC_MULTI_TIMER_INV: + // 100 * (B1 - ((N1 - N0) / (D1 - D0))) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = 100.0 * ((double)current->MultiCounterData - ((double)numerator / (double)denominator)); + // printf("Display value is (multi-timer-inv): %f%%\n", doubleValue); + return doubleValue; + + case PERF_COUNTER_RAWCOUNT: + case PERF_COUNTER_LARGE_RAWCOUNT: + // N as decimal + // printf("Display value is (rawcount): %llu\n", current->Data); + return (double)current->Data; + + case PERF_COUNTER_RAWCOUNT_HEX: + case PERF_COUNTER_LARGE_RAWCOUNT_HEX: + // N as hexadecimal + // printf("Display value is (hex): 0x%llx\n", current->Data); + return (double)current->Data; + + case PERF_COUNTER_DELTA: + case PERF_COUNTER_LARGE_DELTA: + // N1 - N0 + // printf("Display value is (delta): %llu\n", current->Data - previous->Data); + return (double)(current->Data - previous->Data); + + case PERF_RAW_FRACTION: + case PERF_LARGE_RAW_FRACTION: + // 100 * N / B + doubleValue = 100.0 * (double)current->Data / (double)current->Time; + // printf("Display value is (fraction): %f%%\n", doubleValue); + return doubleValue; + + case PERF_AVERAGE_TIMER: + // ((N1 - N0) / TB) / (B1 - B0) + numerator = current->Data - previous->Data; + denominator = current->Time - previous->Time; + doubleValue = (double)numerator / (double)current->Frequency / (double)denominator; + // printf("Display value is (average timer): %f seconds\n", doubleValue); + return doubleValue; + + case PERF_ELAPSED_TIME: + // (D0 - N0) / F + doubleValue = (double)(current->Time - current->Data) / (double)current->Frequency; + // printf("Display value is (elapsed time): %f seconds\n", doubleValue); + return doubleValue; + + case PERF_COUNTER_TEXT: + case PERF_SAMPLE_BASE: + case PERF_AVERAGE_BASE: + case PERF_COUNTER_MULTI_BASE: + case PERF_RAW_BASE: + case PERF_COUNTER_NODATA: + case PERF_PRECISION_TIMESTAMP: + // printf(" > Non-printing counter type: 0x%08x\n", current->CounterType); + return NAN; + break; + + default: + // printf(" > Unrecognized counter type: 0x%08x\n", current->CounterType); + return NAN; + break; + } +} +*/ |