xref: /dpdk/doc/guides/prog_guide/metrics_lib.rst (revision 7fe90a66c718665e819ba68396e016ca51778d23)
1..  BSD LICENSE
2    Copyright(c) 2017 Intel Corporation. All rights reserved.
3    All rights reserved.
4
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8
9    * Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11    * Redistributions in binary form must reproduce the above copyright
12    notice, this list of conditions and the following disclaimer in
13    the documentation and/or other materials provided with the
14    distribution.
15    * Neither the name of Intel Corporation nor the names of its
16    contributors may be used to endorse or promote products derived
17    from this software without specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31.. _Metrics_Library:
32
33Metrics Library
34===============
35
36The Metrics library implements a mechanism by which *producers* can
37publish numeric information for later querying by *consumers*. In
38practice producers will typically be other libraries or primary
39processes, whereas consumers will typically be applications.
40
41Metrics themselves are statistics that are not generated by PMDs. Metric
42information is populated using a push model, where producers update the
43values contained within the metric library by calling an update function
44on the relevant metrics. Consumers receive metric information by querying
45the central metric data, which is held in shared memory.
46
47For each metric, a separate value is maintained for each port id, and
48when publishing metric values the producers need to specify which port is
49being updated. In addition there is a special id ``RTE_METRICS_GLOBAL``
50that is intended for global statistics that are not associated with any
51individual device. Since the metrics library is self-contained, the only
52restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS``
53- there is no requirement for the ports to actually exist.
54
55Initialising the library
56------------------------
57
58Before the library can be used, it has to be initialized by calling
59``rte_metrics_init()`` which sets up the metric store in shared memory.
60This is where producers will publish metric information to, and where
61consumers will query it from.
62
63.. code-block:: c
64
65    rte_metrics_init(rte_socket_id());
66
67This function **must** be called from a primary process, but otherwise
68producers and consumers can be in either primary or secondary processes.
69
70Registering metrics
71-------------------
72
73Metrics must first be *registered*, which is the way producers declare
74the names of the metrics they will be publishing. Registration can either
75be done individually, or a set of metrics can be registered as a group.
76Individual registration is done using ``rte_metrics_reg_name()``:
77
78.. code-block:: c
79
80    id_1 = rte_metrics_reg_name("mean_bits_in");
81    id_2 = rte_metrics_reg_name("mean_bits_out");
82    id_3 = rte_metrics_reg_name("peak_bits_in");
83    id_4 = rte_metrics_reg_name("peak_bits_out");
84
85or alternatively, a set of metrics can be registered together using
86``rte_metrics_reg_names()``:
87
88.. code-block:: c
89
90    const char * const names[] = {
91        "mean_bits_in", "mean_bits_out",
92        "peak_bits_in", "peak_bits_out",
93    };
94    id_set = rte_metrics_reg_names(&names[0], 4);
95
96If the return value is negative, it means registration failed. Otherwise
97the return value is the *key* for the metric, which is used when updating
98values. A table mapping together these key values and the metrics' names
99can be obtained using ``rte_metrics_get_names()``.
100
101Updating metric values
102----------------------
103
104Once registered, producers can update the metric for a given port using
105the ``rte_metrics_update_value()`` function. This uses the metric key
106that is returned when registering the metric, and can also be looked up
107using ``rte_metrics_get_names()``.
108
109.. code-block:: c
110
111    rte_metrics_update_value(port_id, id_1, values[0]);
112    rte_metrics_update_value(port_id, id_2, values[1]);
113    rte_metrics_update_value(port_id, id_3, values[2]);
114    rte_metrics_update_value(port_id, id_4, values[3]);
115
116if metrics were registered as a single set, they can either be updated
117individually using ``rte_metrics_update_value()``, or updated together
118using the ``rte_metrics_update_values()`` function:
119
120.. code-block:: c
121
122    rte_metrics_update_value(port_id, id_set, values[0]);
123    rte_metrics_update_value(port_id, id_set + 1, values[1]);
124    rte_metrics_update_value(port_id, id_set + 2, values[2]);
125    rte_metrics_update_value(port_id, id_set + 3, values[3]);
126
127    rte_metrics_update_values(port_id, id_set, values, 4);
128
129Note that ``rte_metrics_update_values()`` cannot be used to update
130metric values from *multiple* *sets*, as there is no guarantee two
131sets registered one after the other have contiguous id values.
132
133Querying metrics
134----------------
135
136Consumers can obtain metric values by querying the metrics library using
137the ``rte_metrics_get_values()`` function that return an array of
138``struct rte_metric_value``. Each entry within this array contains a metric
139value and its associated key. A key-name mapping can be obtained using the
140``rte_metrics_get_names()`` function that returns an array of
141``struct rte_metric_name`` that is indexed by the key. The following will
142print out all metrics for a given port:
143
144.. code-block:: c
145
146    void print_metrics() {
147        struct rte_metric_value *metrics;
148        struct rte_metric_name *names;
149        int len;
150
151        len = rte_metrics_get_names(NULL, 0);
152        if (len < 0) {
153            printf("Cannot get metrics count\n");
154            return;
155        }
156        if (len == 0) {
157            printf("No metrics to display (none have been registered)\n");
158            return;
159        }
160        metrics = malloc(sizeof(struct rte_metric_value) * len);
161        names =  malloc(sizeof(struct rte_metric_name) * len);
162        if (metrics == NULL || names == NULL) {
163            printf("Cannot allocate memory\n");
164            free(metrics);
165            free(names);
166            return;
167        }
168        ret = rte_metrics_get_values(port_id, metrics, len);
169        if (ret < 0 || ret > len) {
170            printf("Cannot get metrics values\n");
171            free(metrics);
172            free(names);
173            return;
174        }
175        printf("Metrics for port %i:\n", port_id);
176        for (i = 0; i < len; i++)
177            printf("  %s: %"PRIu64"\n",
178                names[metrics[i].key].name, metrics[i].value);
179        free(metrics);
180        free(names);
181    }
182
183
184Bit-rate statistics library
185---------------------------
186
187The bit-rate library calculates the exponentially-weighted moving
188average and peak bit-rates for each active port (i.e. network device).
189These statistics are reported via the metrics library using the
190following names:
191
192    - ``mean_bits_in``: Average inbound bit-rate
193    - ``mean_bits_out``:  Average outbound bit-rate
194    - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed)
195    - ``ewma_bits_out``:  Average outbound bit-rate (EWMA smoothed)
196    - ``peak_bits_in``:  Peak inbound bit-rate
197    - ``peak_bits_out``:  Peak outbound bit-rate
198
199Once initialised and clocked at the appropriate frequency, these
200statistics can be obtained by querying the metrics library.
201
202Initialization
203~~~~~~~~~~~~~~
204
205Before the library can be used, it has to be initialised by calling
206``rte_stats_bitrate_create()``, which will return a bit-rate
207calculation object. Since the bit-rate library uses the metrics library
208to report the calculated statistics, the bit-rate library then needs to
209register the calculated statistics with the metrics library. This is
210done using the helper function ``rte_stats_bitrate_reg()``.
211
212.. code-block:: c
213
214    struct rte_stats_bitrates *bitrate_data;
215
216    bitrate_data = rte_stats_bitrate_create();
217    if (bitrate_data == NULL)
218        rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n");
219    rte_stats_bitrate_reg(bitrate_data);
220
221Controlling the sampling rate
222~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223
224Since the library works by periodic sampling but does not use an
225internal thread, the application has to periodically call
226``rte_stats_bitrate_calc()``. The frequency at which this function
227is called should be the intended sampling rate required for the
228calculated statistics. For instance if per-second statistics are
229desired, this function should be called once a second.
230
231.. code-block:: c
232
233    tics_datum = rte_rdtsc();
234    tics_per_1sec = rte_get_timer_hz();
235
236    while( 1 ) {
237        /* ... */
238        tics_current = rte_rdtsc();
239	if (tics_current - tics_datum >= tics_per_1sec) {
240	    /* Periodic bitrate calculation */
241	    for (idx_port = 0; idx_port < cnt_ports; idx_port++)
242	            rte_stats_bitrate_calc(bitrate_data, idx_port);
243		tics_datum = tics_current;
244	    }
245        /* ... */
246    }
247
248
249Latency statistics library
250--------------------------
251
252The latency statistics library calculates the latency of packet
253processing by a DPDK application, reporting the minimum, average,
254and maximum nano-seconds that packet processing takes, as well as
255the jitter in processing delay. These statistics are then reported
256via the metrics library using the following names:
257
258    - ``min_latency_ns``: Minimum processing latency (nano-seconds)
259    - ``avg_latency_ns``:  Average  processing latency (nano-seconds)
260    - ``mac_latency_ns``:  Maximum  processing latency (nano-seconds)
261    - ``jitter_ns``: Variance in processing latency (nano-seconds)
262
263Once initialised and clocked at the appropriate frequency, these
264statistics can be obtained by querying the metrics library.
265
266Initialization
267~~~~~~~~~~~~~~
268
269Before the library can be used, it has to be initialised by calling
270``rte_latencystats_init()``.
271
272.. code-block:: c
273
274    lcoreid_t latencystats_lcore_id = -1;
275
276    int ret = rte_latencystats_init(1, NULL);
277    if (ret)
278        rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n");
279
280
281Triggering statistic updates
282~~~~~~~~~~~~~~~~~~~~~~~~~~~~
283
284The ``rte_latencystats_update()`` function needs to be called
285periodically so that latency statistics can be updated.
286
287.. code-block:: c
288
289    if (latencystats_lcore_id == rte_lcore_id())
290        rte_latencystats_update();
291
292Library shutdown
293~~~~~~~~~~~~~~~~
294
295When finished, ``rte_latencystats_uninit()`` needs to be called to
296de-initialise the latency library.
297
298.. code-block:: c
299
300    rte_latencystats_uninit();
301