Commit | Line | Data |
---|---|---|
76bcac58 PP |
1 | #compdef lttng |
2 | # | |
3 | # Copyright (c) 2015-2023 Philippe Proulx <eeppeliteloop@gmail.com> | |
4 | # | |
5 | # Permission is hereby granted, free of charge, to any person obtaining | |
6 | # a copy of this software and associated documentation files (the | |
7 | # "Software"), to deal in the Software without restriction, including | |
8 | # without limitation the rights to use, copy, modify, merge, publish, | |
9 | # distribute, sublicense, and/or sell copies of the Software, and to | |
10 | # permit persons to whom the Software is furnished to do so, subject to | |
11 | # the following conditions: | |
12 | # | |
13 | # The above copyright notice and this permission notice shall be | |
14 | # included in all copies or substantial portions of the Software. | |
15 | # | |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 | # | |
24 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
25 | # | |
26 | # This is a Zsh completion function for the lttng(1) command (see | |
27 | # <https://lttng.org/>), for versions 2.5 to 2.14. | |
28 | # | |
29 | # If you want, at your own risk, the function to work with versions | |
30 | # above 2.14, set `LTTNG_ZSH_COMP_IGNORE_VERSION_LIMIT=1`. | |
31 | # | |
32 | # Each subcommand changes the command part of the current context so | |
33 | # that you can target a specific subcommand with `zstyle`, for | |
34 | # example: | |
35 | # | |
36 | # $ zstyle ':completion:*:*:lttng-start:*:sessions' verbose yes | |
37 | # $ zstyle ':completion:*:*:lttng-add-context:type-option:*' \ | |
38 | # group-order perf-context-types static-context-types | |
39 | # | |
40 | # The relevant style arguments and tags are: | |
41 | # | |
42 | # `actions` tag (with the `lttng-snapshot` command): | |
43 | # Snapshot action names. | |
44 | # | |
45 | # `channel` argument and `channels` tag: | |
46 | # Channel names. | |
47 | # | |
48 | # The `verbose` style controls whether or not this function adds | |
49 | # completions as a list (with channel information for each item) or | |
50 | # simple channel names. | |
51 | # | |
52 | # If the verbose style is enabled, then the information part of each | |
53 | # item starts with either ` [enabled` or ` [disabled` (note the | |
54 | # two leading spaces), depending on the status of the channel. | |
55 | # | |
56 | # `commands` tag: | |
57 | # lttng(1) subcommand names. | |
58 | # | |
59 | # `log-levels` tag: | |
60 | # Log level names. | |
61 | # | |
62 | # `session` argument and `sessions` tag: | |
63 | # Recording session names. | |
64 | # | |
65 | # The `verbose` style controls whether or not this function adds | |
66 | # completions as a list (with recording session information for each | |
67 | # item) or simple recording session names. | |
68 | # | |
69 | # If the verbose style is enabled, then the information part of each | |
70 | # item starts with either ` [active` or ` [inactive` (note the two | |
71 | # leading spaces), depending on the status of the recording session. | |
72 | # | |
73 | # `type-option` argument: | |
74 | # `static-context-types` tag: | |
75 | # Statically-known context field types. | |
76 | # | |
77 | # `perf-context-types` tag: | |
78 | # perf counter context field types. | |
79 | # | |
80 | # `triggers` tag: | |
81 | # Trigger names. | |
82 | ||
83 | # Sets the `minor_version` variable to the minor version of LTTng-tools, | |
84 | # or to `0` if not found. | |
85 | __lttng_set_minor_version() { | |
86 | minor_version=0 | |
87 | ||
88 | local -a match | |
89 | ||
90 | if [[ $($prog_name --version) =~ '[[:blank:]]+2\.([[:digit:]]+)' ]]; then | |
91 | minor_version=$match[1] | |
92 | fi | |
93 | } | |
94 | ||
95 | # Runs the `lttng` command with `"$@"` using `$tracing_group`. | |
96 | __lttng_run() { | |
97 | $prog_name --no-sessiond --group=$tracing_group "$@" 2>/dev/null | |
98 | } | |
99 | ||
100 | # Runs the `lttng --mi=xml` command using the selected tracing group | |
101 | # (`$tracing_group`) with: | |
102 | # | |
103 | # `$1`: | |
104 | # A message of what's expected to show on error. | |
105 | # | |
106 | # Other arguments: | |
107 | # Passed to the command as is. | |
108 | # | |
109 | # This function returns 1 with LTTng-tools < 2.6 and if `xmllint` isn't | |
110 | # available. | |
111 | __lttng_mi_run() { | |
112 | local -r msg=$1 | |
113 | ||
114 | shift | |
115 | ||
116 | if ((minor_version < 6)); then | |
117 | # MI output requires LTTng-tools ≥ 2.6 | |
118 | _message -e descriptions $msg | |
119 | return 1 | |
120 | fi | |
121 | ||
122 | if ((! $+commands[xmllint])); then | |
123 | # XML output parsing requires xmllint | |
124 | _message -e descriptions $msg | |
125 | return 1 | |
126 | fi | |
127 | ||
128 | __lttng_run --mi=xml "$@" | |
129 | ||
130 | if (($? != 0)); then | |
131 | # Command failed | |
132 | _message -e descriptions $msg | |
133 | return 1 | |
134 | fi | |
135 | } | |
136 | ||
137 | # Call this instead of _arguments() within this function when you don't | |
138 | # need the `-C` option. | |
139 | __lttng_arguments() { | |
140 | _arguments -s -W : "$@" | |
141 | } | |
142 | ||
143 | # Returns whether or not the verbose style is enabled for the given | |
144 | # argument (`$1`) and tag (`$2`), using `$curcontext` for the other | |
145 | # parts of the full completion context. | |
146 | __lttng_style_is_verbose() { | |
147 | local -r arg=$1 tag=$2 | |
148 | local -r ccparts=("${(@s.:.)curcontext}") | |
149 | ||
150 | zstyle -t :completion:${ccparts[1]}:${ccparts[2]}:${ccparts[3]}:$arg:$tag verbose | |
151 | } | |
152 | ||
153 | # Returns 0 if a Linux kernel tracing domain option is set in | |
154 | # `$opt_args`, or `1` otherwise. | |
155 | __lttng_kernel_domain_opt_is_set() { | |
156 | (($+opt_args[-k] || $+opt_args[--kernel] || | |
157 | $+opt_args[domain--k] || $+opt_args[domain---kernel])) | |
158 | } | |
159 | ||
160 | # Returns 0 if a user space tracing domain option is set in | |
161 | # `$opt_args`, or `1` otherwise. | |
162 | __lttng_user_domain_opt_is_set() { | |
163 | (($+opt_args[-u] || $+opt_args[--userspace] || | |
164 | $+opt_args[domain--u] || $+opt_args[domain---userspace])) | |
165 | } | |
166 | ||
167 | # Returns 0 if a `java.util.logging` tracing domain option is set in | |
168 | # `$opt_args`, or `1` otherwise. | |
169 | __lttng_jul_domain_opt_is_set() { | |
170 | (($+opt_args[-j] || $+opt_args[--jul] || | |
171 | $+opt_args[domain--j] || $+opt_args[domain---jul])) | |
172 | } | |
173 | ||
174 | # Returns 0 if an Apache log4j tracing domain option is set in | |
175 | # `$opt_args`, or `1` otherwise. | |
176 | __lttng_log4j_domain_opt_is_set() { | |
177 | (($+opt_args[-l] || $+opt_args[--log4j] || | |
178 | $+opt_args[domain--l] || $+opt_args[domain---log4j])) | |
179 | } | |
180 | ||
181 | # Returns 0 if a Python tracing domain option is set in `$opt_args`, | |
182 | # or `1` otherwise. | |
183 | __lttng_python_domain_opt_is_set() { | |
184 | (($+opt_args[-p] || $+opt_args[--python] || | |
185 | $+opt_args[domain--p] || $+opt_args[domain---python])) | |
186 | } | |
187 | ||
188 | # Adds completions for the name of an `lttng` command. | |
189 | __lttng_complete_cmd_name() { | |
190 | # LTTng-tools 2.5+ | |
191 | local cmd_names=( | |
192 | 'add-context:add context fields to be recorded' | |
193 | 'create:create a recording session' | |
194 | 'destroy:destroy a recording session' | |
195 | 'disable-channel:disable channels' | |
196 | 'disable-event:disable recording event rules' | |
197 | 'enable-channel:create or enable a channel' | |
198 | 'enable-event:create or enable recording event rules' | |
199 | 'help:show the help of a command' | |
200 | 'list:list recording sessions and instrumentation points' | |
201 | 'set-session:set the current recording session' | |
202 | 'snapshot:take a recording session snapshot' | |
203 | 'start:start a recording session' | |
204 | 'stop:stop a recording session' | |
205 | 'version:show LTTng-tools version information' | |
206 | 'view:launch a trace reader' | |
207 | ) | |
208 | ||
209 | # LTTng-tools 2.6+ | |
210 | if ((minor_version >= 6)); then | |
211 | cmd_names+=( | |
212 | 'load:load recording session configurations' | |
213 | 'save:save recording session configurations' | |
214 | ) | |
215 | fi | |
216 | ||
217 | # LTTng-tools 2.7+ | |
218 | if ((minor_version >= 7)); then | |
219 | cmd_names+=( | |
220 | 'track:allow specific processes to record events' | |
221 | 'untrack:disallow specific processes to record events' | |
222 | ) | |
223 | fi | |
224 | ||
225 | # LTTng-tools 2.8+ | |
226 | if ((minor_version >= 8)); then | |
227 | cmd_names+=( | |
228 | 'status:show the status of the current recording session' | |
229 | ) | |
230 | fi | |
231 | ||
232 | # LTTng-tools 2.9+ | |
233 | if ((minor_version >= 9)); then | |
234 | cmd_names+=( | |
235 | 'regenerate:regenerate specific recording session data' | |
236 | ) | |
237 | fi | |
238 | ||
239 | # LTTng-tools 2.11+ | |
240 | if ((minor_version >= 11)); then | |
241 | cmd_names+=( | |
242 | 'rotate:archive the current trace chunk of a recording session' | |
243 | 'enable-rotation:set a recording session rotation schedule' | |
244 | 'disable-rotation:unset a recording session rotation schedule' | |
245 | ) | |
246 | fi | |
247 | ||
248 | # LTTng-tools 2.12+ | |
249 | if ((minor_version >= 12)); then | |
250 | cmd_names+=( | |
251 | 'clear:clear a recording session' | |
252 | ) | |
253 | fi | |
254 | ||
255 | # LTTng-tools 2.13+ | |
256 | if ((minor_version >= 13)); then | |
257 | cmd_names+=( | |
258 | 'add-trigger:add a trigger' | |
259 | 'list-triggers:list triggers' | |
260 | 'remove-trigger:remove a trigger' | |
261 | ) | |
262 | fi | |
263 | ||
264 | # Add completions | |
265 | local expl | |
266 | ||
267 | _describe -t commands command cmd_names | |
268 | } | |
269 | ||
270 | # Adds completions for the name of an `lttng snapshot` action. | |
271 | __lttng_complete_snapshot_action_name() { | |
272 | local -r action_names=( | |
273 | 'add-output:add a snapshot output' | |
274 | 'del-output:remove a snapshot output' | |
275 | 'list-output:show the snapshot output' | |
276 | 'record:take a snapshot' | |
277 | ) | |
278 | ||
279 | # Add completions | |
280 | local expl | |
281 | ||
282 | _describe -t actions 'snapshot action' action_names | |
283 | } | |
284 | ||
285 | # Adds user ID completions. | |
286 | # | |
287 | # The added completions are displayed as user names, but the actual | |
288 | # completions are corresponding user IDs. | |
289 | __lttng_complete_uid() { | |
290 | if [[ ! -f /etc/passwd ]]; then | |
291 | # Weird flex but ok | |
292 | _message -e descriptions 'user ID' | |
293 | return | |
294 | fi | |
295 | ||
296 | # Read user names and IDs from `/etc/passwd` | |
297 | local line | |
298 | local -a uids names fields | |
299 | ||
300 | while read -r line; do | |
301 | if [[ -z ${line// } ]]; then | |
302 | # Skip empty line | |
303 | continue | |
304 | fi | |
305 | ||
306 | # Extract user ID and name | |
307 | fields=("${(@s/:/)line}") | |
308 | uids+=($fields[3]) | |
309 | names+=("$fields[1]") | |
310 | done < /etc/passwd | |
311 | ||
312 | # Add completions | |
313 | local expl | |
314 | ||
315 | _wanted users expl 'user ID' compadd -d names -a uids | |
316 | } | |
317 | ||
318 | # Adds completions for a context field type (for the `--type` option of | |
319 | # the `add-context` command). | |
320 | # | |
321 | # This function replaces the argument field of the current context with | |
322 | # `type-option`. | |
323 | # | |
324 | # This function relies on the tracing domain options of `$opt_args` to | |
325 | # restrict the offered completions. Without a tracing domain option, | |
326 | # this function adds all the possible context field type completions. | |
327 | # | |
328 | # This function runs `lttng add-context --list` to get the list of | |
329 | # available context field types. | |
330 | # | |
331 | # This function adds completions with both the `static-context-types` | |
332 | # and `perf-context-types` tags so that the Zsh user can hide a group or | |
333 | # select them with the `group-order` and `tag-order` style. | |
334 | __lttng_complete_context_type() { | |
335 | # Statically-known context field types | |
336 | local kernel_types=( | |
337 | pid procname prio nice vpid tid vtid ppid vppid hostname | |
338 | interruptible preemptible need_reschedule migratable | |
339 | callstack-kernel callstack-user cgroup_ns ipc_ns mnt_ns net_ns | |
340 | pid_ns time_ns user_ns uts_ns uid euid suid gid egid sgid vuid veuid | |
341 | vsuid vgid vegid vsgid | |
342 | ) | |
343 | local user_types=( | |
344 | vpid pthread_id procname ip cgroup_ns ipc_ns mnt_ns net_ns pid_ns | |
345 | time_ns user_ns uts_ns vuid veuid vsuid vgid vegid vsgid | |
346 | ) | |
347 | ||
348 | # Set `types` and `domain` depending on the selected tracing domain | |
349 | local -a types | |
350 | local domain descr_suffix | |
351 | ||
352 | if __lttng_kernel_domain_opt_is_set; then | |
353 | # Kernel context field types | |
354 | types=($kernel_types) | |
355 | domain=k | |
356 | elif __lttng_user_domain_opt_is_set; then | |
357 | # User space context field types | |
358 | types=($user_types) | |
359 | domain=u | |
360 | else | |
361 | # No supported tracing domain: offer all context field types | |
362 | types=($user_types $kernel_types) | |
363 | descr_suffix=' (all tracing domains)' | |
364 | fi | |
365 | ||
366 | # Get XML list of available context field types | |
367 | local -r msg='context type' | |
368 | local list_xml | |
369 | ||
370 | list_xml=$(__lttng_mi_run $msg add-context --list) | |
371 | ||
372 | if (($? != 0)); then | |
373 | return 1 | |
374 | fi | |
375 | ||
376 | # Convert to one context field type per line | |
377 | local lines | |
378 | ||
379 | lines=$(__lttng_xmllint_xpath $list_xml '//*[local-name()="symbol"]/text()') | |
380 | ||
381 | if (($? != 0)); then | |
382 | _guard '^-*' $msg | |
383 | return | |
384 | fi | |
385 | ||
386 | # Filter context field types depending on the selected tracing domain | |
387 | local -a static_items perf_items | |
388 | local line | |
389 | ||
390 | while read -r line; do | |
391 | if (($types[(Ie)$line])); then | |
392 | # Statically-known context field type | |
393 | static_items+=$line | |
394 | elif [[ $line = perf:cpu:* && $domain != u ]]; then | |
395 | # Per-CPU perf counter | |
396 | perf_items+=$line | |
397 | elif [[ $line = perf:thread:* && $domain != k ]]; then | |
398 | # Per-thread perf counter | |
399 | perf_items+=$line | |
400 | elif [[ $line = perf:* && $domain != u ]]; then | |
401 | # Other perf counter (Linux kernel tracing domain or none) | |
402 | perf_items+=$line | |
403 | fi | |
404 | done <<< $lines | |
405 | ||
406 | # Add completions | |
407 | _alternative -C type-option \ | |
408 | "static-context-types:statically-known context type${descr_suffix}:compadd -a static_items" \ | |
409 | "perf-context-types:perf counter context type${descr_suffix}:compadd -a perf_items" | |
410 | } | |
411 | ||
412 | # Adds completions for a trigger name. | |
413 | # | |
414 | # Relies on `$opt_args[--owner-uid]` to restrict the offered | |
415 | # completions. | |
416 | __lttng_complete_trigger_name() { | |
417 | # Get XML list of available triggers | |
418 | local msg='trigger name' | |
419 | local list_xml | |
420 | ||
421 | list_xml=$(__lttng_mi_run $msg list-triggers) | |
422 | ||
423 | if (($? != 0)); then | |
424 | return 1 | |
425 | fi | |
426 | ||
427 | # Create the owner UID predicate XPath part | |
428 | local owner_uid_xpath | |
429 | ||
430 | if (($+opt_args[--owner-uid])); then | |
431 | owner_uid_xpath="[./*[local-name()='owner_uid'] = ${opt_args[--owner-uid]}]" | |
432 | fi | |
433 | ||
434 | # Convert to one trigger name per line | |
435 | local lines | |
436 | ||
437 | lines=$(__lttng_xmllint_xpath $list_xml "//*[local-name()='trigger']$owner_uid_xpath/*[local-name()='name']/text()") | |
438 | ||
439 | if (($? != 0)); then | |
440 | _guard '^-*' $msg | |
441 | return | |
442 | fi | |
443 | ||
444 | local -a trigger_names | |
445 | ||
446 | while read -r line; do | |
447 | trigger_names+=$line | |
448 | done <<< $lines | |
449 | ||
450 | # Add completions | |
451 | local expl | |
452 | ||
453 | _wanted triggers expl $msg compadd -a trigger_names | |
454 | } | |
455 | ||
456 | # Runs `xmllint` with: | |
457 | # | |
458 | # `$1`: | |
459 | # An XML document to parse. | |
460 | # | |
461 | # `$2`: | |
462 | # An XPath to extract data. | |
463 | __lttng_xmllint_xpath() { | |
464 | local -r xml=$1 xpath=$2 | |
465 | ||
466 | xmllint --xpath $xpath - <<< $xml 2>/dev/null | |
467 | } | |
468 | ||
469 | # Prints the equivalent recording session status adjective (`active` or | |
470 | # `inactive`) for an `enabled` XML property, or `unknown` on error. | |
471 | __lttng_session_status_from_enabled_prop() { | |
472 | local -r prop=$1 | |
473 | ||
474 | case $prop in | |
475 | true) echo -n active;; | |
476 | false) echo -n inactive;; | |
477 | *) echo -n unknown;; | |
478 | esac | |
479 | } | |
480 | ||
481 | # Prints the value of the immediate XML property named `$3` of the child | |
482 | # node named `$2` within the parent node `$1`. | |
483 | __lttng_immediate_prop_from_xml() { | |
484 | local -r node_xml=$1 node_name=$2 prop_name=$3 | |
485 | ||
486 | __lttng_xmllint_xpath $node_xml "/*[local-name()='$node_name']/*[local-name()='$prop_name']/text()" | |
487 | } | |
488 | ||
489 | # Prints the value of the immediate XML `name` property of the child | |
490 | # node named `$2` within the parent node `$1`. | |
491 | __lttng_name_prop_from_xml() { | |
492 | local -r node_xml=$1 node_name=$2 | |
493 | ||
494 | __lttng_immediate_prop_from_xml $node_xml $node_name name | |
495 | } | |
496 | ||
497 | # Prints the value of the immediate XML `enabled` property of the child | |
498 | # node named `$2` within the parent node `$1`. | |
499 | __lttng_enabled_prop_from_xml() { | |
500 | local -r node_xml=$1 node_name=$2 | |
501 | ||
502 | __lttng_immediate_prop_from_xml $node_xml $node_name enabled | |
503 | } | |
504 | ||
505 | # Adds completions for a recording session name. | |
506 | # | |
507 | # Arguments: | |
508 | # | |
509 | # `$1`: | |
510 | # One of: | |
511 | # | |
512 | # `all`: | |
513 | # Add completions for active and inactive recording sessions. | |
514 | # | |
515 | # `active`: | |
516 | # Only add completions for active recording sessions. | |
517 | # | |
518 | # `inactive`: | |
519 | # Only add completions for inactive recording sessions. | |
520 | # | |
521 | # `$2`: | |
522 | # One of: | |
523 | # | |
524 | # `all`: | |
525 | # Add completions for recording sessions regardless of their | |
526 | # mode. | |
527 | # | |
528 | # `snapshot`: | |
529 | # Only add completions for snapshot recording sessions. | |
530 | # | |
531 | # `live`: | |
532 | # Only add completions for LTTng live recording sessions. | |
533 | __lttng_complete_session_name() { | |
534 | local -r req_status=$1 req_mode=$2 | |
535 | ||
536 | # Get XML document (summary of recording sessions) | |
537 | local session_summaries_xml | |
538 | ||
539 | session_summaries_xml=$(__lttng_mi_run 'recording session name' list) | |
540 | ||
541 | if (($? != 0)); then | |
542 | return 1 | |
543 | fi | |
544 | ||
545 | # Count recording sessions | |
546 | local -i session_count | |
547 | ||
548 | session_count=$(__lttng_xmllint_xpath $session_summaries_xml 'count(//*[local-name()="session"])') | |
549 | ||
550 | if (($? != 0 || session_count == 0)); then | |
551 | _guard '^-*' 'recording session name' | |
552 | return | |
553 | fi | |
554 | ||
555 | # Append the name and info of one recording session at a time | |
556 | local -a session_names session_infos | |
557 | local -i index iprop | |
558 | local session_name session_summary_xml snapshot_mode session_status session_info | |
559 | ||
560 | # For each recording session summary | |
561 | for index in {1..$session_count}; do | |
562 | # Get recording session summary XML node | |
563 | session_summary_xml=$(__lttng_xmllint_xpath $session_summaries_xml "//*[local-name()='session'][$index]") | |
564 | ||
565 | if (($? != 0)); then | |
566 | continue | |
567 | fi | |
568 | ||
569 | # Get recording session name | |
570 | session_name=$(__lttng_name_prop_from_xml $session_summary_xml session) | |
571 | ||
572 | if (($? != 0)); then | |
573 | continue | |
574 | fi | |
575 | ||
576 | # Get recording session status | |
577 | session_status=$(__lttng_enabled_prop_from_xml $session_summary_xml session) | |
578 | ||
579 | if (($? != 0)); then | |
580 | continue | |
581 | fi | |
582 | ||
583 | session_status=$(__lttng_session_status_from_enabled_prop $session_status) | |
584 | ||
585 | if [[ $req_status != all && $req_status != $session_status ]]; then | |
586 | # Skip recording session with unexpected status | |
587 | continue | |
588 | fi | |
589 | ||
590 | # Get recording session mode | |
591 | session_mode= | |
592 | iprop=$(__lttng_immediate_prop_from_xml $session_summary_xml session snapshot_mode) | |
593 | ||
594 | if (($? == 0 && iprop)); then | |
595 | session_mode=snapshot | |
596 | else | |
597 | iprop=$(__lttng_immediate_prop_from_xml $session_summary_xml session live_timer_interval) | |
598 | ||
599 | if (($? == 0 && iprop)); then | |
600 | session_mode=live | |
601 | fi | |
602 | fi | |
603 | ||
604 | if [[ $req_mode != all && $req_mode != $session_mode ]]; then | |
605 | # Skip recording session with unexpected mode | |
606 | continue | |
607 | fi | |
608 | ||
609 | session_info=$session_status | |
610 | ||
611 | if [[ -n $session_mode ]]; then | |
612 | session_info+=", $session_mode mode" | |
613 | fi | |
614 | ||
615 | session_names+=("$session_name") | |
616 | session_infos+=($session_info) | |
617 | done | |
618 | ||
619 | # No recording sessions: show message | |
620 | if (($#session_names == 0)); then | |
621 | _guard '^-*' 'recording session name' | |
622 | return | |
623 | fi | |
624 | ||
625 | # Compute maximum session info length | |
626 | local -i max_info_len=0 len | |
627 | ||
628 | for session_info in $session_infos; do | |
629 | len=$#session_info | |
630 | ||
631 | if ((len > max_info_len)); then | |
632 | max_info_len=$len | |
633 | fi | |
634 | done | |
635 | ||
636 | # Compute maximum session name length | |
637 | local -i max_name_len=0 | |
638 | ||
639 | for session_name in $session_names; do | |
640 | len=$#session_name | |
641 | ||
642 | if ((len > max_name_len)); then | |
643 | max_name_len=$len | |
644 | fi | |
645 | done | |
646 | ||
647 | # Some room for the longest info string, two spaces, and two brackets | |
648 | local -ir max_possible_name_len=$((COLUMNS - max_info_len - 5)) | |
649 | ||
650 | if ((max_name_len > max_possible_name_len)); then | |
651 | # Clamp | |
652 | max_name_len=$max_possible_name_len | |
653 | fi | |
654 | ||
655 | # Create the dislay strings (name, status, mode) | |
656 | local -a disps | |
657 | ||
658 | for index in {1..${#session_names}}; do | |
659 | disps+=("${(r:$max_name_len:: :)session_names[$index]} [$session_infos[$index]]") | |
660 | done | |
661 | ||
662 | # Add completions | |
663 | local expl | |
664 | ||
665 | if __lttng_style_is_verbose session sessions; then | |
666 | # Verbose mode (list with infos) | |
667 | _wanted -C session sessions expl 'recording session name' \ | |
668 | compadd -d disps -l -a session_names | |
669 | else | |
670 | # Just the recording session names | |
671 | _wanted -C session sessions expl 'recording session name' \ | |
672 | compadd -a session_names | |
673 | fi | |
674 | } | |
675 | ||
676 | # Prints the name of the Unix user's current recording session, if any. | |
677 | __lttng_cur_session_name() { | |
678 | local -r lttngrc_path=${LTTNG_HOME:-$HOME}/.lttngrc | |
679 | ||
680 | if [[ ! -f $lttngrc_path ]]; then | |
681 | return 1 | |
682 | fi | |
683 | ||
684 | local cur_session_name | |
685 | local -a match | |
686 | ||
687 | while read -r line; do | |
688 | if [[ $line =~ 'session=([^[:blank:]]+)' ]]; then | |
689 | cur_session_name=$match[1] | |
690 | break | |
691 | fi | |
692 | done < $lttngrc_path | |
693 | ||
694 | if [[ -z $cur_session_name ]]; then | |
695 | return 1 | |
696 | fi | |
697 | ||
698 | echo -n $cur_session_name | |
699 | } | |
700 | ||
701 | # Prints the equivalent status adjective (`enabled` or `disabled`) for | |
702 | # an `enabled` XML property, or `unknown` on error. | |
703 | __lttng_status_from_enabled_prop() { | |
704 | local -r prop=$1 | |
705 | ||
706 | case $prop in | |
707 | true) echo -n enabled;; | |
708 | false) echo -n disabled;; | |
709 | *) echo -n unknown;; | |
710 | esac | |
711 | } | |
712 | ||
713 | # Prints the XML document of `lttng list $2` (specifics of a single | |
714 | # recording session). | |
715 | # | |
716 | # `$1` is a message of what's expected to show on error. | |
717 | __lttng_session_xml() { | |
718 | local -r msg=$1 session_name=$2 | |
719 | ||
720 | __lttng_mi_run $msg list $session_name | |
721 | } | |
722 | ||
723 | # Adds completions for a channel name. | |
724 | # | |
725 | # This function relies on the tracing domain options of `$opt_args`, | |
726 | # `$opt_args[-s]`, `$opt_args[--session]`, and the first non-option | |
727 | # argument to restrict the offered completions. | |
728 | # | |
729 | # Arguments: | |
730 | # | |
731 | # `$1`: | |
732 | # One of: | |
733 | # | |
734 | # `all`: | |
735 | # Add completions for enabled and disabled channels. | |
736 | # | |
737 | # `enabled`: | |
738 | # Only add completions for enabled channels. | |
739 | # | |
740 | # `disabled`: | |
741 | # Only add completions for disabled channels. | |
742 | # | |
743 | # `$2`: | |
744 | # `opt`: | |
745 | # Use `$opt_args[-s]` and `$opt_args[--session]` to find the | |
746 | # name of the selected recording session. | |
747 | # | |
748 | # `arg`: | |
749 | # Use `$line[1]` to find the name of the selected recording | |
750 | # session. | |
751 | __lttng_complete_channel_name() { | |
752 | local -r req_status=$1 session_name_src=$2 | |
753 | ||
754 | shift 2 | |
755 | ||
756 | # Find the recording session name to use | |
757 | local session_name | |
758 | ||
759 | if [[ $session_name_src = opt ]]; then | |
760 | if (($+opt_args[-s])); then | |
761 | session_name=$opt_args[-s] | |
762 | elif (($+opt_args[--session])); then | |
763 | session_name=$opt_args[--session] | |
764 | fi | |
765 | elif [[ $session_name_src = arg ]]; then | |
766 | session_name=$line[1] | |
767 | fi | |
768 | ||
769 | if [[ -z $session_name ]]; then | |
770 | # Fall back to current recording session | |
771 | session_name=$(__lttng_cur_session_name) | |
772 | ||
773 | if (($? != 0)); then | |
774 | _guard '^-*' 'channel name' | |
775 | return | |
776 | fi | |
777 | fi | |
778 | ||
779 | # Get XML document (detailed recording session) | |
780 | local session_xml | |
781 | ||
782 | session_xml=$(__lttng_session_xml 'channel name' $session_name) | |
783 | ||
784 | if (($? != 0)); then | |
785 | return 1 | |
786 | fi | |
787 | ||
788 | # Count tracing domains | |
789 | local -i domain_count | |
790 | ||
791 | domain_count=$(__lttng_xmllint_xpath $session_xml 'count(//*[local-name()="domain"])') | |
792 | ||
793 | if (($? != 0 || domain_count == 0)); then | |
794 | _guard '^-*' 'channel name' | |
795 | return | |
796 | fi | |
797 | ||
798 | # Append the name and info of one channel at a time | |
799 | local domain_xml domain prop | |
800 | local channel_xml channel_name channel_status channel_erl_mode | |
801 | local -a channel_names channel_infos | |
802 | local -i channel_count domain_index channel_index | |
803 | ||
804 | # For each tracing domain | |
805 | for domain_index in {1..$domain_count}; do | |
806 | # Get tracing domain XML node | |
807 | domain_xml=$(__lttng_xmllint_xpath $session_xml "//*[local-name()='domain'][$domain_index]") | |
808 | ||
809 | if (($? != 0)); then | |
810 | continue | |
811 | fi | |
812 | ||
813 | # Get tracing domain type | |
814 | domain=$(__lttng_xmllint_xpath $domain_xml '/*/*[local-name()="type"]/text()') | |
815 | ||
816 | if (($? != 0)); then | |
817 | continue | |
818 | fi | |
819 | ||
820 | # Skip unexpected tracing domains | |
821 | if [[ $domain = KERNEL ]]; then | |
822 | if __lttng_user_domain_opt_is_set; then | |
823 | # Skip unexpected Linux kernel tracing domain | |
824 | continue | |
825 | fi | |
826 | ||
827 | domain='Linux kernel' | |
828 | fi | |
829 | ||
830 | if [[ $domain = UST ]]; then | |
831 | if __lttng_kernel_domain_opt_is_set; then | |
832 | # Skip unexpected user space tracing domain | |
833 | continue | |
834 | fi | |
835 | ||
836 | domain='user space' | |
837 | fi | |
838 | ||
839 | # Count channels within tracing domain | |
840 | channel_count=$(__lttng_xmllint_xpath $domain_xml 'count(//*[local-name()="channel"])') | |
841 | ||
842 | if (($? != 0 || channel_count == 0)); then | |
843 | continue | |
844 | fi | |
845 | ||
846 | # For each channel | |
847 | for channel_index in {1..$channel_count}; do | |
848 | # Get channel XML node | |
849 | channel_xml=$(__lttng_xmllint_xpath $domain_xml "//*[local-name()='channel'][$channel_index]") | |
850 | ||
851 | if (($? != 0)); then | |
852 | continue | |
853 | fi | |
854 | ||
855 | # Get channel name | |
856 | channel_name=$(__lttng_name_prop_from_xml $channel_xml channel) | |
857 | ||
858 | if (($? != 0)); then | |
859 | continue | |
860 | fi | |
861 | ||
862 | # Get channel status | |
863 | channel_status=$(__lttng_enabled_prop_from_xml $channel_xml channel) | |
864 | ||
865 | if (($? != 0)); then | |
866 | continue | |
867 | fi | |
868 | ||
869 | channel_status=$(__lttng_status_from_enabled_prop $channel_status) | |
870 | ||
871 | if [[ $req_status != all && $req_status != $channel_status ]]; then | |
872 | # Skip channel with unexpected status | |
873 | continue | |
874 | fi | |
875 | ||
876 | # Get channel event record loss mode | |
877 | channel_erl_mode=$(__lttng_xmllint_xpath $channel_xml '//*[local-name()="attributes"]/*[local-name()="overwrite_mode"]/text()') | |
878 | ||
879 | if (($? != 0)); then | |
880 | continue | |
881 | fi | |
882 | ||
883 | if [[ $channel_erl_mode = DISCARD ]]; then | |
884 | channel_erl_mode=discard | |
885 | elif [[ $channel_erl_mode = OVERWRITE ]]; then | |
886 | channel_erl_mode=overwrite | |
887 | fi | |
888 | ||
889 | channel_names+=("$channel_name") | |
890 | channel_infos+=("$channel_status, $domain, $channel_erl_mode mode") | |
891 | done | |
892 | done | |
893 | ||
894 | # No channels: show message | |
895 | if (($#channel_names == 0)); then | |
896 | _guard '^-*' 'channel name' | |
897 | return | |
898 | fi | |
899 | ||
900 | # Compute maximum channel info length | |
901 | local channel_info | |
902 | local -i max_info_len=0 len | |
903 | ||
904 | for channel_info in $channel_infos; do | |
905 | len=$#channel_info | |
906 | ||
907 | if ((len > max_info_len)); then | |
908 | max_info_len=$len | |
909 | fi | |
910 | done | |
911 | ||
912 | # Compute maximum channel name length | |
913 | local -i max_name_len=0 | |
914 | ||
915 | for channel_name in $channel_names; do | |
916 | len=$#channel_name | |
917 | ||
918 | if ((len > max_name_len)); then | |
919 | max_name_len=$len | |
920 | fi | |
921 | done | |
922 | ||
923 | # Some room for the longest info string, two spaces, and two brackets | |
924 | local -ir max_possible_name_len=$((COLUMNS - max_info_len - 5)) | |
925 | ||
926 | if ((max_name_len > max_possible_name_len)); then | |
927 | # Clamp | |
928 | max_name_len=$max_possible_name_len | |
929 | fi | |
930 | ||
931 | # Create the dislay strings (name, status, tracing domain, mode) | |
932 | local -a disps | |
933 | ||
934 | for channel_index in {1..${#channel_names}}; do | |
935 | disps+=("${(r:$max_name_len:: :)channel_names[$channel_index]} [$channel_infos[$channel_index]]") | |
936 | done | |
937 | ||
938 | # Add completions | |
939 | local expl | |
940 | ||
941 | if __lttng_style_is_verbose channel channels; then | |
942 | # Verbose mode (list with infos). | |
943 | # | |
944 | # Using `-2` as Linux kernel and user space channels may have the | |
945 | # same name, but we want to show the different infos. | |
946 | _wanted -C channel channels expl 'channel name' \ | |
947 | compadd "$@" -2 -d disps -l -a channel_names | |
948 | else | |
949 | # Just the channel names, no duplicates | |
950 | _wanted -C channel channels expl 'channel name' \ | |
951 | compadd "$@" -a channel_names | |
952 | fi | |
953 | } | |
954 | ||
955 | # Add completions for instrumentation point names. | |
956 | # | |
957 | # This function relies on the tracing domain options of `$opt_args` and | |
958 | # `$opt_args[ip---syscall]` to restrict the offered completions. | |
959 | __lttng_complete_ip_name() { | |
960 | local msg | |
961 | local -a list_opts | |
962 | ||
963 | if __lttng_kernel_domain_opt_is_set; then | |
964 | list_opts=(-k) | |
965 | ||
966 | if (($+opt_args[ip---syscall])); then | |
967 | msg='system call name (no `sys_` prefix)' | |
968 | list_opts+=(--syscall) | |
969 | else | |
970 | msg='Linux kernel tracepoint name' | |
971 | fi | |
972 | elif __lttng_user_domain_opt_is_set; then | |
973 | msg='user space tracepoint name' | |
974 | list_opts=(-u) | |
975 | elif __lttng_jul_domain_opt_is_set; then | |
976 | msg='`java.util.logging` logger name' | |
977 | list_opts=(-j) | |
978 | elif __lttng_log4j_domain_opt_is_set; then | |
979 | msg='Apache log4j logger name' | |
980 | list_opts=(-l) | |
981 | elif __lttng_python_domain_opt_is_set; then | |
982 | msg='Python logger name' | |
983 | list_opts=(-p) | |
984 | else | |
985 | # No tracing domain option | |
986 | _guard '^-*' 'instrumentation point or recording event rule name' | |
987 | return | |
988 | fi | |
989 | ||
990 | # Get XML list of available instrumentation point names | |
991 | local list_xml | |
992 | ||
993 | list_xml=$(__lttng_mi_run $msg list $list_opts) | |
994 | ||
995 | if (($? != 0)); then | |
996 | return 1 | |
997 | fi | |
998 | ||
999 | # Convert to one instrumentation point name per line | |
1000 | local ip_names | |
1001 | ||
1002 | ip_names=$(__lttng_xmllint_xpath $list_xml '//*[local-name()="event"]//*[local-name()="name"]/text()') | |
1003 | ||
1004 | if (($? != 0)) || [[ -z $ip_names ]]; then | |
1005 | # `xmllint` error or no instrumentation points | |
1006 | _guard '^-*' $msg | |
1007 | return | |
1008 | fi | |
1009 | ||
1010 | local ip_name | |
1011 | local -a items | |
1012 | ||
1013 | while read -r ip_name; do | |
1014 | if [[ -z $ip_name ]]; then | |
1015 | continue | |
1016 | fi | |
1017 | ||
1018 | items+=($ip_name) | |
1019 | done <<< $ip_names | |
1020 | ||
1021 | # Add completions | |
1022 | local expl | |
1023 | ||
1024 | _wanted instrumentation-points expl $msg compadd "$@" -a items | |
1025 | } | |
1026 | ||
1027 | # Adds completions for the arguments of the `add-context` command. | |
1028 | __lttng_complete_add_context_cmd() { | |
1029 | local specs=( | |
1030 | $help_opt_specs | |
1031 | '(- : *)--list[list the available context field types]' | |
1032 | '(--list -s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name inactive all' | |
1033 | '(--list -c --channel)'{-c+,--channel=}'[select a specific channel]: : __lttng_complete_channel_name enabled opt' | |
1034 | '(--list)*'{-t+,--type=}'[add a context field to be recorded]: : __lttng_complete_context_type' | |
1035 | + '(domain)' | |
1036 | '(--list)'{-k,--kernel}'[select the Linux kernel tracing domain]' | |
1037 | '(--list)'{-u,--userspace}'[select the user space tracing domain]' | |
1038 | ) | |
1039 | ||
1040 | # The Java tracing domain options require LTTng-tools ≥ 2.8 (for | |
1041 | # application-specific context field types). | |
1042 | if ((minor_version >= 8)); then | |
1043 | specs+=( | |
1044 | '(--list)'{-j,--jul}'[select the `java.util.logging` tracing domain]' | |
1045 | '(--list)'{-l,--log4j}'[select the Apache log4j tracing domain]' | |
1046 | ) | |
1047 | fi | |
1048 | ||
1049 | # Add completions | |
1050 | __lttng_arguments $specs | |
1051 | } | |
1052 | ||
1053 | # Adds completions for log level names. | |
1054 | # | |
1055 | # This function relies on the tracing domain options of `$opt_args` to | |
1056 | # restrict the offered completions. | |
1057 | __lttng_complete_log_level() { | |
1058 | local -a log_levels | |
1059 | ||
1060 | # Fill the `log_levels` array depending on the tracing domain option | |
1061 | if __lttng_user_domain_opt_is_set; then | |
1062 | log_levels=( | |
1063 | EMERG | |
1064 | ALERT | |
1065 | CRIT | |
1066 | ERR | |
1067 | WARNING | |
1068 | NOTICE | |
1069 | INFO | |
1070 | DEBUG_SYSTEM | |
1071 | DEBUG_PROGRAM | |
1072 | DEBUG_PROCESS | |
1073 | DEBUG_MODULE | |
1074 | DEBUG_UNIT | |
1075 | DEBUG_FUNCTION | |
1076 | DEBUG_LINE | |
1077 | DEBUG | |
1078 | ) | |
1079 | elif __lttng_jul_domain_opt_is_set; then | |
1080 | log_levels=( | |
1081 | OFF | |
1082 | SEVERE | |
1083 | WARNING | |
1084 | INFO | |
1085 | CONFIG | |
1086 | FINE | |
1087 | FINER | |
1088 | FINEST | |
1089 | ALL | |
1090 | ) | |
1091 | elif __lttng_log4j_domain_opt_is_set; then | |
1092 | log_levels=( | |
1093 | OFF | |
1094 | FATAL | |
1095 | ERROR | |
1096 | WARN | |
1097 | INFO | |
1098 | DEBUG | |
1099 | TRACE | |
1100 | ALL | |
1101 | ) | |
1102 | elif __lttng_python_domain_opt_is_set; then | |
1103 | log_levels=( | |
1104 | CRITICAL | |
1105 | ERROR | |
1106 | WARNING | |
1107 | INFO | |
1108 | DEBUG | |
1109 | NOTSET | |
1110 | ) | |
1111 | else | |
1112 | # No tracing domain option | |
1113 | _guard '^-*' 'log level name' | |
1114 | fi | |
1115 | ||
1116 | # Add completions | |
1117 | local expl | |
1118 | ||
1119 | _wanted log-levels expl 'log level name' compadd -a log_levels | |
1120 | } | |
1121 | ||
1122 | # Adds completions for a trigger condition type. | |
1123 | __lttng_complete_trigger_condition_type() { | |
1124 | local -r types=( | |
1125 | 'event-rule-matches:an event rule matches an event' | |
1126 | ) | |
1127 | ||
1128 | # Add completions | |
1129 | local expl | |
1130 | ||
1131 | _describe 'trigger condition type' types | |
1132 | } | |
1133 | ||
1134 | # Adds completions for a trigger action type. | |
1135 | __lttng_complete_trigger_action_type() { | |
1136 | local -r types=( | |
1137 | 'notify:send a notification through the notification mechanism' | |
1138 | 'start-session:start a recording session' | |
1139 | 'stop-session:stop a recording session' | |
1140 | 'rotate-session:archive the current trace chunk of a recording session' | |
1141 | 'snapshot-session:take a recording session snapshot' | |
1142 | ) | |
1143 | ||
1144 | # Add completions | |
1145 | local expl | |
1146 | ||
1147 | _describe 'trigger action type' types | |
1148 | } | |
1149 | ||
1150 | # Adds completions for the arguments of the `add-trigger` command. | |
1151 | # | |
1152 | # Note that those completions are incomplete, in that: | |
1153 | # | |
1154 | # • A valid event rule specification, as per lttng-event-rule(7), | |
1155 | # must follow `--condition=event-rule-matches`. | |
1156 | # | |
1157 | # • `--capture` options are possible within an `event-rule-matches` | |
1158 | # condition specifier. | |
1159 | # | |
1160 | # • The `--rate-policy` option and other arguments, sometimes mandatory, | |
1161 | # are possible within an action specifier. | |
1162 | # | |
1163 | # Having full completion for condition and action specifiers require | |
1164 | # more Zsh magic as _arguments(), like most command-line argument | |
1165 | # parsers, doesn't take option positions into account. | |
1166 | __lttng_complete_add_trigger_cmd() { | |
1167 | local -r specs=( | |
1168 | $help_opt_specs | |
1169 | '(-n --name)'{-n+,--name=}'[set the trigger name]:new trigger name:' | |
1170 | '--owner-uid=[add the trigger as another Unix user]: : __lttng_complete_uid' | |
1171 | '--condition=[set the condition type and arguments]: : __lttng_complete_trigger_condition_type' | |
1172 | '*--action=[set the action type and arguments]: : __lttng_complete_trigger_action_type' | |
1173 | ) | |
1174 | ||
1175 | # Add completions | |
1176 | __lttng_arguments $specs | |
1177 | } | |
1178 | ||
1179 | # Adds completions for the arguments of the `clear` command. | |
1180 | __lttng_complete_clear_cmd() { | |
1181 | local -r specs=( | |
1182 | $help_opt_specs | |
1183 | '(-a --all):: : __lttng_complete_session_name all all' | |
1184 | '(1 -a --all)'{-a,--all}'[clear all recording sessions]' | |
1185 | ) | |
1186 | ||
1187 | # Add completions | |
1188 | __lttng_arguments $specs | |
1189 | } | |
1190 | ||
1191 | # Adds completions for the arguments of the `create` command. | |
1192 | __lttng_complete_create_cmd() { | |
1193 | local specs=( | |
1194 | $help_opt_specs | |
1195 | ':: :_guard "^-*" "new recording session name"' | |
1196 | '(-C --ctrl-url output)'{-C+,--ctrl-url=}'[set the control URL]:control URL:' | |
1197 | '(-D --data-url output)'{-D+,--data-url=}'[set the trace data output URL]:trace data output URL:' | |
1198 | ) | |
1199 | ||
79d885cf | 1200 | # The `--shm-path` option requires LTTng-tools ≥ 2.7 |
76bcac58 PP |
1201 | if ((minor_version >= 7)); then |
1202 | specs+=( | |
1203 | '--shm-path=[write shared memory files to a specific directory]:shared memory file directory:_files -/' | |
1204 | ) | |
1205 | fi | |
1206 | ||
1207 | # Add the remaining option groups | |
1208 | specs+=( | |
1209 | + '(output)' | |
1210 | '(-D --data-url -C --ctrl-url --live)--no-output[disable trace data output]' | |
1211 | '(-D --data-url -C --ctrl-url --live)'{-o+,--output=}'[set the local trace data output directory]:trace data output directory:_files -/' | |
1212 | '(-D --data-url -C --ctrl-url)'{-U+,--set-url=}'[set the trace data output and control URL]:trace data output and control URL:' | |
1213 | + '(mode)' | |
1214 | '(-o --output --no-output)--live=[create an LTTng live recording session]:live timer period (µs):' | |
1215 | '--snapshot[create a snapshot recording session]' | |
1216 | ) | |
1217 | ||
1218 | # Add completions | |
1219 | __lttng_arguments $specs | |
1220 | } | |
1221 | ||
1222 | # Adds completions for the arguments of the `destroy` command. | |
1223 | __lttng_complete_destroy_cmd() { | |
1224 | local specs=( | |
1225 | $help_opt_specs | |
1226 | '(-a --all):: : __lttng_complete_session_name all all' | |
1227 | '(1 -a --all)'{-a,--all}'[destroy all recording sessions]' | |
1228 | ) | |
1229 | ||
1230 | # The `--no-wait` option requires LTTng-tools ≥ 2.8 | |
1231 | if ((minor_version >= 8)); then | |
1232 | specs+=( | |
1233 | '(-n --no-wait)'{-n,--no-wait}'[exit immediately]' | |
1234 | ) | |
1235 | fi | |
1236 | ||
1237 | # Add completions | |
1238 | __lttng_arguments $specs | |
1239 | } | |
1240 | ||
1241 | # Adds completions for the arguments of the `disable-channel` command. | |
1242 | __lttng_complete_disable_channel_cmd() { | |
1243 | local -r specs=( | |
1244 | $help_opt_specs | |
1245 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1246 | ': : _sequence __lttng_complete_channel_name enabled opt' | |
1247 | + '(domain)' | |
1248 | {-k,--kernel}'[select the Linux kernel tracing domain]' | |
1249 | {-u,--userspace}'[select the user space tracing domain]' | |
1250 | ) | |
1251 | ||
1252 | # Add completions | |
1253 | __lttng_arguments $specs | |
1254 | } | |
1255 | ||
1256 | # Prints the XML tracing domain name value depending on the tracing | |
1257 | # domain option (in `$opt_args`), or prints nothing and returns 1 when | |
1258 | # not available. | |
1259 | __lttng_xml_domain_name_from_opt() { | |
1260 | if __lttng_kernel_domain_opt_is_set; then | |
1261 | echo -n KERNEL | |
1262 | elif __lttng_user_domain_opt_is_set; then | |
1263 | echo -n UST | |
1264 | elif __lttng_jul_domain_opt_is_set; then | |
1265 | echo -n JUL | |
1266 | elif __lttng_log4j_domain_opt_is_set; then | |
1267 | echo -n LOG4J | |
1268 | elif __lttng_python_domain_opt_is_set; then | |
1269 | echo -n PYTHON | |
1270 | else | |
1271 | return 1 | |
1272 | fi | |
1273 | } | |
1274 | ||
1275 | # Prints the XML instrumentation point type value depending on the | |
1276 | # instrumentation point option (in `$opt_args`). | |
1277 | __lttng_xml_ip_type_from_opt() { | |
1278 | if (($+opt_args[--syscall] || $+opt_args[ip---syscall])); then | |
1279 | echo -n SYSCALL | |
1280 | elif (($+opt_args[--probe] || $+opt_args[ip---probe])); then | |
1281 | echo -n PROBE | |
1282 | elif (($+opt_args[--function] || $+opt_args[ip---function])); then | |
1283 | echo -n FUNCTION | |
1284 | else | |
1285 | echo -n TRACEPOINT | |
1286 | fi | |
1287 | } | |
1288 | ||
1289 | # Adds completions for an old, enabled recording event rule name | |
1290 | # condition (for the `disable-event` command). | |
1291 | __lttng_complete_old_enabled_er_name_cond() { | |
1292 | local -r msg='recording event rule name condition' | |
1293 | ||
1294 | # Find the recording session name to use | |
1295 | local session_name | |
1296 | ||
1297 | if (($+opt_args[-s])); then | |
1298 | session_name=$opt_args[-s] | |
1299 | elif (($+opt_args[--session])); then | |
1300 | session_name=$opt_args[--session] | |
1301 | else | |
1302 | # Fall back to current recording session | |
1303 | session_name=$(__lttng_cur_session_name) | |
1304 | ||
1305 | if (($? != 0)); then | |
1306 | _guard '^-*' $msg | |
1307 | fi | |
1308 | fi | |
1309 | ||
1310 | # Find the channel name to use (`channel0` is the default name) | |
1311 | local channel_name=channel0 | |
1312 | ||
1313 | if (($+opt_args[-c])); then | |
1314 | channel_name=$opt_args[-c] | |
1315 | elif (($+opt_args[--channel])); then | |
1316 | channel_name=$opt_args[--channel] | |
1317 | fi | |
1318 | ||
1319 | # Create tracing domain XPath part | |
1320 | local domain_xpath | |
1321 | local xml_domain_val | |
1322 | ||
1323 | xml_domain_val=$(__lttng_xml_domain_name_from_opt) | |
1324 | ||
1325 | if (($? == 0)); then | |
1326 | domain_xpath="*[local-name() = 'domain'][*[local-name() = 'type'] = '$xml_domain_val']//" | |
1327 | fi | |
1328 | ||
1329 | # Create channel XPath part | |
1330 | local -r channel_xpath="*[local-name() = 'channel'][*[local-name() = 'name'] = '$channel_name']//" | |
1331 | ||
1332 | # Create instrumentation point type XPath part | |
1333 | local -r xml_ip_type_val=$(__lttng_xml_ip_type_from_opt) | |
1334 | local -r ip_type_xpath="[*[local-name() = 'type'] = '$xml_ip_type_val']" | |
1335 | ||
1336 | # Get XML document (detailed recording session) | |
1337 | local session_xml | |
1338 | ||
1339 | session_xml=$(__lttng_session_xml $msg $session_name) | |
1340 | ||
1341 | if (($? != 0)); then | |
1342 | return 1 | |
1343 | fi | |
1344 | ||
1345 | # Convert to one recording event rule name per line | |
1346 | local lines | |
1347 | ||
1348 | lines=$(__lttng_xmllint_xpath $session_xml "//$domain_xpath${channel_xpath}*[local-name() = 'event']${ip_type_xpath}[*[local-name() = 'enabled'] = 'true']/*[local-name() = 'name']/text()") | |
1349 | ||
1350 | if (($? != 0)); then | |
1351 | _guard '^-*' $msg | |
1352 | return | |
1353 | fi | |
1354 | ||
1355 | local -a er_names | |
1356 | ||
1357 | while read -r line; do | |
1358 | if [[ -z ${line// } ]]; then | |
1359 | # Skip empty line | |
1360 | continue | |
1361 | fi | |
1362 | ||
1363 | er_names+=$line | |
1364 | done <<< $lines | |
1365 | ||
1366 | # Add completions | |
1367 | local expl | |
1368 | ||
1369 | _wanted -C event events expl $msg compadd "$@" -a er_names | |
1370 | } | |
1371 | ||
1372 | # Adds completions for the arguments of the `disable-event` command. | |
1373 | __lttng_complete_disable_event_cmd() { | |
1374 | local -r kernel_ip_opt_excl=(--syscall --probe --function) | |
1375 | local specs=( | |
1376 | $help_opt_specs | |
1377 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1378 | '(-c --channel)'{-c+,--channel=}'[select a specific channel]: : __lttng_complete_channel_name all opt' | |
1379 | + '(names)' | |
1380 | {-a,--all-events}'[disable all recording event rules]' | |
1381 | ': :_sequence __lttng_complete_old_enabled_er_name_cond' | |
1382 | + '(domain)' | |
1383 | {-k,--kernel}'[select the Linux kernel tracing domain]' | |
1384 | "($kernel_ip_opt_excl)"{-u,--userspace}'[select the user space tracing domain]' | |
1385 | "($kernel_ip_opt_excl)"{-j,--jul}'[select the `java.util.logging` tracing domain]' | |
1386 | ) | |
1387 | ||
1388 | # Add tracing domain option specifications based on the minor version | |
1389 | # of LTTng-tools. | |
1390 | if ((minor_version >= 6)); then | |
1391 | specs+=( | |
1392 | "($kernel_ip_opt_excl)"{-l,--log4j}'[select the Apache log4j tracing domain]' | |
1393 | ) | |
1394 | fi | |
1395 | ||
1396 | if ((minor_version >= 7)); then | |
1397 | specs+=( | |
1398 | "($kernel_ip_opt_excl)"{-p,--python}'[select the Python tracing domain]' | |
1399 | ) | |
1400 | fi | |
1401 | ||
1402 | # Add instrumentation point type option specifications based on the | |
1403 | # minor version of LTTng-tools. | |
1404 | if ((minor_version >= 6)); then | |
1405 | specs+=( | |
1406 | + '(ip)' | |
1407 | "($non_kernel_domain_opt_excl)--syscall[disable recording ER matching Linux system call events]" | |
1408 | ) | |
1409 | fi | |
1410 | ||
1411 | if ((minor_version >= 7)); then | |
1412 | specs+=( | |
1413 | '--tracepoint[disable recording ER matching tracepoint events]' | |
1414 | "($non_kernel_domain_opt_excl)--probe[disable recording ER matching kprobe events]" | |
1415 | "($non_kernel_domain_opt_excl)--function[disable recording ER matching kretprobe events]" | |
1416 | ) | |
1417 | fi | |
1418 | ||
1419 | # Add completions | |
1420 | __lttng_arguments $specs | |
1421 | } | |
1422 | ||
1423 | # Adds completions for the arguments of the `disable-rotation` command. | |
1424 | __lttng_complete_disable_rotation_cmd() { | |
1425 | local -r specs=( | |
1426 | $help_opt_specs | |
1427 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1428 | '--timer[disable the periodic rotation schedule]' | |
1429 | '--size[disable the size-based rotation schedule]' | |
1430 | ) | |
1431 | ||
1432 | __lttng_arguments $specs | |
1433 | } | |
1434 | ||
1435 | # Adds completions for a channel output type (`mmap` and, possibly, | |
1436 | # `splice`) (for the `--output` option of the `enable-channel` command). | |
1437 | # | |
1438 | # This function replaces the argument field of the current context with | |
1439 | # `output-opt`. | |
1440 | # | |
1441 | # This function relies on the user space tracing domain options of | |
1442 | # `$opt_args` to restrict the offered completions. Without the user | |
1443 | # space tracing domain option, this function adds the `splice` | |
1444 | # completion too. | |
1445 | __lttng_complete_channel_output_type() { | |
1446 | local output_types=(mmap) | |
1447 | ||
1448 | if ! __lttng_user_domain_opt_is_set; then | |
1449 | # Linux kernel tracing domain or none | |
1450 | output_types+=(splice) | |
1451 | fi | |
1452 | ||
1453 | local expl | |
1454 | ||
1455 | _wanted -C 'output-opt' values expl 'output type' compadd -a output_types | |
1456 | } | |
1457 | ||
1458 | # Adds completions for the non-option argument of the `enable-channel` | |
1459 | # command. | |
1460 | # | |
1461 | # This function either, depending on the keys of `$opt_args`: | |
1462 | # | |
1463 | # At least one creation option: | |
1464 | # Shows a message to enter the new channel name. | |
1465 | # | |
1466 | # Otherwise: | |
1467 | # Adds completions for a comma-separated list of known channel names | |
1468 | # using __lttng_complete_channel_name(). | |
1469 | __lttng_complete_enable_channel_cmd_names() { | |
1470 | local key | |
1471 | local -r enable_opts=( | |
1472 | -s --session | |
1473 | domain---kernel domain--k | |
1474 | domain---userspace domain--u | |
1475 | ) | |
1476 | ||
1477 | # For each key of `$opt_args` | |
1478 | for key in "${(@k)opt_args}"; do | |
1479 | if (($enable_opts[(Ie)$key])); then | |
1480 | # Enabling option exists: skip | |
1481 | continue | |
1482 | fi | |
1483 | ||
1484 | # Creation option exists: single name | |
1485 | _guard '^-*' 'new channel name' | |
1486 | return | |
1487 | done | |
1488 | ||
1489 | # Comma-separated list of existing channel names | |
1490 | _sequence __lttng_complete_channel_name disabled opt | |
1491 | } | |
1492 | ||
1493 | # Adds completions for the arguments of the `enable-channel` command. | |
1494 | __lttng_complete_enable_channel_cmd() { | |
1495 | local specs=( | |
1496 | $help_opt_specs | |
1497 | '--switch-timer=[set the switch timer period]:switch timer period (µs):' | |
1498 | '--read-timer=[set the read timer period]:read timer period (µs):' | |
1499 | '--subbuf-size=[set the size of each sub-buffer]:sub-buffer size (bytes; `k`/`M`/`G` suffixes supported):' | |
1500 | '--num-subbuf=[set the number of sub-buffers per ring buffer]:sub-buffer count:' | |
1501 | '--tracefile-size=[set the maximum size of each trace file]:trace file size (bytes; `k`/`M`/`G` suffixes supported):' | |
1502 | '--tracefile-count=[set the maximum number of trace files]:maximum trace file count:' | |
1503 | '--output=[set the output type]: : __lttng_complete_channel_output_type' | |
1504 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1505 | ': : __lttng_complete_enable_channel_cmd_names' | |
1506 | ) | |
1507 | ||
1508 | # The `--blocking-timeout` and `--monitor-timer` options require | |
1509 | # LTTng-tools ≥ 2.10. | |
1510 | if ((minor_version >= 10)); then | |
1511 | specs+=( | |
1512 | '(--kernel --overwrite --buffers-global)--blocking-timeout=[set the blocking timeout]:blocking timeout (µs):' | |
1513 | '--monitor-timer=[set the monitor timer period]:monitor timer period (µs):' | |
1514 | ) | |
1515 | fi | |
1516 | ||
1517 | # Add the remaining option groups | |
1518 | specs+=( | |
1519 | + '(domain)' | |
1520 | '(--blocking-timeout --buffers-uid --buffers-pid)'{-k,--kernel}'[select the Linux kernel tracing domain]' | |
1521 | '(--buffers-global)'{-u,--userspace}'[select the user space tracing domain]' | |
1522 | + '(loss-mode)' | |
1523 | '--discard[discard event records with no available sub-buffer]' | |
1524 | '(--blocking-timeout)--overwrite[overwrite oldest sub-buffer with no available sub-buffer]' | |
1525 | + '(buffering)' | |
1526 | '(-k --kernel)--buffers-uid[use per-user ring buffers]' | |
1527 | '(-k --kernel)--buffers-pid[use per-process ring buffers]' | |
1528 | '(-u --userspace --blocking-timeout)--buffers-global[use global ring buffers]' | |
1529 | ) | |
1530 | ||
1531 | # Add completions | |
1532 | __lttng_arguments $specs | |
1533 | } | |
1534 | ||
1535 | # Adds completions for the arguments of the `enable-event` command. | |
1536 | __lttng_complete_enable_event_cmd() { | |
1537 | local -r kernel_opts_excl=( | |
1538 | -k --kernel | |
1539 | --syscall | |
1540 | --probe | |
1541 | --userspace-probe | |
1542 | --function | |
1543 | ) | |
1544 | local -r non_kernel_opts_excl=( | |
1545 | $non_kernel_domain_opt_excl | |
1546 | -x --exclude | |
1547 | log-level | |
1548 | ) | |
1549 | local -r exclude_opt_excl=( | |
1550 | $kernel_opts_excl | |
1551 | -j --jul | |
1552 | -l --log4j | |
1553 | -p --python | |
1554 | -x --exclude | |
1555 | ) | |
1556 | local ip_specs=( | |
1557 | '--tracepoint[only match LTTng tracepoint events]' | |
1558 | "($non_kernel_opts_excl)--syscall[only match Linux system call events]" | |
1559 | "($non_kernel_opts_excl)--probe=[only match kprobe events]:kprobe location:" | |
1560 | "($non_kernel_opts_excl)--function=[only match kretprobe events]:kretprobe location:" | |
1561 | ) | |
1562 | local domain_specs=( | |
1563 | "($non_kernel_opts_excl)"{-k,--kernel}'[select the Linux kernel tracing domain]' | |
1564 | "($kernel_opts_excl)"{-u,--userspace}'[select the user space tracing domain]' | |
1565 | "($kernel_opts_excl -x --exclude)"{-j,--jul}'[select the `java.util.logging` tracing domain]' | |
1566 | ) | |
1567 | ||
1568 | # The Apache log4j tracing domain options require LTTng-tools ≥ 2.6 | |
1569 | if ((minor_version >= 6)); then | |
1570 | domain_specs+=( | |
1571 | "($kernel_opts_excl -x --exclude)"{-l,--log4j}'[select the Apache log4j tracing domain]' | |
1572 | ) | |
1573 | fi | |
1574 | ||
1575 | # The Python tracing domain options require LTTng-tools 2.7 | |
1576 | if ((minor_version >= 7)); then | |
1577 | domain_specs+=( | |
1578 | "($kernel_opts_excl -x --exclude)"{-p,--python}'[select the Python tracing domain]' | |
1579 | ) | |
1580 | fi | |
1581 | ||
1582 | # The Linux user space probe instrumentation options require LTTng-tools 2.11 | |
1583 | if ((minor_version >= 11)); then | |
1584 | ip_specs+=( | |
1585 | "($non_kernel_opts_excl)--userspace-probe=[only match Linux user space probe events]:user space probe location:" | |
1586 | ) | |
1587 | fi | |
1588 | ||
1589 | # Add completions. | |
1590 | # | |
1591 | # There's no way, based on the command-line arguments, to distinguish | |
1592 | # between creating a new recording event rule and enabling an | |
1593 | # existing, disabled recording event rule here. | |
1594 | # | |
1595 | # For example, given this: | |
1596 | # | |
1597 | # $ lttng enable-event --kernel --syscall <TAB> | |
1598 | # | |
1599 | # At this point, the user might want the list of existing, disabled | |
1600 | # kernel system call recording event rule names (current recording | |
1601 | # session, default channel name), or the full list of available system | |
1602 | # call instrumentation point names. | |
1603 | # | |
1604 | # This function makes the arbitrary choice to provide the available | |
1605 | # instrumentation point names (__lttng_complete_ip_name()) because, | |
1606 | # interactively, it seems to be more common/useful than disabling | |
1607 | # existing recording event rules. | |
1608 | local -r specs=( | |
1609 | $help_opt_specs | |
1610 | '(--probe --userspace-probe --function -f --filter)'{-f+,--filter=}'[only match events which satisfy an expression]:filter expression:' | |
1611 | "($exclude_opt_excl)"{-x+,--exclude=}'[exclude event name patterns]:comma-separated list of patterns:' | |
1612 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1613 | '(-c --channel)'{-c+,--channel=}'[select a specific channel]: : __lttng_complete_channel_name all opt' | |
1614 | + '(log-level)' | |
1615 | "($kernel_opts_excl)--loglevel=[only match events with specific log levels]: : __lttng_complete_log_level" | |
1616 | "($kernel_opts_excl)--loglevel-only=[only match events with an exact log level]: : __lttng_complete_log_level" | |
1617 | + '(names)' | |
1618 | {-a,--all}'[match events regardless of their name]' | |
1619 | ': :_sequence __lttng_complete_ip_name' | |
1620 | + '(ip)' $ip_specs | |
1621 | + '(domain)' $domain_specs | |
1622 | ) | |
1623 | ||
1624 | __lttng_arguments $specs | |
1625 | } | |
1626 | ||
1627 | # Adds completions for the arguments of the `enable-rotation` command. | |
1628 | __lttng_complete_enable_rotation_cmd() { | |
1629 | local -r specs=( | |
1630 | $help_opt_specs | |
1631 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1632 | '--timer=[rotate periodically]:period (µs; `ms`/`s`/`m`/`h` suffixes supported):' | |
1633 | '--size=[rotate based on flushed size of current trace chunk]:size (bytes; `k`/`M`/`G` suffixes supported):' | |
1634 | ) | |
1635 | ||
1636 | # Add completions | |
1637 | __lttng_arguments $specs | |
1638 | } | |
1639 | ||
1640 | # Adds completions for the arguments of the `help` command. | |
1641 | __lttng_complete_help_cmd() { | |
1642 | local -r specs=( | |
1643 | $help_opt_specs | |
1644 | ': : __lttng_complete_cmd_name' | |
1645 | ) | |
1646 | ||
1647 | # Add completions | |
1648 | __lttng_arguments $specs | |
1649 | } | |
1650 | ||
1651 | # Adds completions for the arguments of the `list` command. | |
1652 | __lttng_complete_list_cmd() { | |
1653 | local -r domain_opt_excl=( | |
1654 | -d --domain | |
1655 | -f --fields | |
1656 | -c --channel | |
1657 | -k --kernel | |
1658 | -u --userspace | |
1659 | -j --jul | |
1660 | -l --log4j | |
1661 | -p --python | |
1662 | --syscall | |
1663 | ) | |
1664 | local specs=( | |
1665 | $help_opt_specs | |
1666 | '(-d --domain -f --fields --syscall -c --channel 1)'{-f,--fields}'[show instrumentation point fields]' | |
1667 | "($domain_opt_excl)"{-d,--domain}'[show tracing domains with at least one channel]' | |
1668 | '(-d --domain -f --fields --syscall -c --channel)'{-c+,--channel=}'[list the objects of a specific channel]: : __lttng_complete_channel_name all arg' | |
1669 | '(-d --domain -f --fields --syscall):recording session name: __lttng_complete_session_name all all' | |
1670 | '(-d --domain -k --kernel)'{-k,--kernel}'[list Linux kernel tracing domain objects]' | |
1671 | '(-d --domain -u --userspace)'{-u,--userspace}'[list user space tracing domain objects]' | |
1672 | '(-d --domain -j --jul)'{-j,--jul}'[list `java.util.logging` tracing domain objects]' | |
1673 | ) | |
1674 | ||
1675 | # The Apache log4j tracing domain and `--syscall` options require | |
1676 | # LTTng-tools ≥ 2.6. | |
1677 | if ((minor_version >= 6)); then | |
1678 | specs+=( | |
1679 | '(-d --domain -l --log4j)'{-l,--log4j}'[list Apache log4j tracing domain objects]' | |
1680 | '(-d --domain)--syscall[list Linux kernel system calls]' | |
1681 | ) | |
1682 | fi | |
1683 | ||
1684 | # The Python tracing domain options require LTTng-tools 2.7 | |
1685 | if ((minor_version >= 7)); then | |
1686 | specs+=( | |
1687 | '(-d --domain -p --python)'{-p,--python}'[list Python tracing domain objects]' | |
1688 | ) | |
1689 | fi | |
1690 | ||
1691 | # Add completions | |
1692 | __lttng_arguments $specs | |
1693 | } | |
1694 | ||
1695 | # Adds completions for the arguments of the `list-triggers` command. | |
1696 | __lttng_complete_list_triggers_cmd() { | |
1697 | __lttng_arguments $help_opt_specs | |
1698 | } | |
1699 | ||
1700 | # Adds completions for the arguments of the `load` command. | |
1701 | __lttng_complete_load_cmd() { | |
1702 | local specs=( | |
1703 | $help_opt_specs | |
1704 | '(-f --force)'{-f,--force}'[overwrite existing recording sessions]' | |
1705 | '(-i --input-path)'{-i+,--input-path=}'[load recording session configurations from a specific path]:recording session configuration path:_files' | |
1706 | '(-a --all --override-name 1)'{-a,--all}'[load all recording session configurations]' | |
1707 | '(-a --all):recording session configuration name:_guard "^-*" "recording session name"' | |
1708 | ) | |
1709 | ||
1710 | if ((minor_version >= 9)); then | |
1711 | specs+=( | |
1712 | '--override-url=[override the loaded recording session output URL]:output URL:' | |
1713 | '(-a --all)--override-name=[override the loaded recording session name]:recording session name:' | |
1714 | ) | |
1715 | fi | |
1716 | ||
1717 | # Add completions | |
1718 | __lttng_arguments $specs | |
1719 | } | |
1720 | ||
1721 | # Adds completions for the arguments of the `metadata` command | |
1722 | # (deprecated). | |
1723 | __lttng_complete_metadata_cmd() { | |
1724 | local -r specs=( | |
1725 | $help_opt_specs | |
1726 | ':action:(regenerate)' | |
1727 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1728 | ) | |
1729 | ||
1730 | # Add completions | |
1731 | __lttng_arguments $specs | |
1732 | } | |
1733 | ||
1734 | # Adds completions for the arguments of the `regenerate` command. | |
1735 | __lttng_complete_regenerate_cmd() { | |
1736 | local -r specs=( | |
1737 | $help_opt_specs | |
1738 | ':trace data type:(metadata statedump)' | |
1739 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1740 | ) | |
1741 | ||
1742 | # Add completions | |
1743 | __lttng_arguments $specs | |
1744 | } | |
1745 | ||
1746 | # Adds completions for the arguments of the `remove-trigger` command. | |
1747 | __lttng_complete_remove_trigger_cmd() { | |
1748 | local -r specs=( | |
1749 | $help_opt_specs | |
1750 | '--owner-uid=[remove the trigger as another Unix user]: : __lttng_complete_uid' | |
1751 | ': : __lttng_complete_trigger_name' | |
1752 | ) | |
1753 | ||
1754 | # Add completions | |
1755 | __lttng_arguments $specs | |
1756 | } | |
1757 | ||
1758 | # Adds completions for the arguments of the `rotate` command. | |
1759 | __lttng_complete_rotate_cmd() { | |
1760 | local -r specs=( | |
1761 | $help_opt_specs | |
1762 | '(-n --no-wait)'{-n,--no-wait}'[exit immediately]' | |
1763 | ': : __lttng_complete_session_name all all' | |
1764 | ) | |
1765 | ||
1766 | # Add completions | |
1767 | __lttng_arguments $specs | |
1768 | } | |
1769 | ||
1770 | # Adds completions for the arguments of the `save` command. | |
1771 | __lttng_complete_save_cmd() { | |
1772 | local -r specs=( | |
1773 | $help_opt_specs | |
1774 | '(-f --force)'{-f,--force}'[overwrite existing recording session configuration files]' | |
1775 | '(-o --output-path)'{-o+,--output-path=}'[save recording session configuration files to a specific directory]:recording session configuration directory:_files -/' | |
1776 | '(-a --all 1)'{-a,--all}'[save all recording session configurations]' | |
1777 | '(-a --all): : __lttng_complete_session_name all all' | |
1778 | ) | |
1779 | ||
1780 | # Add completions | |
1781 | __lttng_arguments $specs | |
1782 | } | |
1783 | ||
1784 | # Adds completions for the arguments of the `set-session` command. | |
1785 | __lttng_complete_set_session_cmd() { | |
1786 | local -r specs=( | |
1787 | $help_opt_specs | |
1788 | ': : __lttng_complete_session_name all all' | |
1789 | ) | |
1790 | ||
1791 | # Add completions | |
1792 | __lttng_arguments $specs | |
1793 | } | |
1794 | ||
1795 | # Adds completions for the arguments of the `snapshot` command. | |
1796 | __lttng_complete_snapshot_cmd() { | |
1797 | local specs=( | |
1798 | $help_opt_specs | |
1799 | '(-): : __lttng_complete_snapshot_action_name' \ | |
1800 | '(-)*:: :->action-args' \ | |
1801 | ) | |
1802 | ||
1803 | # Add action name completions | |
1804 | local curcontext=$curcontext state state_descr line | |
1805 | local -A opt_args | |
1806 | ||
1807 | _arguments -C -s -W : $specs | |
1808 | ||
1809 | if (($? == 0)); then | |
1810 | # Completions added: we're done | |
1811 | return | |
1812 | fi | |
1813 | ||
1814 | # Add action-specific completions | |
1815 | local -r common_session_specs=( | |
1816 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all snapshot' | |
1817 | ) | |
1818 | local -r common_output_specs=( | |
1819 | '(-m --max-size)'{-m+,--max-size=}'[set the maximum total size of all snapshot files]:maximum size (bytes; `k`/`M`/`G` suffixes supported):' | |
1820 | '(-n --name)'{-n+,--name=}'[set the snapshot output name]:snapshot output name:' | |
1821 | '(1 -C --ctrl-url output)'{-C+,--ctrl-url=}'[set the control URL]:control URL:' | |
1822 | '(1 -D --data-url output)'{-D+,--data-url=}'[set the trace data output URL]:trace data output URL:' | |
1823 | '(-C --ctrl-url -D --data-url): :_guard "^-*" "snapshot output URL"' | |
1824 | ) | |
1825 | ||
1826 | if [[ $state[1] = action-args ]]; then | |
1827 | # Add completions for the arguments of the specific snapshot action | |
1828 | curcontext=${curcontext%:*:*}:lttng-snapshot-$line[1]: | |
1829 | ||
1830 | case $line[1] in | |
1831 | add-output | record) | |
1832 | specs=($common_session_specs $common_output_specs);; | |
1833 | del-output) | |
1834 | specs=($common_session_specs ':snapshot output index:(1)');; | |
1835 | list-output) | |
1836 | specs=($common_session_specs);; | |
1837 | *) | |
1838 | _message "unknown snapshot action \`$line[1]\`" | |
1839 | return 1 | |
1840 | ;; | |
1841 | esac | |
1842 | ||
1843 | # Add completions | |
1844 | __lttng_arguments $specs | |
1845 | return | |
1846 | fi | |
1847 | ||
1848 | return 1 | |
1849 | } | |
1850 | ||
1851 | # Adds completions for the arguments of the `start` command. | |
1852 | __lttng_complete_start_cmd() { | |
1853 | local -r specs=( | |
1854 | $help_opt_specs | |
1855 | ': : __lttng_complete_session_name inactive all' | |
1856 | ) | |
1857 | ||
1858 | # Add completions | |
1859 | __lttng_arguments $specs | |
1860 | } | |
1861 | ||
1862 | # Adds completions for the arguments of the `stop` command. | |
1863 | __lttng_complete_stop_cmd() { | |
1864 | local -r specs=( | |
1865 | $help_opt_specs | |
1866 | '(-n --no-wait)'{-n,--no-wait}'[exit immediately]' | |
1867 | ': : __lttng_complete_session_name active all' | |
1868 | ) | |
1869 | ||
1870 | # Add completions | |
1871 | __lttng_arguments $specs | |
1872 | } | |
1873 | ||
1874 | # Adds completions for the arguments of the `status` command. | |
1875 | __lttng_complete_status_cmd() { | |
1876 | __lttng_arguments $help_opt_specs | |
1877 | } | |
1878 | ||
1879 | # Adds completions for the arguments of the `track` command. | |
1880 | __lttng_complete_track_cmd() { | |
1881 | local specs=( | |
1882 | $help_opt_specs | |
1883 | '(-s --session)'{-s+,--session=}'[select a specific recording session]: : __lttng_complete_session_name all all' | |
1884 | '(-a --all)'{-a,--all}'[add all possible values to the selected inclusion sets]' | |
1885 | '(-p --pid)'{-p+,--pid=}'[add values to the process ID inclusion set]:process ID(s):_sequence _pids' | |
1886 | ) | |
1887 | ||
1888 | # Virtual PID and user/group inclusion sets require LTTng-tools ≥ 2.12 | |
1889 | if ((minor_version >= 12)); then | |
1890 | specs+=( | |
1891 | '--vpid=[add values to the virtual process ID inclusion set]:virtual process ID(s):_sequence _pids' | |
1892 | '(-u --userspace)--uid=[add values to the user ID inclusion set]:user(s):_sequence _users' | |
1893 | '--vuid=[add values to the virtual user ID inclusion set]:virtual user(s):_sequence _users' | |
1894 | '(-u --userspace)--gid=[add values to the group ID inclusion set]:group(s):_sequence _groups' | |
1895 | '--vgid=[add values to the virtual group ID inclusion set]:virtual group(s):_sequence _groups' | |
1896 | ) | |
1897 | fi | |
1898 | ||
1899 | # Append tracing domain specifications | |
1900 | specs+=( | |
1901 | + '(domain)' | |
1902 | {-k,--kernel}'[select the Linux kernel tracing domain]' | |
1903 | "(--uid --gid)"{-u,--userspace}'[select the user space tracing domain]' | |
1904 | ) | |
1905 | ||
1906 | # Add completions | |
1907 | __lttng_arguments $specs | |
1908 | } | |
1909 | ||
1910 | # Adds completions for the arguments of the `untrack` command. | |
1911 | __lttng_complete_untrack_cmd() { | |
1912 | # As of LTTng-tools 2.13, the `track` and `untrack` commands expect | |
1913 | # the same arguments. | |
1914 | __lttng_complete_track_cmd | |
1915 | } | |
1916 | ||
1917 | # Adds completions for the arguments of the `version` command. | |
1918 | __lttng_complete_version_cmd() { | |
1919 | __lttng_arguments $help_opt_specs | |
1920 | } | |
1921 | ||
1922 | # Adds completions for the arguments of the `view` command. | |
1923 | __lttng_complete_view_cmd() { | |
1924 | local -r specs=( | |
1925 | $help_opt_specs | |
1926 | '(-e --viewer)'{-e+,--viewer=}'[set the trace reader path]:trace reader path:_files' | |
1927 | '(-t --trace-path): : __lttng_complete_session_name all all' | |
1928 | '(1 -t --trace-path)'{-t+,--trace-path=}'[set the trace directory to pass to the reader]:trace directory:_files -/' | |
1929 | ) | |
1930 | ||
1931 | # Add completions | |
1932 | __lttng_arguments $specs | |
1933 | } | |
1934 | ||
1935 | # Add completions for the specific `lttng` command named `$line[1]`. | |
1936 | __lttng_complete_cmd() { | |
1937 | # An lttng(1) command: replace `lttng` with `lttng-$line[1]` (for | |
1938 | # example, `lttng-add-trigger`). | |
1939 | curcontext=${curcontext%:*:*}:lttng-$line[1]: | |
1940 | ||
1941 | # Keep the tracing group: we need to execute `lttng` for some | |
1942 | # completions and use the required tracing group to connect to the | |
1943 | # same session daemon. | |
1944 | # | |
1945 | # The default tracing group is `tracing`. | |
1946 | local tracing_group=tracing | |
1947 | ||
1948 | if (($+opt_args[-g])); then | |
1949 | tracing_group=$opt_args[-g] | |
1950 | elif (($+opt_args[--group])); then | |
1951 | tracing_group=$opt_args[--group] | |
1952 | fi | |
1953 | ||
1954 | # Add command completions: dispatch to a dedicated function | |
1955 | local -r func_name=__lttng_complete_${line[1]//-/_}_cmd | |
1956 | ||
1957 | if ! typeset -f $func_name >/dev/null; then | |
1958 | _message "unknown command \`$line[1]\`" | |
1959 | return 1 | |
1960 | fi | |
1961 | ||
1962 | local -A opt_args | |
1963 | ||
1964 | $func_name | |
1965 | } | |
1966 | ||
1967 | # Save program name | |
1968 | local -r prog_name=$words[1] | |
1969 | ||
1970 | # First, set the `minor_version` variable to the minor version of | |
1971 | # LTTng-tools. Some features depend on a specific version and this | |
1972 | # completion function supports many versions from LTTng-tools 2.5. | |
1973 | local -i minor_version | |
1974 | ||
1975 | __lttng_set_minor_version | |
1976 | ||
1977 | # Exit now with LTTng-tools < 2.5 or LTTng-tools > 2.14 | |
1978 | local -r ignore_version_limit=${LTTNG_ZSH_COMP_IGNORE_VERSION_LIMIT:-0} | |
1979 | ||
1980 | if ((minor_version < 5 || (minor_version > 14 && !ignore_version_limit))); then | |
1981 | _message "completion not available for LTTng-tools 2.$minor_version; please update the completion files or set \`LTTNG_ZSH_COMP_IGNORE_VERSION_LIMIT=1\`" | |
1982 | return 1 | |
1983 | fi | |
1984 | ||
1985 | # Common help option specifications | |
1986 | local -r help_opt_specs=( | |
1987 | '(- : *)'{-h,--help}'[show help]' | |
1988 | ) | |
1989 | ||
1990 | # Common non Linux kernel tracing domain option exclusions | |
1991 | local -r non_kernel_domain_opt_excl=(-u --userspace -j --jul -l --log4j -p --python) | |
1992 | ||
1993 | # General option specifications | |
1994 | local gen_opt_specs=( | |
1995 | $help_opt_specs | |
1996 | '(- : *)--list-commands[list the available commands and quit]' | |
1997 | '--relayd-path=[set the relay daemon path]:relay daemon path:_files -g \*lttng-relayd' | |
1998 | '--group=[set the tracing group]:tracing group:_groups' | |
1999 | '(-q --quiet)*'{-v,--verbose}'[increase verbosity]' | |
2000 | '(-q --quiet -v --verbose)'{-q,--quiet}'[suppress all messages, including warnings and errors]' | |
2001 | '(- : *)'{-V,--version}'[show version and quit]' | |
2002 | ) | |
2003 | ||
2004 | # MI output requires LTTng-tools ≥ 2.6 | |
2005 | if ((minor_version >= 6)); then | |
2006 | gen_opt_specs+=( | |
2007 | '(-m --mi)'{-m+,--mi=}'[use the machine interface output]:machine interface type:(xml)' | |
2008 | ) | |
2009 | fi | |
2010 | ||
2011 | # Append session daemon option specifications | |
2012 | gen_opt_specs+=( | |
2013 | + '(sessiond)' | |
2014 | {-n,--no-sessiond}'[do not spawn a session daemon]' | |
2015 | '--sessiond-path=[set the session daemon path]:session daemon path:_files -g \*lttng-sessiond' | |
2016 | ) | |
2017 | ||
2018 | # Add general option and command name completions | |
2019 | local curcontext=$curcontext state state_descr line | |
2020 | local -A opt_args | |
2021 | ||
2022 | _arguments -C -s -W : \ | |
2023 | '(-): : __lttng_complete_cmd_name' \ | |
2024 | '(-)*:: :->cmd-args' \ | |
2025 | $gen_opt_specs | |
2026 | ||
2027 | local -ir main_ret=$? | |
2028 | ||
2029 | if ((main_ret == 0)); then | |
2030 | # Completions added: we're done | |
2031 | return | |
2032 | fi | |
2033 | ||
2034 | if [[ $state[1] = cmd-args ]]; then | |
2035 | # Add completions for the arguments of the specific command | |
2036 | __lttng_complete_cmd | |
2037 | return | |
2038 | fi | |
2039 | ||
2040 | return $main_ret |