Go to main content

man pages section 3: Extended Library Functions, Volume 4

Exit Print View

Updated: Thursday, June 13, 2019
 
 

sstore_histogram_quantize (3SSTORE)

Name

sstore_histogram_init, sstore_histogram_free, sstore_histogram_quantize, sstore_histogram_bucket - allocate, free, or update an sstore_histogram_t

Synopsis

cc [ flag... ] file... -lsstore [ library... ]
#include <libsstore.h>

typedef enum {
    SSTORE_HISTOGRAM_TYPE_LINEAR,
    SSTORE_HISTOGRAM_TYPE_LOG10,
    SSTORE_HISTOGRAM_TYPE_LOG2,
    SSTORE_HISTOGRAM_LOG10_LINEAR
} sstore_histogram_type_t;

typedef struct sstore_histogram *sstore_histogram_t;

sstore_err_t sstore_histogram_init(sstore_handle_t hdl,
    sstore_histogram_type_t type, uint64_t range_min,
    uint64_t range_max, uint64_t step, sstore_histogram_t *histp);

void sstore_histogram_free(sstore_histogram_t hist);

sstore_err_t sstore_histogram_quantize(sstore_handle_t hdl,
    sstore_histogram_t hist, uint64_t val);

char *sstore_histogram_bucket(sstore_histogram_type_t type,
    uint64_t range_min, uint64_t range_max, uint64_t step,
    uint64_t val)

Parameters

hdl

Handle to libsstore

type

Type of the histogram from sstore_histogram_type_t

range_min

Number representing the upper bound of the first bucket in a linear histogram. In log-linear histograms, this parameter is the lower magnitude of the logarithmic range

range_max

Number representing the lower bound of the last bucket in a linear histogram. In log-linear histograms, this parameter is the upper magnitude of the logarithmic range

step

Bucket step for linear histograms. Number of steps in each linear range in log-linear histograms. Not used for plain log histograms

histp

Address to store the sstore_histogram_t.

hist

The sstore_histogram_t to be free or updated

val

Value

Description

The sstore_histogram_t is an opaque struct that is used to maintain a local copy of a histogram and provide it to sstored(8) using sstore_data_attach_histogram(3SSTORE), sstore_data_update(3SSTORE), and sstore_data_bulk_update(3SSTORE).

The sstore_histogram_t supports four types of histograms:

SSTORE_HISTOGRAM_TYPE_LINEAR

A histogram with fixed, linear bucket ranges.

The number of buckets depend on range_min, range_max and step, and the bucket ranges will be:

[0, range_min)
[range_min, range_min + step)
[range_min + step, range_min + step + step)
...
[range_max, 2^64)
SSTORE_HISTOGRAM_TYPE_LOG2

A histogram with bucket ranges increasing in powers of 2.

The bucket ranges are:

[0, 2^0)     # Value range: 0-0
[2^0, 2^1)   # Value range: 1-1
[2^1, 2^2)   # Value range: 2-3
[2^2, 2^3)   # Value range: 4-7
...
[2^63, 2^64)
SSTORE_HISTOGRAM_TYPE_LOG10:

A histogram with bucket ranges increasing in powers of 10.

The bucket ranges are:

[0, 10^0)    # Value range: 0-0
[10^0, 10^1) # Value range: 1-9
[10^1, 10^2) # Value range: 10-99
...
[10^19, 2^64)
SSTORE_HISTOGRAM_TYPE_LOG10_LINEAR

A histogram with fixed, linear bucket ranges which increase in log10 steps.

The number of buckets depend on range_min, range_max and step. The first bucket will contain a count of values in the range:

[0, 10^range_min)

and the last bucket will contain a count of values in the range:

[10^(range_max+1), 2^64)

Between the first and last bucket, each of the following intermediate ranges will have step number of buckets of size (10^intermediate_range_max / step):

[10^range_min, 10^(range_min+1))
[10^(range_min+1), 10^(range_min+2))
...
[10^(range_max-1), 10^range_max)
[10^range_max, 10^(range_max+1))

The value of step must be atleast 10 and should be able to evenly divide 10^(range_min+1).

For example, if range_min=1, range_max=2 and step=10, the bucket ranges will be:

[0, 10)
[10, 20)
[20, 30)
...
[90, 100)
[100, 200)
[200, 300)
...
[800, 900)
[900, 1000)
[1000, 2^64)

A statistic updated with a histogram type value will be recorded as a partitioned stat with just one partition which breaks down the statistic by the histogram buckets. These buckets can represent latency, size, or other numerically distributed parameters.

The histogram-partitions property must be used to identify any partitions that represent a histogram. The sstored(8) will use this information to set the histogram property to true in the metadata of those partitions, so that a consumer such as the webui(7) can use this to show the most optimized view for a histogram-type partition.

Note that if any non-histogram partitions exist, all partition names, including the ones that are histograms, must appear in the partitions array.

The sstore_histogram_init() function allocates a histogram and initializes its buckets based on the given type, range_min, range_max and step parameters.

The sstore_histogram_free() function frees the given sstore_histogram_t and the data associated with it. If the given sstore_histogram_t is mapped to a shared-memory region using the sstore_data_attach_histogram() function, then it will unmap the shared-memory region.

The sstore_histogram_quantize() function expands the number of buckets as needed to increment the contents of the bucket which would hold the given val parameter.

The sstore_histogram_bucket() function returns a string representing start of the bucket range in a histogram with the given parameters, that the given value falls in. For any invalid inputs, "0" will be returned. The caller is responsible for releasing the memory associated with the returned string.

The string returned from sstore_histogram_bucket() function can be used as a partition key for a stat, which has histogram as one of its partitions.

For example, if type=SSTORE_HISTOGRAM_TYPE_LINEAR, range_min=100, range_max=200 and step=10:

value = 110 -> bucket = "110"
value = 112 -> bucket = "110"
value = 153 -> bucket = "150"
value = 10  -> bucket = "0"
value = 250 -> bucket = "200"

Return Values

Upon successful completion, the sstore_histogram_init() and sstore_histogram_quantize() functions return ESSTORE_OK. Otherwise, they return an error code, which is cached in the given libsstore handle.

Errors

The sstore_histogram_init() and sstore_histogram_quantize() functions will fail if:

ESSTORE_ARG_INVALID

Required arguments are missing or invalid

ESSTORE_HANDLE_INVALID

The handle is invalid

ESSTORE_NOMEM

No memory is available

Examples

Example 1 Using sstore_data_attach_histogram() Function to Update a Statistic with a Histogram Partition

The following metadata files must be installed in /usr/lib/sstore/metadata/json/solaris for this example:

  • class.example.json

  • stat.example.json

After installing the files, svc:/system/sstore:default must be restarted.

class.example.json:
{
    "$schema": "//:class",
    "description": "histogram example class",
    "id": "example/histogram",
    "stability": "stable",
    "stat-names": [
    "//:stat.one"
    ]   
}

stat.example.json
    [
        {   
            "$schema": "//:stat",
            "description": "example stat one",
            "histogram-partitions": [ "linear" ]
            "id": "//:class.example//:stat.one",
            "stability": "stable",
            "type": "counter",
            "units": "calls"
        }
    ]

/*
* Example program histogram_attach.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>

#define NUM_STATS      1
#define RANGE_MIN      100
#define RANGE_MAX      500
#define RANGE_STEP     50

const char *ssid = "//:class.example/histogram//:stat.one";

int main()
{
    sstore_handle_t hdl;
    sstore_histogram_t h;
    uint64_t i;
    int ret = -1;

    if ((hdl = sstore_alloc()) == NULL) {
        fprintf(stderr, "Failed to alloc libsstore handle\n");
        return (-1);
        }

    /* Initialize a linear histogram */
    if (sstore_histogram_init(hdl, SSTORE_HISTOGRAM_TYPE_LINEAR,
        RANGE_MIN, RANGE_MAX, RANGE_STEP, &h) != ESSTORE_OK) {
            fprintf(stderr, "Failed to initialize a linear "
            "histogram. Reason: %s\n",
            sstore_err_description(hdl));
            goto error;
        }

    /*
    * Setup a shared memory region between sstored(8) and the test program
    */
    if (sstore_data_attach_histogram(hdl, ssid, h) != ESSTORE_OK) {
        fprintf(stderr, "Failed to setup a shared memory region. "
            "Reason: %s\n", sstore_err_description(hdl));
            goto error;
        }

/* Update the histogram every second */
    i = RANGE_MIN;
    while (1) {
        if (sstore_histogram_quantize(hdl, h, i) != ESSTORE_OK) {
            fprintf(stderr, "Failed to update the histogram. "
            "Reason: %s\n", sstore_err_description(hdl));
            break;
        }

        i++;
        sleep(1);
    }

    ret = 0;
    error:
    sstore_histogram_free(h);
    sstore_free(hdl);
    return (ret);
}

Compile this program as follows:

cc -o histogram_attach -lsstore histogram_attach.c

After installing the metadata, restart sstore and run the histogram_attach() function as a user with appropriate sstore authorizations. For more information about the authorizations required to provide and update statistics, see the sstore-security(7) man page.

In another terminal, start recording the stats updated by using the histogram_attach() function as follows:

sstore capture //:class.example/histogram//:stat.one
sstore capture //:class.example/histogram//:stat.one//:part.linear
Sample output:

$ sstore capture //:class.example/histogram//:stat.one
TIME                VALUE IDENTIFIER
2016-03-31T13:36:12 6 //:class.example/histogram//:stat.one
2016-03-31T13:36:13 7 //:class.example/histogram//:stat.one
2016-03-31T13:36:14 8 //:class.example/histogram//:stat.one

$ sstore capture //:class.example/histogram//:stat.one//:part.linear
TIME                VALUE IDENTIFIER
2016-03-11T17:03:32  //:class.example/histogram//:stat.one//:part.linear
                0: 0.0
                100: 50.0
                150: 50.0
                200: 50.0
                250: 38.0
                300: 0.0
                350: 0.0
                400: 0.0
                450: 0.0
                500: 0.0
2016-03-11T17:03:33  //:class.example/histogram//:stat.one//:part.linear
                0: 0.0
                100: 50.0
                150: 50.0
                200: 50.0
                250: 39.0
                300: 0.0
                350: 0.0
                400: 0.0
                450: 0.0
                500: 0.0
Example 2 Using sstore_data_update() Function to Update a Statistic with a Histogram Partition

The following metadata files must be installed in /usr/lib/sstore/metadata/json/solaris for this example:

  • class.example.json

  • stat.example.json

After installing the files, svc:/system/sstore:default must be restarted.

class.example.json:
{
    "$schema": "//:class",
    "description": "histogram example class",
    "id": "example/histogram",
    "stability": "stable",
    "stat-names": [
        "//:stat.one"
        ]   
}

stat.example.json
[
    {   
        "$schema": "//:stat",
        "description": "example stat one",
        "histogram-partitions": [ "histogram" ]
        "id": "//:class.example//:stat.one",
        "stability": "stable",
        "type": "counter",
        "units": "calls"
    }
]

/*
* Example program histogram_update.c:
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libsstore.h>

#define NUM_STATS	1
#define RANGE_MIN	100
#define	RANGE_MAX	500
#define	RANGE_STEP	50

const char *ssids = ["//:class.example/histogram//:stat.one"];

int main()
{
    sstore_handle_t hdl;
    sstore_value_t vals[NUM_STATS];
    uint64_t i;
    int ret = -1;

    if ((hdl = sstore_alloc()) == NULL) {
        fprintf(stderr, "Failed to alloc libsstore handle\n");
            return (-1);
    }

    /* Initialize sstore_value_t */
        if ((vals[0] = sstore_value_alloc()) == NULL) {
            fprintf(stderr, "Failed to alloc an "
            "sstore_value_t.\n")
                goto error;
        }

    /* Initialize a linear histogram */
        if (sstore_histogram_init(hdl, SSTORE_HISTOGRAM_TYPE_LINEAR,
            RANGE_MIN, RANGE_MAX, RANGE_STEP,
            &vals[0]->sv_value.hist) != ESSTORE_OK) {
                fprintf(stderr, "Failed to initialize a linear "
                "histogram. Reason: %s\n",
                sstore_err_description(hdl));
                goto error;
        }

    vals[0]->sv_type = SSTORE_VALUE_HISTOGRAM;

    /* Update the value every second */
    i = RANGE_MIN;
    while (1) {
        if (sstore_histogram_quantize(hdl, vals[0]->sv_value.hist,
            i) != ESSTORE_OK) {
                fprintf(stderr, "Failed to update the histogram. "
                "Reason: %s\n", sstore_err_description(hdl));
                    break;
           }

    if (sstore_data_update(hdl, ssids, vals,
        NUM_STATS) != ESSTORE_OK) {
            fprintf(stderr, "Failed to update stats. "
            "Reason: %s\n", sstore_err_description(hdl));
                break;
        }

/* Check warnings */
    while (sstore_warning_next(hdl, &id,
    &desc) != SS_WARN_OK) {
        fprintf(stderr, "failed to update stat for %s "
        "because %s\n", id, desc);
    }

    i++;
    sleep(1);
    }

    ret = 0;
    error:
    sstore_histogram_free(vals[0]->sv_value.hist);
    sstore_value_free(vals[0]);
    free(vals);
    sstore_free(hdl);
    return (ret);
}

Compile this program as follows:

cc -o histogram_update -lsstore histogram_update.c

After installing the metadata, restart sstore and run the histogram_attach() function as a user with appropriate sstore authorizations. For more information about the authorizations required to provide and update statistics, see the sstore-security(7) man page.

In another terminal, start recording the stats updated by using the histogram_attach() function as follows:

sstore capture //:class.example/histogram//:stat.one
sstore capture //:class.example/histogram//:stat.one//:part.linear

Output will be similar to the sample output in Example 1.

Attributes

See attributes(7) for descriptions of the following attributes:

ATTRIBUTE TYPE
ATTRIBUTE VALUE
Availability
pkg:/service/system/sstore
Interface Stability
Committed
MT-Level
Safe

See Also

libsstore(3LIB), sstore_alloc(3SSTORE), sstore_data_attach(3SSTORE), sstore_err_action(3SSTORE), sstore_value_alloc(3SSTORE), sstore_resource_add(3SSTORE) ssid-metadata(7), attributes(7)