xref: /freebsd/share/man/man3/stats.3 (revision 2e3507c25e42292b45a5482e116d278f5515d04d)
1.\"
2.\" Copyright (c) 2016-2018 Netflix, Inc.
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.\" 1. Redistributions of source code must retain the above copyright
9.\"    notice, this list of conditions, and the following disclaimer,
10.\"    without modification, immediately at the beginning of the file.
11.\" 2. The name of the author may not be used to endorse or promote products
12.\"    derived from this software without specific prior written permission.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18.\" ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE.
25.\"
26.Dd December 2, 2019
27.Dt STATS 3
28.Os
29.Sh NAME
30.Nm stats
31.Nd statistics gathering
32.Sh LIBRARY
33.Lb libstats
34.Sh SYNOPSIS
35.In sys/arb.h
36.In sys/qmath.h
37.In sys/stats.h
38.Ss Stats Blob Template Management Functions
39.Ft int
40.Fo stats_tpl_alloc
41.Fa "const char *name"
42.Fa "uint32_t flags"
43.Fc
44.Ft int
45.Fo stats_tpl_fetch_allocid
46.Fa "const char *name"
47.Fa "uint32_t hash"
48.Fc
49.Ft int
50.Fo stats_tpl_fetch
51.Fa "int tpl_id"
52.Fa "struct statsblob_tpl **tpl"
53.Fc
54.Ft int
55.Fo stats_tpl_id2name
56.Fa "uint32_t tpl_id"
57.Fa "char *buf"
58.Fa "size_t len"
59.Fc
60.Ft int
61.Fo stats_tpl_sample_rates
62.Fa "SYSCTL_HANDLER_ARGS"
63.Fc
64.Ft int
65.Fo stats_tpl_sample_rollthedice
66.Fa "struct stats_tpl_sample_rate *rates"
67.Fa "int nrates"
68.Fa "void *seed_bytes"
69.Fa "size_t seed_len"
70.Fc
71.Ft struct voistatspec
72.Fo STATS_VSS_SUM
73.Fc
74.Ft struct voistatspec
75.Fo STATS_VSS_MAX
76.Fc
77.Ft struct voistatspec
78.Fo STATS_VSS_MIN
79.Fc
80.Ft struct voistatspec
81.Fo STATS_VSS_CRHIST<32|64>_LIN
82.Fa "lb"
83.Fa "ub"
84.Fa "stepinc"
85.Fa "vsdflags"
86.Fc
87.Ft struct voistatspec
88.Fo STATS_VSS_CRHIST<32|64>_EXP
89.Fa "lb"
90.Fa "ub"
91.Fa "stepbase"
92.Fa "stepexp"
93.Fa "vsdflags"
94.Fc
95.Ft struct voistatspec
96.Fo "STATS_VSS_CRHIST<32|64>_LINEXP"
97.Fa "lb"
98.Fa "ub"
99.Fa "nlinsteps"
100.Fa "stepbase"
101.Fa "vsdflags"
102.Fc
103.Ft struct voistatspec
104.Fo "STATS_VSS_CRHIST<32|64>_USR"
105.Fa Sy "HBKTS" Ns Pq Sy "CRBKT" Ns ( Em "lb" ) , "..." Pc ,
106.Fa "vsdflags"
107.Fc
108.Ft struct voistatspec
109.Fo "STATS_VSS_DRHIST<32|64>_USR"
110.Fa Sy "HBKTS" Ns Pq Sy "DRBKT" Ns ( Em "lb" , "ub" ) , "..." Pc ,
111.Fa "vsdflags"
112.Fc
113.Ft struct voistatspec
114.Fo "STATS_VSS_DVHIST<32|64>_USR"
115.Fa Sy "HBKTS" Ns Pq Sy "DVBKT" Ns ( Em "val" ) , "..." Pc ,
116.Fa "vsdflags"
117.Fc
118.Ft struct voistatspec
119.Fo STATS_VSS_TDGSTCLUST<32|64>
120.Fa "nctroids"
121.Fa "prec"
122.Fc
123.Ft int
124.Fo stats_tpl_add_voistats
125.Fa "uint32_t tpl_id"
126.Fa "int32_t voi_id"
127.Fa "const char *voi_name"
128.Fa "enum vsd_dtype voi_dtype"
129.Fa "uint32_t nvss"
130.Fa "struct voistatspec *vss"
131.Fa "uint32_t flags"
132.Fc
133.Ss Stats Blob Data Gathering Functions
134.Ft int
135.Fo stats_voi_update_<abs|rel>_<dtype>
136.Fa "struct statsblob *sb"
137.Fa "int32_t voi_id"
138.Fa "<dtype> voival"
139.Fc
140.Ss Stats Blob Utility Functions
141.Ft struct statsblob *
142.Fo stats_blob_alloc
143.Fa "uint32_t tpl_id"
144.Fa "uint32_t flags"
145.Fc
146.Ft int
147.Fo stats_blob_init
148.Fa "struct statsblob *sb"
149.Fa "uint32_t tpl_id"
150.Fa "uint32_t flags"
151.Fc
152.Ft int
153.Fo stats_blob_clone
154.Fa "struct statsblob **dst"
155.Fa "size_t dstmaxsz"
156.Fa "struct statsblob *src"
157.Fa "uint32_t flags"
158.Fc
159.Ft void
160.Fo stats_blob_destroy
161.Fa "struct statsblob *sb"
162.Fc
163.Ft int
164.Fo stats_voistat_fetch_dptr
165.Fa "struct statsblob *sb"
166.Fa "int32_t voi_id"
167.Fa "enum voi_stype stype"
168.Fa "enum vsd_dtype *retdtype"
169.Fa "struct voistatdata **retvsd"
170.Fa "size_t *retvsdsz"
171.Fc
172.Ft int
173.Fo stats_voistat_fetch_<dtype>
174.Fa "struct statsblob *sb"
175.Fa "int32_t voi_id"
176.Fa "enum voi_stype stype"
177.Fa "<dtype> *ret"
178.Fc
179.Ft int
180.Fo stats_blob_snapshot
181.Fa "struct statsblob **dst"
182.Fa "size_t dstmaxsz"
183.Fa "struct statsblob *src"
184.Fa "uint32_t flags"
185.Fc
186.Ft int
187.Fo stats_blob_tostr
188.Fa "struct statsblob *sb"
189.Fa "struct sbuf *buf"
190.Fa "enum sb_str_fmt fmt"
191.Fa "uint32_t flags"
192.Fc
193.Ft int
194.Fo stats_voistatdata_tostr
195.Fa "const struct voistatdata *vsd"
196.Fa "enum vsd_dtype dtype"
197.Fa "enum sb_str_fmt fmt"
198.Fa "struct sbuf *buf"
199.Fa "int objdump"
200.Fc
201.Ft typedef int
202.Fn "\*(lp*stats_blob_visitcb_t\*(rp" "struct sb_visit *sbv" "void *usrctx"
203.Ft int
204.Fo stats_blob_visit
205.Fa "struct statsblob *sb"
206.Fa "stats_blob_visitcb_t func"
207.Fa "void *usrctx"
208.Fc
209.Sh DESCRIPTION
210The
211.Nm
212framework facilitates real-time kernel and user space statistics gathering.
213The framework is built around the
214.Dq statsblob ,
215an object embedded within a contiguous memory allocation that is mostly opaque
216to consumers and stores all required state.
217A
218.Dq statsblob
219object can itself be embedded within other objects either directly or indirectly
220using a pointer.
221.Pp
222Objects or subsystems for which statistics are to be gathered are initialized
223from a template
224.Dq statsblob ,
225which acts as the blueprint for an arbitrary set of
226Variables Of Interest (VOIs) and their associated statistics.
227Each template defines a schema plus associated metadata, which are kept separate
228to minimize the memory footprint of blobs.
229.Pp
230Data gathering hook functions added at appropriate locations within the code
231base of interest feed VOI data into the framework for processing.
232.Pp
233Each
234.Dq statsblob ,
235consists of a
236.Vt struct statsblob
237header and opaque internal blob structure per the following diagram:
238.Bd -literal -offset indent
239---------------------------------------------------------
240|   struct  |		       uint8_t			|
241| statsblob |		      opaque[]			|
242---------------------------------------------------------
243.Ed
244.Pp
245The publicly visible 8-byte header is defined as:
246.Bd -literal -offset indent
247struct statsblob {
248	uint8_t		abi;
249	uint8_t		endian;
250	uint16_t	flags;
251	uint16_t	maxsz;
252	uint16_t	cursz;
253	uint8_t		opaque[];
254};
255.Ed
256.Pp
257.Va abi
258specifies which API version the blob's
259.Va opaque
260internals conform to
261.Pq Dv STATS_ABI_V1 is the only version currently defined .
262.Va endian
263specifies the endianness of the blob's fields
264.Po
265.Dv SB_LE
266for little endian,
267.Dv SB_BE
268for big endian, or
269.Dv SB_UE
270for unknown endianness
271.Pc .
272.Va cursz
273specifies the size of the blob, while
274.Va maxsz
275specifies the size of the underlying memory allocation in which the
276blob is embedded.
277Both
278.Va cursz
279and
280.Va maxsz
281default to units of bytes, unless a flag is set in
282.Va flags
283that dictates otherwise.
284.Pp
285Templates are constructed by associating arbitrary VOI IDs with a set of
286statistics, where each statistic is specified using a
287.Vt struct voistatspec
288per the definition below:
289.Bd -literal -offset indent
290struct voistatspec {
291	vss_hlpr_fn		hlpr;
292	struct vss_hlpr_info	*hlprinfo;
293	struct voistatdata	*iv;
294	size_t			vsdsz;
295	uint32_t		flags;
296	enum vsd_dtype		vs_dtype : 8;
297	enum voi_stype		stype : 8;
298};
299.Ed
300.Pp
301It is generally expected that consumers will not work with
302.Vt struct voistatspec
303directly, and instead use the
304.Fn STATS_VSS_*
305helper macros.
306.Pp
307The
308.Nm
309framework offers the following statistics for association with VOIs:
310.Bl -tag -width ".Dv VS_STYPE_TDGST"
311.It Dv VS_STYPE_SUM
312The sum of VOI values.
313.It Dv VS_STYPE_MAX
314The maximum VOI value.
315.It Dv VS_STYPE_MIN
316The minimum VOI value.
317.It Dv VS_STYPE_HIST
318A static bucket histogram of VOI values, including a count of
319.Dq out-of-band/bucket Dc
320values which did not match any bucket.
321Histograms can be specified as
322.Dq Em C Ns ontinuous Em R Ns ange Dc
323.Pq CRHIST Pc ,
324.Dq Em D Ns iscrete Em R Ns ange Dc
325.Pq DRHIST Pc
326or
327.Dq Em D Ns iscrete Em V Ns alue Dc
328.Pq DVHIST Pc ,
329with 32 or 64 bit bucket counters, depending on the VOI semantics.
330.It Dv VS_STYPE_TDGST
331A dynamic bucket histogram of VOI values based on the t-digest method
332.Po refer to the t-digest paper in the
333.Sx SEE ALSO
334section below
335.Pc .
336.El
337.Pp
338A
339.Dq visitor software design pattern Ns
340-like scheme is employed to facilitate iterating over a blob's data without
341concern for the blob's structure.
342The data provided to visitor callback functions is encapsulated in
343.Vt struct sb_visit
344per the definition below:
345.Bd -literal -offset indent
346struct sb_visit {
347	struct voistatdata	*vs_data;
348	uint32_t		tplhash;
349	uint32_t		flags;
350	int16_t			voi_id;
351	int16_t			vs_dsz;
352	enum vsd_dtype		voi_dtype : 8;
353	enum vsd_dtype		vs_dtype : 8;
354	int8_t			vs_stype;
355	uint16_t		vs_errs;
356};
357.Ed
358.Pp
359The
360.Fn stats_tpl_sample_rates
361and
362.Fn stats_tpl_sample_rollthedice
363functions utilize
364.Vt struct stats_tpl_sample_rate
365to encapsulate per-template sample rate information per the definition below:
366.Bd -literal -offset indent
367struct stats_tpl_sample_rate {
368	int32_t		tpl_slot_id;
369	uint32_t	tpl_sample_pct;
370};
371.Ed
372.Pp
373The
374.Va tpl_slot_id
375member holds the template's slot ID obtained from
376.Fn stats_tpl_alloc
377or
378.Fn stats_tpl_fetch_allocid .
379The
380.Va tpl_sample_pct
381member holds the template's sample rate as an integer percentage in the range
382[0,100].
383.Pp
384The
385.Vt stats_tpl_sr_cb_t
386conformant function pointer that is required as the
387.Fa arg1
388of
389.Fn stats_tpl_sample_rates
390is defined as:
391.Bd -literal -offset indent
392enum stats_tpl_sr_cb_action {
393	TPL_SR_UNLOCKED_GET,
394	TPL_SR_RLOCKED_GET,
395	TPL_SR_RUNLOCK,
396	TPL_SR_PUT
397};
398typedef int (*stats_tpl_sr_cb_t)(enum stats_tpl_sr_cb_action action,
399    struct stats_tpl_sample_rate **rates, int *nrates, void *ctx);
400.Ed
401.Pp
402It is required that a conformant function:
403.Bl -dash
404.It
405Return an appropriate
406.Xr errno 2
407on error, otherwise 0.
408.It
409When called with
410.Qq action == TPL_SR_*_GET ,
411return the subsystem's rates list ptr and count, locked or unlocked as
412requested.
413.It
414When called with
415.Qq action == TPL_SR_RUNLOCK ,
416unlock the subsystem's rates list ptr and count.
417Pair with a prior
418.Qq action == TPL_SR_RLOCKED_GET
419call.
420.It
421When called with
422.Qq action == TPL_SR_PUT ,
423update the subsystem's rates list ptr and count to the sysctl processed values
424and return the inactive list details in
425.Fa rates
426and
427.Fa nrates
428for garbage collection by
429.Fn stats_tpl_sample_rates .
430.El
431.Pp
432Where templates need to be referenced via textual means, for example via a MIB
433variable, the following string based template spec formats can be used:
434.Bl -enum
435.It
436.Qq <tplname> Qc Ns
437:<tplhash>
438.Ns , for example
439.Qq TCP_DEFAULT Qc Ns
440:1731235399
441.It
442.Qq <tplname> Qc
443.Ns , for example
444.Qq TCP_DEFAULT Qc
445.It
446:<tplhash>
447.Ns , for example
448:1731235399
449.El
450.Pp
451The first form is the normative spec format generated by the framework, while
452the second and third forms are convenience formats primarily for user input.
453The use of inverted commas around the template name is optional.
454.Ss MIB Variables
455The in-kernel
456.Nm
457framework exposes the following framework-specific variables in the
458.Va kern.stats
459branch of the
460.Xr sysctl 3
461MIB.
462.Bl -tag -width "templates"
463.It templates
464Read-only CSV list of registered templates in normative template spec form.
465.El
466.Ss Template Management Functions
467The
468.Fn stats_tpl_alloc
469function allocates a new template with the specified unique name and returns its
470runtime-stable template slot ID for use with other API functions.
471The
472.Fa flags
473argument is currently unused.
474.Pp
475The
476.Fn stats_tpl_fetch_allocid
477function returns the runtime-stable template slot ID of any registered template
478matching the specified name and hash.
479.Pp
480The
481.Fn stats_tpl_fetch
482function returns the pointer to the registered template object at the specified
483template slot ID.
484.Pp
485The
486.Fn stats_tpl_id2name
487function returns the name of the registered template object at the specified
488template slot ID.
489.Pp
490The
491.Fn stats_tpl_sample_rates
492function provides a generic handler for template sample rates management and
493reporting via
494.Xr sysctl 3
495MIB variables.
496Subsystems can use this function to create a subsystem-specific
497.Xr SYSCTL_PROC 9
498MIB variable that manages and reports subsystem-specific template sampling
499rates.
500Subsystems must supply a
501.Vt stats_tpl_sr_cb_t
502conformant function pointer as the sysctl's
503.Fa arg1 ,
504which is a callback used to interact with the subsystem's stats template sample
505rates list.
506Subsystems can optionally specify the sysctl's
507.Fa arg2
508as non-zero, which causes a zero-initialized allocation of arg2-sized contextual
509memory to be heap-allocated and passed in to all subsystem callbacks made during
510the operation of
511.Fn stats_tpl_sample_rates .
512.Pp
513The
514.Fn stats_tpl_sample_rollthedice
515function makes a weighted random template selection from the supplied array of
516template sampling rates.
517The cumulative percentage of all sampling rates should not exceed 100.
518If no seed is supplied, a PRNG is used to generate a true random number so that
519every selection is independent.
520If a seed is supplied, selection will be made randomly across different seeds, but
521deterministically given the same seed.
522.Pp
523The
524.Fn stats_tpl_add_voistats
525function is used to add a VOI and associated set of statistics to the registered
526template object at the specified template slot ID.
527The set of statistics is passed as an array of
528.Vt struct voistatspec
529which can be initialized using the
530.Fn STATS_VSS_*
531helper macros or manually for non-standard use cases.
532For static
533.Fa vss
534arrays, the
535.Fa nvss
536count of array elements can be determined by passing
537.Fa vss
538to the
539.Fn NVSS
540macro.
541The
542.Dv SB_VOI_RELUPDATE
543flag can be passed to configure the VOI for use with
544.Fn stats_voi_update_rel_<dtype> ,
545which entails maintaining an extra 8 bytes of state in the blob at each update.
546.Ss Data Gathering Functions
547The
548.Fn stats_voi_update_abs_<dtype>
549and
550.Fn stats_voi_update_rel_<dtype>
551functions both update all the statistics associated with the VOI identified by
552.Fa voi_id .
553The
554.Dq abs
555call uses
556.Fa voival
557as an absolute value, whereas the
558.Dq rel
559call uses
560.Fa voival
561as a value relative to that of the previous update function call, by adding it
562to the previous value and using the result for the update.
563Relative updates are only possible for VOIs that were added to the template with
564the
565.Dv SB_VOI_RELUPDATE
566flag specified to
567.Fn stats_tpl_add_voistats .
568.Ss Utility Functions
569The
570.Fn stats_blob_alloc
571function allocates and initializes a new blob based on the registered template
572object at the specified template slot ID.
573.Pp
574The
575.Fn stats_blob_init
576function initializes a new blob in an existing memory allocation based on the
577registered template object at the specified template slot ID.
578.Pp
579The
580.Fn stats_blob_clone
581function duplicates the
582.Fa src
583blob into
584.Fa dst ,
585leaving only the
586.Va maxsz
587field of
588.Fa dst
589untouched.
590The
591.Dv SB_CLONE_ALLOCDST
592flag can be passed to instruct the function to allocate a new blob of
593appropriate size into which to clone
594.Fa src ,
595storing the new pointer in
596.Fa *dst .
597The
598.Dv SB_CLONE_USRDSTNOFAULT
599or
600.Dv SB_CLONE_USRDST
601flags can be set to respectively signal that
602.Xr copyout_nofault 9
603or
604.Xr copyout 9
605should be used because
606.Fa *dst
607is a user space address.
608.Pp
609The
610.Fn stats_blob_snapshot
611function calls
612.Fn stats_blob_clone
613to obtain a copy of
614.Fa src
615and then performs any additional functions required to produce a coherent
616blob snapshot.
617The flags interpreted by
618.Fn stats_blob_clone
619also apply to
620.Fn stats_blob_snapshot .
621Additionally, the
622.Dv SB_CLONE_RSTSRC
623flag can be used to effect a reset of the
624.Fa src
625blob's statistics after a snapshot is successfully taken.
626.Pp
627The
628.Fn stats_blob_destroy
629function destroys a blob previously created with
630.Fn stats_blob_alloc ,
631.Fn stats_blob_clone
632or
633.Fn stats_blob_snapshot .
634.Pp
635The
636.Fn stats_blob_visit
637function allows the caller to iterate over the contents of a blob.
638The callback function
639.Fa func
640is called for every VOI and statistic in the blob, passing a
641.Vt struct sb_visit
642and the user context argument
643.Fa usrctx
644to the callback function.
645The
646.Fa sbv
647passed to the callback function may have one or more of the following flags set
648in the
649.Va flags
650struct member to provide useful metadata about the iteration:
651.Dv SB_IT_FIRST_CB ,
652.Dv SB_IT_LAST_CB ,
653.Dv SB_IT_FIRST_VOI ,
654.Dv SB_IT_LAST_VOI ,
655.Dv SB_IT_FIRST_VOISTAT ,
656.Dv SB_IT_LAST_VOISTAT ,
657.Dv SB_IT_NULLVOI
658and
659.Dv SB_IT_NULLVOISTAT .
660Returning a non-zero value from the callback function terminates the iteration.
661.Pp
662The
663.Fn stats_blob_tostr
664renders a string representation of a blob into the
665.Xr sbuf 9
666.Fa buf .
667Currently supported render formats are
668.Dv SB_STRFMT_FREEFORM
669and
670.Dv SB_STRFMT_JSON .
671The
672.Dv SB_TOSTR_OBJDUMP
673flag can be passed to render version specific opaque implementation detail for
674debugging or string-to-binary blob reconstruction purposes.
675The
676.Dv SB_TOSTR_META
677flag can be passed to render template metadata into the string representation,
678using the blob's template hash to lookup the corresponding template.
679.Pp
680The
681.Fn stats_voistatdata_tostr
682renders a string representation of an individual statistic's data into the
683.Xr sbuf 9
684.Fa buf .
685The same render formats supported by the
686.Fn stats_blob_tostr
687function can be specified, and the
688.Fa objdump
689boolean has the same meaning as the
690.Dv SB_TOSTR_OBJDUMP
691flag.
692.Pp
693The
694.Fn stats_voistat_fetch_dptr
695function returns an internal blob pointer to the specified
696.Fa stype
697statistic data for the VOI
698.Fa voi_id .
699The
700.Fn stats_voistat_fetch_<dtype>
701functions are convenience wrappers around
702.Fn stats_voistat_fetch_dptr
703to perform the extraction for simple data types.
704.Sh IMPLEMENTATION NOTES
705The following notes apply to STATS_ABI_V1 format statsblobs.
706.Ss Space-Time Complexity
707Blobs are laid out as three distinct memory regions following the header:
708.Bd -literal -offset indent
709------------------------------------------------------
710|   struct    | struct |   struct   |     struct     |
711| statsblobv1 | voi [] | voistat [] | voistatdata [] |
712------------------------------------------------------
713.Ed
714.Pp
715Blobs store VOI and statistic blob state
716.Po
7178 bytes for
718.Vt struct voi
719and 8 bytes for
720.Vt struct voistat
721respectively
722.Pc
723in sparse arrays, using the
724.Fa voi_id
725and
726.Vt enum voi_stype
727as array indices.
728This allows O(1) access to any voi/voistat pair in the blob, at the expense of
7298 bytes of wasted memory per vacant slot for templates which do not specify
730contiguously numbered VOIs and/or statistic types.
731Data storage for statistics is only allocated for non-vacant slot pairs.
732.Pp
733To provide a concrete example, a blob with the following specification:
734.Bl -dash
735.It
736Two VOIs; ID 0 and 2; added to the template in that order
737.It
738VOI 0 is of data type
739.Vt int64_t ,
740is configured with
741.Dv SB_VOI_RELUPDATE
742to enable support for relative updates using
743.Fn stats_voi_update_rel_<dtype> ,
744and has a
745.Dv VS_STYPE_MIN
746statistic associated with it.
747.It
748VOI 2 is of data type
749.Vt uint32_t
750with
751.Dv VS_STYPE_SUM
752and
753.Dv VS_STYPE_MAX
754statistics associated with it.
755.El
756.Pp
757would have the following memory layout:
758.Bd -literal
759--------------------------------------
760| header			     | struct statsblobv1, 32 bytes
761|------------------------------------|
762| voi[0]			     | struct voi, 8 bytes
763| voi[1] (vacant)		     | struct voi, 8 bytes
764| voi[2]			     | struct voi, 8 bytes
765|------------------------------------|
766| voi[2]voistat[VOISTATE] (vacant)   | struct voistat, 8 bytes
767| voi[2]voistat[SUM]		     | struct voistat, 8 bytes
768| voi[2]voistat[MAX]		     | struct voistat, 8 bytes
769| voi[0]voistat[VOISTATE]	     | struct voistat, 8 bytes
770| voi[0]voistat[SUM] (vacant)	     | struct voistat, 8 bytes
771| voi[0]voistat[MAX] (vacant)	     | struct voistat, 8 bytes
772| voi[0]voistat[MIN]		     | struct voistat, 8 bytes
773|------------------------------------|
774| voi[2]voistat[SUM]voistatdata      | struct voistatdata_int32, 4 bytes
775| voi[2]voistat[MAX]voistatdata      | struct voistatdata_int32, 4 bytes
776| voi[0]voistat[VOISTATE]voistatdata | struct voistatdata_numeric, 8 bytes
777| voi[0]voistat[MIN]voistatdata      | struct voistatdata_int64, 8 bytes
778--------------------------------------
779				       TOTAL 136 bytes
780.Ed
781.Pp
782When rendered to string format using
783.Fn stats_blob_tostr ,
784the
785.Dv SB_STRFMT_FREEFORM
786.Fa fmt
787and the
788.Dv SB_TOSTR_OBJDUMP
789flag, the rendered output is:
790.Bd -literal
791struct statsblobv1@0x8016250a0, abi=1, endian=1, maxsz=136, cursz=136, \\
792  created=6294158585626144, lastrst=6294158585626144, flags=0x0000, \\
793  stats_off=56, statsdata_off=112, tplhash=2994056564
794    vois[0]: id=0, name="", flags=0x0001, dtype=INT_S64, voistatmaxid=3, \\
795      stats_off=80
796        vois[0]stat[0]: stype=VOISTATE, flags=0x0000, dtype=VOISTATE, \\
797          dsz=8, data_off=120
798            voistatdata: prev=0
799        vois[0]stat[1]: stype=-1
800        vois[0]stat[2]: stype=-1
801        vois[0]stat[3]: stype=MIN, flags=0x0000, dtype=INT_S64, \\
802          dsz=8, data_off=128
803            voistatdata: 9223372036854775807
804    vois[1]: id=-1
805    vois[2]: id=2, name="", flags=0x0000, dtype=INT_U32, voistatmaxid=2, \\
806      stats_off=56
807        vois[2]stat[0]: stype=-1
808        vois[2]stat[1]: stype=SUM, flags=0x0000, dtype=INT_U32, dsz=4, \\
809          data_off=112
810            voistatdata: 0
811        vois[2]stat[2]: stype=MAX, flags=0x0000, dtype=INT_U32, dsz=4, \\
812          data_off=116
813            voistatdata: 0
814.Ed
815.Pp
816Note: The
817.Qq \e
818present in the rendered output above indicates a manual line break inserted to
819keep the man page within 80 columns and is not part of the actual output.
820.Ss Locking
821The
822.Nm
823framework does not provide any concurrency protection at the individual blob
824level, instead requiring that consumers guarantee mutual exclusion when calling
825API functions that reference a non-template blob.
826.Pp
827The list of templates is protected with a
828.Xr rwlock 9
829in-kernel, and
830.Xr pthread 3
831rw lock in user space to support concurrency between template management and
832blob initialization operations.
833.Sh RETURN VALUES
834.Fn stats_tpl_alloc
835returns a runtime-stable template slot ID on success, or a negative errno on
836failure.
837-EINVAL is returned if any problems are detected with the arguments.
838-EEXIST is returned if an existing template is registered with the same name.
839-ENOMEM is returned if a required memory allocation fails.
840.Pp
841.Fn stats_tpl_fetch_allocid
842returns a runtime-stable template slot ID, or negative errno on failure.
843-ESRCH is returned if no registered template matches the specified name and/or
844hash.
845.Pp
846.Fn stats_tpl_fetch
847returns 0 on success, or ENOENT if an invalid
848.Fa tpl_id
849is specified.
850.Pp
851.Fn stats_tpl_id2name
852returns 0 on success, or an errno on failure.
853EOVERFLOW is returned if the length of
854.Fa buf
855specified by
856.Fa len
857is too short to hold the template's name.
858ENOENT is returned if an invalid
859.Fa tpl_id
860is specified.
861.Pp
862.Fn stats_tpl_sample_rollthedice
863returns a valid template slot id selected from
864.Fa rates
865or -1 if a NULL selection was made, that is no stats collection this roll.
866.Pp
867.Fn stats_tpl_add_voistats
868return 0 on success, or an errno on failure.
869EINVAL is returned if any problems are detected with the arguments.
870EFBIG is returned if the resulting blob would have exceeded the maximum size.
871EOPNOTSUPP is returned if an attempt is made to add more VOI stats to a
872previously configured VOI.
873ENOMEM is returned if a required memory allocation fails.
874.Pp
875.Fn stats_voi_update_abs_<dtype>
876and
877.Fn stats_voi_update_rel_<dtype>
878return 0 on success, or EINVAL if any problems are detected with the arguments.
879.Pp
880.Fn stats_blob_init
881returns 0 on success, or an errno on failure.
882EINVAL is returned if any problems are detected with the arguments.
883EOVERFLOW is returned if the template blob's
884.Fa cursz
885is larger than the
886.Fa maxsz
887of the blob being initialized.
888.Pp
889.Fn stats_blob_alloc
890returns a pointer to a newly allocated and initialized blob based on the
891specified template with slot ID
892.Fa tpl_id ,
893or NULL if the memory allocation failed.
894.Pp
895.Fn stats_blob_clone
896and
897.Fn stats_blob_snapshot
898return 0 on success, or an errno on failure.
899EINVAL is returned if any problems are detected with the arguments.
900ENOMEM is returned if the SB_CLONE_ALLOCDST flag was specified and the memory
901allocation for
902.Fa dst
903fails.
904EOVERFLOW is returned if the src blob's
905.Fa cursz
906is larger than the
907.Fa maxsz
908of the
909.Fa dst
910blob.
911.Pp
912.Fn stats_blob_visit
913returns 0 on success, or EINVAL if any problems are detected with the arguments.
914.Pp
915.Fn stats_blob_tostr
916and
917.Fn stats_voistatdata_tostr
918return 0 on success, or an errno on failure.
919EINVAL is returned if any problems are detected with the arguments, otherwise
920any error returned by
921.Fn sbuf_error
922for
923.Fa buf
924is returned.
925.Pp
926.Fn stats_voistat_fetch_dptr
927returns 0 on success, or EINVAL if any problems are detected with the arguments.
928.Pp
929.Fn stats_voistat_fetch_<dtype>
930returns 0 on success, or an errno on failure.
931EINVAL is returned if any problems are detected with the arguments.
932EFTYPE is returned if the requested data type does not match the blob's data
933type for the specified
934.Fa voi_id
935and
936.Fa stype .
937.Sh SEE ALSO
938.Xr errno 2 ,
939.Xr arb 3 ,
940.Xr qmath 3 ,
941.Xr tcp 4 ,
942.Xr sbuf 9
943.Rs
944.%A "Ted Dunning"
945.%A "Otmar Ertl"
946.%T "Computing Extremely Accurate Quantiles Using t-digests"
947.%U "https://github.com/tdunning/t-digest/raw/master/docs/t-digest-paper/histo.pdf"
948.Re
949.Sh HISTORY
950The
951.Nm
952framework first appeared in
953.Fx 13.0 .
954.Sh AUTHORS
955.An -nosplit
956The
957.Nm
958framework and this manual page were written by
959.An Lawrence Stewart Aq lstewart@FreeBSD.org
960and sponsored by Netflix, Inc.
961.Sh CAVEATS
962Granularity of timing-dependent network statistics, in particular TCP_RTT,
963depends on the
964.Dv HZ
965timer.
966To minimize the measurement error avoid using HZ lower than 1000.
967