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