Cleanup license (MIT)
[deliverable/lttng-analyses.git] / lttnganalysescli / lttnganalysescli / command.py
1 #!/usr/bin/env python3
2 #
3 # The MIT License (MIT)
4 #
5 # Copyright (C) 2015 - Julien Desfossez <jdesfosez@efficios.com>
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24
25 import linuxautomaton.automaton
26 from lttnganalysescli import progressbar
27 from linuxautomaton import common
28 from babeltrace import TraceCollection
29 import argparse
30 import sys
31
32
33 class Command:
34 def __init__(self, add_arguments_cb,
35 enable_proc_filter_args=False,
36 enable_max_min_args=False,
37 enable_max_min_size_arg=False,
38 enable_freq_arg=False,
39 enable_log_arg=False,
40 enable_stats_arg=False):
41 self._add_arguments_cb = add_arguments_cb
42 self._enable_proc_filter_args = enable_proc_filter_args
43 self._enable_max_min_arg = enable_max_min_args
44 self._enable_max_min_size_arg = enable_max_min_size_arg
45 self._enable_freq_arg = enable_freq_arg
46 self._enable_log_arg = enable_log_arg
47 self._enable_stats_arg = enable_stats_arg
48 self._create_automaton()
49
50 def _error(self, msg, exit_code=1):
51 print(msg, file=sys.stderr)
52 sys.exit(exit_code)
53
54 def _gen_error(self, msg, exit_code=1):
55 self._error('Error: {}'.format(msg), exit_code)
56
57 def _cmdline_error(self, msg, exit_code=1):
58 self._error('Command line error: {}'.format(msg), exit_code)
59
60 def _open_trace(self):
61 traces = TraceCollection()
62 handle = traces.add_traces_recursive(self._arg_path, "ctf")
63 if handle == {}:
64 self._gen_error("Failed to open " + self._arg_path, -1)
65 self._handle = handle
66 self._traces = traces
67 common.process_date_args(self)
68
69 def _close_trace(self):
70 for h in self._handle.values():
71 self._traces.remove_trace(h)
72
73 def _run_analysis(self, reset_cb, refresh_cb, break_cb=None):
74 self.trace_start_ts = 0
75 self.trace_end_ts = 0
76 self.current_sec = 0
77 self.start_ns = 0
78 self.end_ns = 0
79 started = 0
80 progressbar.progressbar_setup(self)
81 if not self._arg_begin:
82 started = 1
83 for event in self._traces.events:
84 progressbar.progressbar_update(self)
85 if self._arg_begin and started == 0 and \
86 event.timestamp >= self._arg_begin:
87 started = 1
88 self.trace_start_ts = event.timestamp
89 self.start_ns = event.timestamp
90 reset_cb(event.timestamp)
91 if self._arg_end and event.timestamp > self._arg_end:
92 if break_cb is not None:
93 # check if we really can break here
94 if break_cb():
95 break
96 else:
97 break
98 if self.start_ns == 0:
99 self.start_ns = event.timestamp
100 if self.trace_start_ts == 0:
101 self.trace_start_ts = event.timestamp
102 self.end_ns = event.timestamp
103 self._check_refresh(event, refresh_cb)
104 self.trace_end_ts = event.timestamp
105 # feed analysis
106 self._analysis.process_event(event)
107 # feed automaton
108 self._automaton.process_event(event)
109 progressbar.progressbar_finish(self)
110
111 def _check_refresh(self, event, refresh_cb):
112 """Check if we need to output something"""
113 if self._arg_refresh == 0:
114 return
115 event_sec = event.timestamp / common.NSEC_PER_SEC
116 if self.current_sec == 0:
117 self.current_sec = event_sec
118 elif self.current_sec != event_sec and \
119 (self.current_sec + self._arg_refresh) <= event_sec:
120 refresh_cb(self.start_ns, event.timestamp)
121 self.current_sec = event_sec
122 self.start_ns = event.timestamp
123
124 def _validate_transform_common_args(self, args):
125 self._arg_path = args.path
126 if args.limit:
127 self._arg_limit = args.limit
128 self._arg_begin = None
129 if args.begin:
130 self._arg_begin = args.begin
131 self._arg_end = None
132 if args.end:
133 self._arg_end = args.end
134 self._arg_timerange = None
135 if args.timerange:
136 self._arg_timerange = args.timerange
137 self._arg_gmt = None
138 if args.gmt:
139 self._arg_gmt = args.gmt
140 self._arg_refresh = args.refresh
141 self._arg_no_progress = args.no_progress
142
143 if self._enable_proc_filter_args:
144 self._arg_proc_list = None
145 if args.procname:
146 self._arg_proc_list = args.procname.split(",")
147 self._arg_pid_list = None
148 if args.pid:
149 self._arg_pid_list = args.pid.split(",")
150
151 if self._enable_max_min_arg:
152 if args.max == -1:
153 self._arg_max = None
154 else:
155 self._arg_max = args.max
156 if args.min == -1:
157 self._arg_min = None
158 else:
159 self._arg_min = args.min
160
161 if self._enable_max_min_size_arg:
162 if args.maxsize == -1:
163 self._arg_maxsize = None
164 else:
165 self._arg_maxsize = args.maxsize
166 if args.minsize == -1:
167 self._arg_minsize = None
168 else:
169 self._arg_minsize = args.minsize
170
171 if self._enable_freq_arg:
172 self._arg_freq = args.freq
173 self._arg_freq_resolution = args.freq_resolution
174
175 if self._enable_log_arg:
176 self._arg_log = args.log
177
178 if self._enable_stats_arg:
179 self._arg_stats = args.stats
180
181 def _parse_args(self):
182 ap = argparse.ArgumentParser(description=self._DESC)
183
184 # common arguments
185 ap.add_argument('path', metavar="<path/to/trace>", help='trace path')
186 ap.add_argument('-r', '--refresh', type=int,
187 help='Refresh period in seconds', default=0)
188 ap.add_argument('--limit', type=int, default=10,
189 help='Limit to top X (default = 10)')
190 ap.add_argument('--no-progress', action="store_true",
191 help='Don\'t display the progress bar')
192 ap.add_argument('--gmt', action="store_true",
193 help='Manipulate timestamps based on GMT instead '
194 'of local time')
195 ap.add_argument('--begin', type=str, help='start time: '
196 'hh:mm:ss[.nnnnnnnnn]')
197 ap.add_argument('--end', type=str, help='end time: '
198 'hh:mm:ss[.nnnnnnnnn]')
199 ap.add_argument('--timerange', type=str, help='time range: '
200 '[begin,end]')
201
202 if self._enable_proc_filter_args:
203 ap.add_argument('--procname', type=str, default=0,
204 help='Filter the results only for this list of '
205 'process names')
206 ap.add_argument('--pid', type=str, default=0,
207 help='Filter the results only for this list '
208 'of PIDs')
209
210 if self._enable_max_min_arg:
211 ap.add_argument('--max', type=float, default=-1,
212 help='Filter out, duration longer than max usec')
213 ap.add_argument('--min', type=float, default=-1,
214 help='Filter out, duration shorter than min usec')
215
216 if self._enable_max_min_size_arg:
217 ap.add_argument('--maxsize', type=float, default=-1,
218 help='Filter out, I/O operations working with '
219 'more that maxsize bytes')
220 ap.add_argument('--minsize', type=float, default=-1,
221 help='Filter out, I/O operations working with '
222 'less that minsize bytes')
223
224 if self._enable_freq_arg:
225 ap.add_argument('--freq', action="store_true",
226 help='Show the frequency distribution of '
227 'handler duration')
228 ap.add_argument('--freq-resolution', type=int, default=20,
229 help='Frequency distribution resolution '
230 '(default 20)')
231
232 if self._enable_log_arg:
233 ap.add_argument('--log', action="store_true",
234 help='Display the events in the order they '
235 'appeared')
236
237 if self._enable_stats_arg:
238 ap.add_argument('--stats', action="store_true",
239 help='Display the statistics')
240
241 # specific arguments
242 self._add_arguments_cb(ap)
243
244 # version of the specific command
245 ap.add_argument('-V', '--version', action='version',
246 version=self._VERSION)
247
248 # parse arguments
249 args = ap.parse_args()
250
251 self._validate_transform_common_args(args)
252
253 # save all arguments
254 self._args = args
255
256 def _create_automaton(self):
257 self._automaton = linuxautomaton.automaton.Automaton()
This page took 0.039621 seconds and 5 git commands to generate.