sstore_data_read, sstore_data_iter_next - Read statistics and events
cc [ flag... ] file... -lsstore [ library... ] #include <libsstore.h> sstore_err_t sstore_data_read(sstore_handle_t hdl, const char **ids, uint32_t id_count, sstore_range_t range, sstore_walk_t walk, sstore_iter_t *iterp); sstore_err_t sstore_data_iter_next(sstore_handle_t hdl, sstore_iter_t iter, char **idp, uint64_t *timep, sstore_value_t *valp);
Handle to libsstore
Array of Statistics Store identifiers
Total number of Statistics Store identifiers
Time range or data range.
Passing NULL for range implies:
start-time = SS_TIME_NOW
end-time = SS_TIME_NOW
step = (None - raw data)
Format of the iteration. The following formats are supported:
Walks the data records by identifier
Walks the data records by timestamps
Address to store the starting address of the iterator returned from batch request execution
Iterator returned from the sstore_data_read() function.
Address to store the starting address of the Statistics Store identifier.
Address to store the time in microseconds since epoch.
Address to store the handle to a typed value.
The sstore_data_read() function retrieves the statistics and events associated with the given identifiers and range. The retrieved data is returned in the form of an iterator that can be used to read the data records. Once all the data records have been read from the iterator, the iterator must be freed using the sstore_iter_free(3SSTORE) function.
If the start-time or end-time in the given range is SS_TIME_NOW, indicating that the range includes current time, then the sstore_data_read() function also starts recording data for the ssids in the ids array if they are not being recorded already. The sstore_data_read() function continues to record this data for 300 seconds after the last sstore_data_read() function call for the given ssids with a range that includes current time.
Data point interpolation may be applied for non-zero values of the step parameter (gives the granularity in seconds). For more information, see the sstore_range_alloc(3SSTORE) man page.
The value of the walk parameter determines the order in which the data records are returned when you walk the iterator. The walk parameter can have the following values:
Walks the result by Statistics Store identifier. For each identifier, walks all the data records associated with that identifier.
Walks the result by the time stamp of the data records in chronological order.
The sstore_data_iter_next(3SSTORE) function retrieves the next data record of the iteration. Each data record consists of an ssid, a time stamp, and a value. The reference pointers passed to this call are populated if the call succeeds. The identifier, time stamp, and value populated on success do not need to be freed. They are freed on the next call to the sstore_data_iter_next(3SSTORE) function.
See the sstore-security(7) man page for a description of the authorizations required to read statistics.
Upon successful completion, the sstore_data_read() and sstore_data_iter_next() functions return ESSTORE_OK. Otherwise, they return an error code, which is also cached in the given libsstore handle.
The sstore_data_read() function might return ESSTORE_ARG_INVALID, ESSTORE_HANDLE_INVALID, ESSTORE_RETRY, ESSTORE_CONNECTION_FAILED, ESSTORE_UNAUTHORIZED, ESSTORE_TOO_BIG, or ESSTORE_NOMEM.
The sstore_data_iter_next() function might return ESSTORE_ARG_INVALID, ESSTORE_HANDLE_INVALID, or ESSTORE_ITER_DONE.
There is insufficient memory.
One of the following reasons:
Required arguments are missing.
The format is not valid.
The range is not valid.
The libsstore handle is invalid.
Failed to connect to the statistics store daemon.
The statistics store daemon is busy. Retry later.
The total size of all the resulting statistics records is larger than the maximum size limit set in libsstore handle.
The sstore_data_read() function might set the following:
This is syntactically or semantically invalid.
Unable to resolve the ssid.
Read CPU statistics for CPU 0 for count times and sleep for interval seconds between each read as follows:
#include <libsstore.h> #include <stdio.h> #include <unistd.h> /* List of statistical identifiers */ const char *ids[] = { "//:class.cpu//:stat.xcalls", "//:class.cpu//:stat.usage//:part.mode(idle)", "//:class.cpu//:stat.interrupt-//:s.[count,time]", }; /* Total number of statistical identifiers */ uint32_t id_count = 3; /* Number of seconds to sleep between 2 reads */ int interval = 1; /* Number of times the statistics need to be read */ int count = 3; sstore_handle_t hdl = NULL; /* * Prints the value in the value handle. */ int print_value(sstore_value_t val) { uint64_t val_u64; char *keyp; sstore_value_t valp; switch(sstore_value_type(val)) { case SSTORE_VALUE_NUMBER: if (sstore_value_number(hdl, val, &val_u64) != ESSTORE_OK) { return (sstore_err_code(hdl)); } printf("%llu\n", val_u64); break; case SSTORE_VALUE_DICTIONARY: while (sstore_value_dictionary_next(hdl, val, &keyp, &valp) == ESSTORE_OK) { (void) printf("%s ", keyp); (void) print_value(valp); } break; case SSTORE_VALUE_NODATA: printf("NO_DATA\n"); break; default: printf("Invalid value type %d\n", sstore_value_type(val)); } return (ESSTORE_OK); } /* * Reads and iterate through the statistics for the given identifiers * every second for 'count' number of times. */ void read_data() { sstore_iter_t iter = NULL; sstore_value_t val; int i = 0; char *id, *desc; uint64_t ts; printf("%-58s %-16s %s\n", "IDENTIFIER", "TIMESTAMP", "VALUE"); while (i++ < count) { /* Read the most recent value for the given identifiers */ if (sstore_data_read(hdl, ids, id_count, NULL, SSTORE_WALK_ID, &iter) != ESSTORE_OK) break; /* Check and print any warnings */ while (sstore_warning_next(hdl, &id, &desc) != SS_WARN_OK) { fprintf(stderr, "Failed to read stats for %s. Error: %s\n", id, desc); } /* Iterate and print the returned statistical records */ while (sstore_data_iter_next(hdl, iter, &id, &ts, &val) == ESSTORE_OK) { printf("%-58s %16llu ", id, ts); if (print_value(val) != ESSTORE_OK) break; } /* Free the iterator */ sstore_iter_free(iter); iter = NULL; /* Check if the iteration was successful */ if (sstore_err_code(hdl) != ESSTORE_ITER_DONE) break; sleep(interval); printf("\n"); } /* Check for errors */ if (sstore_err_code(hdl) != ESSTORE_OK && sstore_err_code(hdl) != ESSTORE_ITER_DONE) { sstore_iter_free(iter); fprintf(stderr, "%s. Error: %s.\n", sstore_err_action(hdl), sstore_err_description(hdl)); } } int main() { /* Allocate a libsstore handle */ if ((hdl = sstore_alloc()) == NULL) { printf("Failed to allocate handle\n"); return (-1); } /* Read and print the statistics */ read_data(); /* Free the libsstore handle */ sstore_free(hdl); return (0); } Output: IDENTIFIER TIMESTAMP VALUE //:class.cpu//:stat.xcalls 1424815728214187 68027 //:class.cpu//:stat.usage//:part.mode(idle) 1424815727214132 idle 3206077270089 //:class.cpu//:stat.interrupt-count 1424815728960968 total 1479974 //:class.cpu//:stat.interrupt-time 1424815728960968 total 5329198050 //:class.cpu//:stat.xcalls 1424815728214187 68027 //:class.cpu//:stat.usage//:part.mode(idle) 1424815728214187 idle 3207073755382 //:class.cpu//:stat.interrupt-count 1424815728960968 total 1479974 //:class.cpu//:stat.interrupt-time 1424815728960968 total 5329198050 //:class.cpu//:stat.xcalls 1424815729214360 68053 //:class.cpu//:stat.usage//:part.mode(idle) 1424815729214360 idle 3208069183506 //:class.cpu//:stat.interrupt-count 1424815729214363 total 1480104 //:class.cpu//:stat.interrupt-time 1424815729214363 total 5329702612Example 2 Reading Historical CPU Statistics and Walking the Result
Read historical statistics for CPU 0 and walk the result with different walk types as follows:
#include <libsstore.h> #include <stdio.h> #include <sys/time.h> #include <unistd.h> #define MICRO 1000000 /* List of statistical identifiers */ const char *ids[] = { "//:class.cpu//:stat.usage", "//:class.cpu//:stat.xcalls", }; /* Total number of statistical identifiers */ uint32_t id_count = 2; /* Interval for data capture */ int interval = 3; sstore_handle_t hdl = NULL; /* * Prints the value in the value handle. */ int print_value(sstore_value_t val) { uint64_t val_u64; double val_real; char *keyp; sstore_value_t valp; switch(sstore_value_type(val)) { case SSTORE_VALUE_NUMBER: if (sstore_value_number(hdl, val, &val_u64) != ESSTORE_OK) { return (sstore_err_code(hdl)); } printf("%llu\n", val_u64); break; case SSTORE_VALUE_REAL: if (sstore_value_real(hdl, val, &val_real) != ESSTORE_OK) { return (sstore_err_code(hdl)); } printf("%6.2f\n", val_real); break; case SSTORE_VALUE_DICTIONARY: while (sstore_value_dictionary_next(hdl, val, &keyp, &valp) == ESSTORE_OK) { (void) printf("%s ", keyp); (void) print_value(valp); } break; case SSTORE_VALUE_NODATA: printf("NO_DATA\n"); break; default: printf("Invalid value type %d\n", sstore_value_type(val)); } return (ESSTORE_OK); } /* * Reads and iterate through the statistics for the given identifiers * every second for 'count' number of times. */ void read_data(sstore_range_t range, sstore_walk_t walk, int print_data) { sstore_iter_t iter = NULL; sstore_value_t val; char *id, *desc; uint64_t ts; /* Read the statistics collected during the interval */ if (sstore_data_read(hdl, ids, id_count, range, walk, &iter) != ESSTORE_OK) goto error; /* Check if we need to print the data */ if (print_data == 0) goto cleanup; /* Iterate through data records and print */ printf("%-42s %-16s %s\n", "IDENTIFIER", "TIMESTAMP", "VALUE"); while (sstore_data_iter_next(hdl, iter, &id, &ts, &val) == ESSTORE_OK) { /* Round out the times */ ts = (ts / MICRO) * MICRO; printf("%-42s %16llu ", id, ts); if (print_value(val) != ESSTORE_OK) goto cleanup; } cleanup: /* Free the iterator */ sstore_iter_free(iter); if (sstore_err_code(hdl) == ESSTORE_OK || sstore_err_code(hdl) == ESSTORE_ITER_DONE) return; error: fprintf(stderr, "%s. Error: %s\n", sstore_err_action(hdl), sstore_err_description(hdl)); } int main() { uint64_t init_time, start_time, end_time, step; sstore_range_t range = NULL; if ((init_time = time(NULL)) == (time_t)-1) { fprintf(stderr, "Could not find time\n"); return (-1); } /* Allocate a libsstore handle */ if ((hdl = sstore_alloc()) == NULL) { fprintf(stderr, "Failed to allocate handle\n"); return (-1); } /* Allocate a range struct */ if ((range = sstore_range_alloc()) == NULL) { sstore_free(hdl); fprintf(stderr, "Failed to allocate range\n"); return (-1); } /* * Start a dynamic log job to record stats in sstored. * Wait 'interval' seconds to allow some data to be collected. * * Note: Passing NULL for 'range' implies start = SS_TIME_NOW, * end = SS_TIME_NOW and step = 1. */ printf("Capturing data for %d seconds...\n", interval); read_data(NULL, SSTORE_WALK_ID, 0); sleep(interval); /* Convert init_time into microseconds and get the time range */ start_time = init_time * MICRO; end_time = ((init_time + interval) * MICRO) - 1; step = 1; /* * Initialize the range struct * Note: The following call will not fail since we are * reusing the range struct allocated earlier. */ range = sstore_range_by_time(range, start_time, end_time, step); /* Read and print the statistics while walking by ID */ printf("\nWalking data by TS...\n"); read_data(range, SSTORE_WALK_TS, 1); /* Read and print the statistics while walking by TS */ printf("\nWalking data by ID...\n"); read_data(range, SSTORE_WALK_ID, 1); /* Free the libsstore handle */ sstore_free(hdl); /* Free the range struct */ sstore_range_free(range); return (0); } Output: Capturing data for 3 seconds... Walking data by TS... IDENTIFIER TIMESTAMP VALUE //:class.cpu//:stat.usage 1424815732000000 total 3243831735969 //:class.cpu//:stat.xcalls 1424815732000000 68122.89 //:class.cpu//:stat.usage 1424815733000000 total 3244833333130 //:class.cpu//:stat.xcalls 1424815733000000 80431.19 //:class.cpu//:stat.usage 1424815734000000 total 3244833333587 //:class.cpu//:stat.xcalls 1424815734000000 80629.86 Walking data by ID... IDENTIFIER TIMESTAMP VALUE //:class.cpu//:stat.usage 1424815732000000 total 3243831735969 //:class.cpu//:stat.usage 1424815733000000 total 3244833333130 //:class.cpu//:stat.usage 1424815734000000 total 3244833333587 //:class.cpu//:stat.xcalls 1424815732000000 68122.89 //:class.cpu//:stat.xcalls 1424815733000000 80431.19 //:class.cpu//:stat.xcalls 1424815734000000 80629.86
See the attributes(7) man page for descriptions of the following attributes:
|
libnvpair(3LIB), libsstore(3LIB), sstore_alloc(3SSTORE), sstore_data_attach(3SSTORE), sstore_err_action(3SSTORE), sstore_range_alloc(3SSTORE), attributes(7), privileges(7), sstore(7), sstore-security(7)