xref: /freebsd/contrib/libxo/doc/faq.rst (revision 6419bb52)
1
2FAQs
3====
4
5This section contains the set of questions that users typically ask,
6along with answers that might be helpful.
7
8General
9-------
10
11Can you share the history of libxo?
12~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13
14In 2001, we added an XML API to the JUNOS operating system, which is
15built on top of FreeBSD_.  Eventually this API became standardized as
16the NETCONF API (:RFC:`6241`).  As part of this effort, we modified many
17FreeBSD utilities to emit XML, typically via a "-X" switch.  The
18results were mixed.  The cost of maintaining this code, updating it,
19and carrying it were non-trivial, and contributed to our expense (and
20the associated delay) with upgrading the version of FreeBSD on which
21each release of JUNOS is based.
22
23.. _FreeBSD: https://www.freebsd.org
24
25A recent (2014) effort within JUNOS aims at removing our modifications
26to the underlying FreeBSD code as a means of reducing the expense and
27delay in tracking HEAD.  JUNOS is structured to have system components
28generate XML that is rendered by the CLI (think: login shell) into
29human-readable text.  This allows the API to use the same plumbing as
30the CLI, and ensures that all components emit XML, and that it is
31emitted with knowledge of the consumer of that XML, yielding an API
32that have no incremental cost or feature delay.
33
34libxo is an effort to mix the best aspects of the JUNOS strategy into
35FreeBSD in a seemless way, allowing commands to make printf-like
36output calls with a single code path.
37
38Did the complex semantics of format strings evolve over time?
39~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40
41The history is both long and short: libxo's functionality is based
42on what JUNOS does in a data modeling language called ODL (output
43definition language).  In JUNOS, all subcomponents generate XML,
44which is feed to the CLI, where data from the ODL files tell is
45how to render that XML into text.  ODL might had a set of tags
46like::
47
48     tag docsis-state {
49         help "State of the DOCSIS interface";
50         type string;
51     }
52
53     tag docsis-mode {
54         help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
55         type string;
56     }
57
58     tag docsis-upstream-speed {
59         help "Operational upstream speed of the interface";
60         type string;
61     }
62
63     tag downstream-scanning {
64         help "Result of scanning in downstream direction";
65         type string;
66     }
67
68     tag ranging {
69         help "Result of ranging action";
70         type string;
71     }
72
73     tag signal-to-noise-ratio {
74         help "Signal to noise ratio for all channels";
75         type string;
76     }
77
78     tag power {
79         help "Operational power of the signal on all channels";
80         type string;
81     }
82
83     format docsis-status-format {
84         picture "
85     State   : @, Mode: @, Upstream speed: @
86     Downstream scanning: @, Ranging: @
87     Signal to noise ratio: @
88     Power: @
89     ";
90         line {
91             field docsis-state;
92             field docsis-mode;
93             field docsis-upstream-speed;
94             field downstream-scanning;
95             field ranging;
96             field signal-to-noise-ratio;
97             field power;
98         }
99     }
100
101These tag definitions are compiled into field definitions
102that are triggered when matching XML elements are seen.  ODL
103also supports other means of defining output.
104
105The roles and modifiers describe these details.
106
107In moving these ideas to bsd, two things had to happen: the
108formatting had to happen at the source since BSD won't have
109a JUNOS-like CLI to do the rendering, and we can't depend on
110external data models like ODL, which was seen as too hard a
111sell to the BSD community.
112
113The results were that the xo_emit strings are used to encode the
114roles, modifiers, names, and formats.  They are dense and a bit
115cryptic, but not so unlike printf format strings that developers will
116be lost.
117
118libxo is a new implementation of these ideas and is distinct from
119the previous implementation in JUNOS.
120
121.. index:: XOF_UNDERSCORES
122
123.. _good-field-names:
124
125What makes a good field name?
126~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
128To make useful, consistent field names, follow these guidelines:
129
130Use lower case, even for TLAs
131  Lower case is more civilized.  Even TLAs should be lower case
132  to avoid scenarios where the differences between "XPath" and
133  "Xpath" drive your users crazy.  Using "xpath" is simpler and better.
134
135Use hyphens, not underscores
136  Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
137  flag can be used to generate underscores in JSON, if desired.
138  But the raw field name should use hyphens.
139
140Use full words
141  Don't abbreviate especially when the abbreviation is not obvious or
142  not widely used.  Use "data-size", not "dsz" or "dsize".  Use
143  "interface" instead of "ifname", "if-name", "iface", "if", or "intf".
144
145Use <verb>-<units>
146  Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
147  making consistent, useful names, avoiding the situation where one app
148  uses "sent-packet" and another "packets-sent" and another
149  "packets-we-have-sent".  The <units> can be dropped when it is
150  obvious, as can obvious words in the classification.
151  Use "receive-after-window-packets" instead of
152  "received-packets-of-data-after-window".
153
154Reuse existing field names
155  Nothing's worse than writing expressions like::
156
157    if ($src1/process[pid == $pid]/name ==
158        $src2/proc-table/proc-list
159                   /prc-entry[prcss-id == $pid]/proc-name) {
160        ...
161    }
162
163  Find someone else who is expressing similar data and follow their
164  fields and hierarchy.  Remember the quote is not "Consistency is the
165  hobgoblin of little minds", but "A *foolish* consistency is the
166  hobgoblin of little minds".  Consistency rocks!
167
168Use containment as scoping
169  In the previous example, all the names are prefixed with "proc-",
170  which is redundant given that they are nested under the process table.
171
172Think about your users
173  Have empathy for your users, choosing clear and useful fields that
174  contain clear and useful data.  You may need to augment the display
175  content with xo_attr() calls (:ref:`xo_attr`) or "{e:}"
176  fields (:ref:`encoding-modifier`) to make the data useful.
177
178Don't use an arbitrary number postfix
179  What does "errors2" mean?  No one will know.  "errors-after-restart"
180  would be a better choice.  Think of your users, and think of the
181  future.  If you make "errors2", the next guy will happily make
182  "errors3" and before you know it, someone will be asking what's the
183  difference between errors37 and errors63.
184
185Be consistent, uniform, unsurprising, and predictable
186  Think of your field vocabulary as an API.  You want it useful,
187  expressive, meaningful, direct, and obvious.  You want the client
188  application's programmer to move between without the need to
189  understand a variety of opinions on how fields are named.  They
190  should see the system as a single cohesive whole, not a sack of
191  cats.
192
193Field names constitute the means by which client programmers interact
194with our system.  By choosing wise names now, you are making their
195lives better.
196
197After using `xolint` to find errors in your field descriptors, use
198"`xolint -V`" to spell check your field names and to help you detect
199different names for the same data.  "dropped-short" and
200"dropped-too-short" are both reasonable names, but using them both
201will lead users to ask the difference between the two fields.  If
202there is no difference, use only one of the field names.  If there is
203a difference, change the names to make that difference more obvious.
204
205What does this message mean?
206~~~~~~~~~~~~~~~~~~~~~~~~~~~~
207
208.. include:: xolint.rst
209