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