5 This section contains the set of questions that users typically ask,
6 along with answers that might be helpful.
11 Can you share the history of libxo?
12 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 In 2001, we added an XML API to the JUNOS operating system, which is
15 built on top of FreeBSD_. Eventually this API became standardized as
16 the NETCONF API (:RFC:`6241`). As part of this effort, we modified many
17 FreeBSD utilities to emit XML, typically via a "-X" switch. The
18 results were mixed. The cost of maintaining this code, updating it,
19 and carrying it were non-trivial, and contributed to our expense (and
20 the associated delay) with upgrading the version of FreeBSD on which
21 each release of JUNOS is based.
23 .. _FreeBSD: https://www.freebsd.org
25 A recent (2014) effort within JUNOS aims at removing our modifications
26 to the underlying FreeBSD code as a means of reducing the expense and
27 delay in tracking HEAD. JUNOS is structured to have system components
28 generate XML that is rendered by the CLI (think: login shell) into
29 human-readable text. This allows the API to use the same plumbing as
30 the CLI, and ensures that all components emit XML, and that it is
31 emitted with knowledge of the consumer of that XML, yielding an API
32 that have no incremental cost or feature delay.
34 libxo is an effort to mix the best aspects of the JUNOS strategy into
35 FreeBSD in a seemless way, allowing commands to make printf-like
36 output calls with a single code path.
38 Did the complex semantics of format strings evolve over time?
39 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
41 The history is both long and short: libxo's functionality is based
42 on what JUNOS does in a data modeling language called ODL (output
43 definition language). In JUNOS, all subcomponents generate XML,
44 which is feed to the CLI, where data from the ODL files tell is
45 how to render that XML into text. ODL might had a set of tags
49 help "State of the DOCSIS interface";
54 help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
58 tag docsis-upstream-speed {
59 help "Operational upstream speed of the interface";
63 tag downstream-scanning {
64 help "Result of scanning in downstream direction";
69 help "Result of ranging action";
73 tag signal-to-noise-ratio {
74 help "Signal to noise ratio for all channels";
79 help "Operational power of the signal on all channels";
83 format docsis-status-format {
85 State : @, Mode: @, Upstream speed: @
86 Downstream scanning: @, Ranging: @
87 Signal to noise ratio: @
93 field docsis-upstream-speed;
94 field downstream-scanning;
96 field signal-to-noise-ratio;
101 These tag definitions are compiled into field definitions
102 that are triggered when matching XML elements are seen. ODL
103 also supports other means of defining output.
105 The roles and modifiers describe these details.
107 In moving these ideas to bsd, two things had to happen: the
108 formatting had to happen at the source since BSD won't have
109 a JUNOS-like CLI to do the rendering, and we can't depend on
110 external data models like ODL, which was seen as too hard a
111 sell to the BSD community.
113 The results were that the xo_emit strings are used to encode the
114 roles, modifiers, names, and formats. They are dense and a bit
115 cryptic, but not so unlike printf format strings that developers will
118 libxo is a new implementation of these ideas and is distinct from
119 the previous implementation in JUNOS.
121 .. index:: XOF_UNDERSCORES
123 .. _good-field-names:
125 What makes a good field name?
126 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
128 To make useful, consistent field names, follow these guidelines:
130 Use 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.
135 Use 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.
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".
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".
154 Reuse existing field names
155 Nothing's worse than writing expressions like::
157 if ($src1/process[pid == $pid]/name ==
158 $src2/proc-table/proc-list
159 /prc-entry[prcss-id == $pid]/proc-name) {
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!
168 Use 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.
172 Think 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.
178 Don'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.
185 Be 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
193 Field names constitute the means by which client programmers interact
194 with our system. By choosing wise names now, you are making their
197 After using `xolint` to find errors in your field descriptors, use
198 "`xolint -V`" to spell check your field names and to help you detect
199 different names for the same data. "dropped-short" and
200 "dropped-too-short" are both reasonable names, but using them both
201 will lead users to ask the difference between the two fields. If
202 there is no difference, use only one of the field names. If there is
203 a difference, change the names to make that difference more obvious.
205 What does this message mean?
206 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
208 .. include:: xolint.rst