xref: /dpdk/doc/guides/prog_guide/metrics_lib.rst (revision 5630257fcc30397e7217139ec55da4f301f59fb7)
1*5630257fSFerruh Yigit..  SPDX-License-Identifier: BSD-3-Clause
2*5630257fSFerruh Yigit    Copyright(c) 2017 Intel Corporation.
3349950ddSRemy Horton
4349950ddSRemy Horton.. _Metrics_Library:
5349950ddSRemy Horton
6349950ddSRemy HortonMetrics Library
7349950ddSRemy Horton===============
8349950ddSRemy Horton
9349950ddSRemy HortonThe Metrics library implements a mechanism by which *producers* can
10349950ddSRemy Hortonpublish numeric information for later querying by *consumers*. In
11349950ddSRemy Hortonpractice producers will typically be other libraries or primary
12349950ddSRemy Hortonprocesses, whereas consumers will typically be applications.
13349950ddSRemy Horton
14349950ddSRemy HortonMetrics themselves are statistics that are not generated by PMDs. Metric
15349950ddSRemy Hortoninformation is populated using a push model, where producers update the
16349950ddSRemy Hortonvalues contained within the metric library by calling an update function
17349950ddSRemy Hortonon the relevant metrics. Consumers receive metric information by querying
18349950ddSRemy Hortonthe central metric data, which is held in shared memory.
19349950ddSRemy Horton
20349950ddSRemy HortonFor each metric, a separate value is maintained for each port id, and
21349950ddSRemy Hortonwhen publishing metric values the producers need to specify which port is
22349950ddSRemy Hortonbeing updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
23349950ddSRemy Hortonthat is intended for global statistics that are not associated with any
24349950ddSRemy Hortonindividual device. Since the metrics library is self-contained, the only
25349950ddSRemy Hortonrestriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
26349950ddSRemy Horton- there is no requirement for the ports to actually exist.
27349950ddSRemy Horton
28349950ddSRemy HortonInitialising the library
29349950ddSRemy Horton------------------------
30349950ddSRemy Horton
31349950ddSRemy HortonBefore the library can be used, it has to be initialized by calling
32349950ddSRemy Horton``rte_metrics_init()`` which sets up the metric store in shared memory.
33349950ddSRemy HortonThis is where producers will publish metric information to, and where
34349950ddSRemy Hortonconsumers will query it from.
35349950ddSRemy Horton
36349950ddSRemy Horton.. code-block:: c
37349950ddSRemy Horton
38349950ddSRemy Horton    rte_metrics_init(rte_socket_id());
39349950ddSRemy Horton
40349950ddSRemy HortonThis function **must** be called from a primary process, but otherwise
41349950ddSRemy Hortonproducers and consumers can be in either primary or secondary processes.
42349950ddSRemy Horton
43349950ddSRemy HortonRegistering metrics
44349950ddSRemy Horton-------------------
45349950ddSRemy Horton
46349950ddSRemy HortonMetrics must first be *registered*, which is the way producers declare
47349950ddSRemy Hortonthe names of the metrics they will be publishing. Registration can either
48349950ddSRemy Hortonbe done individually, or a set of metrics can be registered as a group.
49349950ddSRemy HortonIndividual registration is done using ``rte_metrics_reg_name()``:
50349950ddSRemy Horton
51349950ddSRemy Horton.. code-block:: c
52349950ddSRemy Horton
53349950ddSRemy Horton    id_1 = rte_metrics_reg_name("mean_bits_in");
54349950ddSRemy Horton    id_2 = rte_metrics_reg_name("mean_bits_out");
55349950ddSRemy Horton    id_3 = rte_metrics_reg_name("peak_bits_in");
56349950ddSRemy Horton    id_4 = rte_metrics_reg_name("peak_bits_out");
57349950ddSRemy Horton
58349950ddSRemy Hortonor alternatively, a set of metrics can be registered together using
59349950ddSRemy Horton``rte_metrics_reg_names()``:
60349950ddSRemy Horton
61349950ddSRemy Horton.. code-block:: c
62349950ddSRemy Horton
63349950ddSRemy Horton    const char * const names[] = {
64349950ddSRemy Horton        "mean_bits_in", "mean_bits_out",
65349950ddSRemy Horton        "peak_bits_in", "peak_bits_out",
66349950ddSRemy Horton    };
67349950ddSRemy Horton    id_set = rte_metrics_reg_names(&names[0], 4);
68349950ddSRemy Horton
69349950ddSRemy HortonIf the return value is negative, it means registration failed. Otherwise
70349950ddSRemy Hortonthe return value is the *key* for the metric, which is used when updating
71349950ddSRemy Hortonvalues. A table mapping together these key values and the metrics' names
72349950ddSRemy Hortoncan be obtained using ``rte_metrics_get_names()``.
73349950ddSRemy Horton
74349950ddSRemy HortonUpdating metric values
75349950ddSRemy Horton----------------------
76349950ddSRemy Horton
77349950ddSRemy HortonOnce registered, producers can update the metric for a given port using
78349950ddSRemy Hortonthe ``rte_metrics_update_value()`` function. This uses the metric key
79349950ddSRemy Hortonthat is returned when registering the metric, and can also be looked up
80349950ddSRemy Hortonusing ``rte_metrics_get_names()``.
81349950ddSRemy Horton
82349950ddSRemy Horton.. code-block:: c
83349950ddSRemy Horton
84349950ddSRemy Horton    rte_metrics_update_value(port_id, id_1, values[0]);
85349950ddSRemy Horton    rte_metrics_update_value(port_id, id_2, values[1]);
86349950ddSRemy Horton    rte_metrics_update_value(port_id, id_3, values[2]);
87349950ddSRemy Horton    rte_metrics_update_value(port_id, id_4, values[3]);
88349950ddSRemy Horton
89349950ddSRemy Hortonif metrics were registered as a single set, they can either be updated
90349950ddSRemy Hortonindividually using ``rte_metrics_update_value()``, or updated together
91349950ddSRemy Hortonusing the ``rte_metrics_update_values()`` function:
92349950ddSRemy Horton
93349950ddSRemy Horton.. code-block:: c
94349950ddSRemy Horton
95349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set, values[0]);
96349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 1, values[1]);
97349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 2, values[2]);
98349950ddSRemy Horton    rte_metrics_update_value(port_id, id_set + 3, values[3]);
99349950ddSRemy Horton
100349950ddSRemy Horton    rte_metrics_update_values(port_id, id_set, values, 4);
101349950ddSRemy Horton
102349950ddSRemy HortonNote that ``rte_metrics_update_values()`` cannot be used to update
103349950ddSRemy Hortonmetric values from *multiple* *sets*, as there is no guarantee two
104349950ddSRemy Hortonsets registered one after the other have contiguous id values.
105349950ddSRemy Horton
106349950ddSRemy HortonQuerying metrics
107349950ddSRemy Horton----------------
108349950ddSRemy Horton
109349950ddSRemy HortonConsumers can obtain metric values by querying the metrics library using
110349950ddSRemy Hortonthe ``rte_metrics_get_values()`` function that return an array of
111349950ddSRemy Horton``struct rte_metric_value``. Each entry within this array contains a metric
112349950ddSRemy Hortonvalue and its associated key. A key-name mapping can be obtained using the
113349950ddSRemy Horton``rte_metrics_get_names()`` function that returns an array of
114349950ddSRemy Horton``struct rte_metric_name`` that is indexed by the key. The following will
115349950ddSRemy Hortonprint out all metrics for a given port:
116349950ddSRemy Horton
117349950ddSRemy Horton.. code-block:: c
118349950ddSRemy Horton
119349950ddSRemy Horton    void print_metrics() {
120c17c27e8SYong Wang        struct rte_metric_value *metrics;
121349950ddSRemy Horton        struct rte_metric_name *names;
122349950ddSRemy Horton        int len;
123349950ddSRemy Horton
124349950ddSRemy Horton        len = rte_metrics_get_names(NULL, 0);
125349950ddSRemy Horton        if (len < 0) {
126349950ddSRemy Horton            printf("Cannot get metrics count\n");
127349950ddSRemy Horton            return;
128349950ddSRemy Horton        }
129349950ddSRemy Horton        if (len == 0) {
130349950ddSRemy Horton            printf("No metrics to display (none have been registered)\n");
131349950ddSRemy Horton            return;
132349950ddSRemy Horton        }
133349950ddSRemy Horton        metrics = malloc(sizeof(struct rte_metric_value) * len);
134349950ddSRemy Horton        names =  malloc(sizeof(struct rte_metric_name) * len);
135349950ddSRemy Horton        if (metrics == NULL || names == NULL) {
136349950ddSRemy Horton            printf("Cannot allocate memory\n");
137349950ddSRemy Horton            free(metrics);
138349950ddSRemy Horton            free(names);
139349950ddSRemy Horton            return;
140349950ddSRemy Horton        }
141349950ddSRemy Horton        ret = rte_metrics_get_values(port_id, metrics, len);
142349950ddSRemy Horton        if (ret < 0 || ret > len) {
143349950ddSRemy Horton            printf("Cannot get metrics values\n");
144349950ddSRemy Horton            free(metrics);
145349950ddSRemy Horton            free(names);
146349950ddSRemy Horton            return;
147349950ddSRemy Horton        }
148349950ddSRemy Horton        printf("Metrics for port %i:\n", port_id);
149349950ddSRemy Horton        for (i = 0; i < len; i++)
150349950ddSRemy Horton            printf("  %s: %"PRIu64"\n",
151349950ddSRemy Horton                names[metrics[i].key].name, metrics[i].value);
152349950ddSRemy Horton        free(metrics);
153349950ddSRemy Horton        free(names);
154349950ddSRemy Horton    }
1552ad7ba9aSRemy Horton
1562ad7ba9aSRemy Horton
1572ad7ba9aSRemy HortonBit-rate statistics library
1582ad7ba9aSRemy Horton---------------------------
1592ad7ba9aSRemy Horton
1602ad7ba9aSRemy HortonThe bit-rate library calculates the exponentially-weighted moving
1612ad7ba9aSRemy Hortonaverage and peak bit-rates for each active port (i.e. network device).
1622ad7ba9aSRemy HortonThese statistics are reported via the metrics library using the
1632ad7ba9aSRemy Hortonfollowing names:
1642ad7ba9aSRemy Horton
1652ad7ba9aSRemy Horton    - ``mean_bits_in``: Average inbound bit-rate
1662ad7ba9aSRemy Horton    - ``mean_bits_out``:  Average outbound bit-rate
1672ad7ba9aSRemy Horton    - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed)
1682ad7ba9aSRemy Horton    - ``ewma_bits_out``:  Average outbound bit-rate (EWMA smoothed)
1692ad7ba9aSRemy Horton    - ``peak_bits_in``:  Peak inbound bit-rate
1702ad7ba9aSRemy Horton    - ``peak_bits_out``:  Peak outbound bit-rate
1712ad7ba9aSRemy Horton
1722ad7ba9aSRemy HortonOnce initialised and clocked at the appropriate frequency, these
1732ad7ba9aSRemy Hortonstatistics can be obtained by querying the metrics library.
1742ad7ba9aSRemy Horton
1752ad7ba9aSRemy HortonInitialization
1762ad7ba9aSRemy Horton~~~~~~~~~~~~~~
1772ad7ba9aSRemy Horton
1782ad7ba9aSRemy HortonBefore the library can be used, it has to be initialised by calling
1792ad7ba9aSRemy Horton``rte_stats_bitrate_create()``, which will return a bit-rate
1802ad7ba9aSRemy Hortoncalculation object. Since the bit-rate library uses the metrics library
1812ad7ba9aSRemy Hortonto report the calculated statistics, the bit-rate library then needs to
1822ad7ba9aSRemy Hortonregister the calculated statistics with the metrics library. This is
1832ad7ba9aSRemy Hortondone using the helper function ``rte_stats_bitrate_reg()``.
1842ad7ba9aSRemy Horton
1852ad7ba9aSRemy Horton.. code-block:: c
1862ad7ba9aSRemy Horton
1872ad7ba9aSRemy Horton    struct rte_stats_bitrates *bitrate_data;
1882ad7ba9aSRemy Horton
1892ad7ba9aSRemy Horton    bitrate_data = rte_stats_bitrate_create();
1902ad7ba9aSRemy Horton    if (bitrate_data == NULL)
1912ad7ba9aSRemy Horton        rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
1922ad7ba9aSRemy Horton    rte_stats_bitrate_reg(bitrate_data);
1932ad7ba9aSRemy Horton
1942ad7ba9aSRemy HortonControlling the sampling rate
1952ad7ba9aSRemy Horton~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1962ad7ba9aSRemy Horton
1972ad7ba9aSRemy HortonSince the library works by periodic sampling but does not use an
1982ad7ba9aSRemy Hortoninternal thread, the application has to periodically call
1992ad7ba9aSRemy Horton``rte_stats_bitrate_calc()``. The frequency at which this function
2002ad7ba9aSRemy Hortonis called should be the intended sampling rate required for the
2012ad7ba9aSRemy Hortoncalculated statistics. For instance if per-second statistics are
2022ad7ba9aSRemy Hortondesired, this function should be called once a second.
2032ad7ba9aSRemy Horton
2042ad7ba9aSRemy Horton.. code-block:: c
2052ad7ba9aSRemy Horton
2062ad7ba9aSRemy Horton    tics_datum = rte_rdtsc();
2072ad7ba9aSRemy Horton    tics_per_1sec = rte_get_timer_hz();
2082ad7ba9aSRemy Horton
2092ad7ba9aSRemy Horton    while( 1 ) {
2102ad7ba9aSRemy Horton        /* ... */
2112ad7ba9aSRemy Horton        tics_current = rte_rdtsc();
2122ad7ba9aSRemy Horton	if (tics_current - tics_datum >= tics_per_1sec) {
2132ad7ba9aSRemy Horton	    /* Periodic bitrate calculation */
2142ad7ba9aSRemy Horton	    for (idx_port = 0; idx_port < cnt_ports; idx_port++)
2152ad7ba9aSRemy Horton	            rte_stats_bitrate_calc(bitrate_data, idx_port);
2162ad7ba9aSRemy Horton		tics_datum = tics_current;
2172ad7ba9aSRemy Horton	    }
2182ad7ba9aSRemy Horton        /* ... */
2192ad7ba9aSRemy Horton    }
2205cd3cac9SReshma Pattan
2215cd3cac9SReshma Pattan
2225cd3cac9SReshma PattanLatency statistics library
2235cd3cac9SReshma Pattan--------------------------
2245cd3cac9SReshma Pattan
2255cd3cac9SReshma PattanThe latency statistics library calculates the latency of packet
2265cd3cac9SReshma Pattanprocessing by a DPDK application, reporting the minimum, average,
2275cd3cac9SReshma Pattanand maximum nano-seconds that packet processing takes, as well as
2285cd3cac9SReshma Pattanthe jitter in processing delay. These statistics are then reported
2295cd3cac9SReshma Pattanvia the metrics library using the following names:
2305cd3cac9SReshma Pattan
2315cd3cac9SReshma Pattan    - ``min_latency_ns``: Minimum processing latency (nano-seconds)
2325cd3cac9SReshma Pattan    - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
2335cd3cac9SReshma Pattan    - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
2345cd3cac9SReshma Pattan    - ``jitter_ns``: Variance in processing latency (nano-seconds)
2355cd3cac9SReshma Pattan
2365cd3cac9SReshma PattanOnce initialised and clocked at the appropriate frequency, these
2375cd3cac9SReshma Pattanstatistics can be obtained by querying the metrics library.
2385cd3cac9SReshma Pattan
2395cd3cac9SReshma PattanInitialization
2405cd3cac9SReshma Pattan~~~~~~~~~~~~~~
2415cd3cac9SReshma Pattan
2425cd3cac9SReshma PattanBefore the library can be used, it has to be initialised by calling
2435cd3cac9SReshma Pattan``rte_latencystats_init()``.
2445cd3cac9SReshma Pattan
2455cd3cac9SReshma Pattan.. code-block:: c
2465cd3cac9SReshma Pattan
2475cd3cac9SReshma Pattan    lcoreid_t latencystats_lcore_id = -1;
2485cd3cac9SReshma Pattan
2495cd3cac9SReshma Pattan    int ret = rte_latencystats_init(1, NULL);
2505cd3cac9SReshma Pattan    if (ret)
2515cd3cac9SReshma Pattan        rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
2525cd3cac9SReshma Pattan
2535cd3cac9SReshma Pattan
2545cd3cac9SReshma PattanTriggering statistic updates
2555cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2565cd3cac9SReshma Pattan
2575cd3cac9SReshma PattanThe ``rte_latencystats_update()`` function needs to be called
2585cd3cac9SReshma Pattanperiodically so that latency statistics can be updated.
2595cd3cac9SReshma Pattan
2605cd3cac9SReshma Pattan.. code-block:: c
2615cd3cac9SReshma Pattan
2625cd3cac9SReshma Pattan    if (latencystats_lcore_id == rte_lcore_id())
2635cd3cac9SReshma Pattan        rte_latencystats_update();
2645cd3cac9SReshma Pattan
2655cd3cac9SReshma PattanLibrary shutdown
2665cd3cac9SReshma Pattan~~~~~~~~~~~~~~~~
2675cd3cac9SReshma Pattan
2685cd3cac9SReshma PattanWhen finished, ``rte_latencystats_uninit()`` needs to be called to
2695cd3cac9SReshma Pattande-initialise the latency library.
2705cd3cac9SReshma Pattan
2715cd3cac9SReshma Pattan.. code-block:: c
2725cd3cac9SReshma Pattan
2735cd3cac9SReshma Pattan    rte_latencystats_uninit();
274