Commit | Line | Data |
---|---|---|
4ed24f86 JD |
1 | #!/usr/bin/env python3 |
2 | # | |
3 | # The MIT License (MIT) | |
4 | # | |
a3fa57c0 | 5 | # Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com> |
4ed24f86 JD |
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 | ||
bd3cd7c5 JD |
25 | import math |
26 | import re | |
27 | import time | |
28 | import datetime | |
29 | import socket | |
30 | import struct | |
bd3cd7c5 JD |
31 | |
32 | NSEC_PER_SEC = 1000000000 | |
33 | MSEC_PER_NSEC = 1000000 | |
34 | ||
35 | O_CLOEXEC = 0o2000000 | |
36 | ||
37 | ||
baa4cfe9 AB |
38 | def get_syscall_name(event): |
39 | name = event.name | |
40 | ||
41 | if name.startswith('sys_'): | |
fe656dde AB |
42 | # Strip first 4 because sys_ is 4 chars long |
43 | return name[4:] | |
baa4cfe9 AB |
44 | |
45 | # Name begins with syscall_entry_ (14 chars long) | |
fe656dde | 46 | return name[14:] |
baa4cfe9 AB |
47 | |
48 | ||
bd3cd7c5 JD |
49 | def convert_size(size, padding_after=False, padding_before=False): |
50 | if padding_after and size < 1024: | |
3f52a605 | 51 | space_after = ' ' |
bd3cd7c5 | 52 | else: |
3f52a605 | 53 | space_after = '' |
bd3cd7c5 | 54 | if padding_before and size < 1024: |
3f52a605 | 55 | space_before = ' ' |
bd3cd7c5 | 56 | else: |
3f52a605 | 57 | space_before = '' |
bd3cd7c5 | 58 | if size <= 0: |
3f52a605 AB |
59 | return '0 ' + space_before + 'B' + space_after |
60 | size_name = ('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB') | |
bd3cd7c5 JD |
61 | i = int(math.floor(math.log(size, 1024))) |
62 | p = math.pow(1024, i) | |
63 | s = round(size/p, 2) | |
ced36aab | 64 | if s > 0: |
bd3cd7c5 | 65 | try: |
3f52a605 | 66 | v = '%0.02f' % s |
8e05871d | 67 | return '%s %s%s%s' % (v, space_before, size_name[i], space_after) |
bd3cd7c5 JD |
68 | except: |
69 | print(i, size_name) | |
3f52a605 | 70 | raise Exception('Too big to be true') |
bd3cd7c5 JD |
71 | else: |
72 | return '0 B' | |
73 | ||
74 | ||
ced36aab AB |
75 | def is_multi_day_trace_collection(handles): |
76 | time_begin = None | |
77 | ||
78 | for handle in handles.values(): | |
79 | if time_begin is None: | |
80 | time_begin = time.localtime(handle.timestamp_begin / NSEC_PER_SEC) | |
81 | year_begin = time_begin.tm_year | |
82 | month_begin = time_begin.tm_mon | |
83 | day_begin = time_begin.tm_mday | |
84 | ||
85 | time_end = time.localtime(handle.timestamp_end / NSEC_PER_SEC) | |
86 | year_end = time_end.tm_year | |
87 | month_end = time_end.tm_mon | |
88 | day_end = time_end.tm_mday | |
89 | ||
90 | if year_begin != year_end: | |
bd3cd7c5 | 91 | return True |
ced36aab | 92 | elif month_begin != month_end: |
bd3cd7c5 | 93 | return True |
ced36aab | 94 | elif day_begin != day_end: |
bd3cd7c5 | 95 | return True |
ced36aab | 96 | |
bd3cd7c5 JD |
97 | return False |
98 | ||
99 | ||
ced36aab AB |
100 | def trace_collection_date(handles): |
101 | if is_multi_day_trace_collection(handles): | |
bd3cd7c5 | 102 | return None |
ced36aab | 103 | |
652bc6b7 AB |
104 | for handle in handles.values(): |
105 | trace_time = time.localtime(handle.timestamp_begin / NSEC_PER_SEC) | |
106 | year = trace_time.tm_year | |
107 | month = trace_time.tm_mon | |
108 | day = trace_time.tm_mday | |
109 | return (year, month, day) | |
bd3cd7c5 JD |
110 | |
111 | ||
ced36aab | 112 | def extract_timerange(handles, timerange, gmt): |
5b395a93 AB |
113 | pattern = re.compile(r'^\[(?P<begin>.*),(?P<end>.*)\]$') |
114 | if not pattern.match(timerange): | |
bd3cd7c5 | 115 | return None |
5b395a93 AB |
116 | begin_str = pattern.search(timerange).group('begin').strip() |
117 | end_str = pattern.search(timerange).group('end').strip() | |
ced36aab AB |
118 | begin = date_to_epoch_nsec(handles, begin_str, gmt) |
119 | end = date_to_epoch_nsec(handles, end_str, gmt) | |
bd3cd7c5 JD |
120 | return (begin, end) |
121 | ||
122 | ||
ced36aab | 123 | def date_to_epoch_nsec(handles, date, gmt): |
bd3cd7c5 | 124 | # match 2014-12-12 17:29:43.802588035 or 2014-12-12T17:29:43.802588035 |
5b395a93 AB |
125 | pattern1 = re.compile(r'^(?P<year>\d\d\d\d)-(?P<mon>[01]\d)-' |
126 | r'(?P<day>[0123]\d)[\sTt]' | |
127 | r'(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d).' | |
128 | r'(?P<nsec>\d\d\d\d\d\d\d\d\d)$') | |
bd3cd7c5 | 129 | # match 2014-12-12 17:29:43 or 2014-12-12T17:29:43 |
5b395a93 AB |
130 | pattern2 = re.compile(r'^(?P<year>\d\d\d\d)-(?P<mon>[01]\d)-' |
131 | r'(?P<day>[0123]\d)[\sTt]' | |
132 | r'(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d)$') | |
bd3cd7c5 | 133 | # match 17:29:43.802588035 |
5b395a93 AB |
134 | pattern3 = re.compile(r'^(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d).' |
135 | r'(?P<nsec>\d\d\d\d\d\d\d\d\d)$') | |
bd3cd7c5 | 136 | # match 17:29:43 |
5b395a93 AB |
137 | pattern4 = re.compile(r'^(?P<hour>\d\d):(?P<min>\d\d):(?P<sec>\d\d)$') |
138 | ||
139 | if pattern1.match(date): | |
140 | year = pattern1.search(date).group('year') | |
141 | month = pattern1.search(date).group('mon') | |
142 | day = pattern1.search(date).group('day') | |
143 | hour = pattern1.search(date).group('hour') | |
144 | minute = pattern1.search(date).group('min') | |
145 | sec = pattern1.search(date).group('sec') | |
146 | nsec = pattern1.search(date).group('nsec') | |
147 | elif pattern2.match(date): | |
148 | year = pattern2.search(date).group('year') | |
149 | month = pattern2.search(date).group('mon') | |
150 | day = pattern2.search(date).group('day') | |
151 | hour = pattern2.search(date).group('hour') | |
152 | minute = pattern2.search(date).group('min') | |
153 | sec = pattern2.search(date).group('sec') | |
bd3cd7c5 | 154 | nsec = 0 |
5b395a93 | 155 | elif pattern3.match(date): |
ced36aab AB |
156 | collection_date = trace_collection_date(handles) |
157 | if collection_date is None: | |
bd3cd7c5 JD |
158 | print("Use the format 'yyyy-mm-dd hh:mm:ss[.nnnnnnnnn]' " |
159 | "for multi-day traces") | |
160 | return None | |
ced36aab | 161 | (year, month, day) = collection_date |
5b395a93 AB |
162 | hour = pattern3.search(date).group('hour') |
163 | minute = pattern3.search(date).group('min') | |
164 | sec = pattern3.search(date).group('sec') | |
165 | nsec = pattern3.search(date).group('nsec') | |
166 | elif pattern4.match(date): | |
ced36aab AB |
167 | collection_date = trace_collection_date(handles) |
168 | if collection_date is None: | |
bd3cd7c5 JD |
169 | print("Use the format 'yyyy-mm-dd hh:mm:ss[.nnnnnnnnn]' " |
170 | "for multi-day traces") | |
171 | return None | |
ced36aab | 172 | (year, month, day) = collection_date |
5b395a93 AB |
173 | hour = pattern4.search(date).group('hour') |
174 | minute = pattern4.search(date).group('min') | |
175 | sec = pattern4.search(date).group('sec') | |
bd3cd7c5 JD |
176 | nsec = 0 |
177 | else: | |
178 | return None | |
179 | ||
ced36aab | 180 | date_time = datetime.datetime(int(year), int(month), int(day), int(hour), |
5b395a93 | 181 | int(minute), int(sec)) |
bd3cd7c5 | 182 | if gmt: |
ced36aab AB |
183 | date_time = date_time + datetime.timedelta(seconds=time.timezone) |
184 | return int(date_time.timestamp()) * NSEC_PER_SEC + int(nsec) | |
bd3cd7c5 JD |
185 | |
186 | ||
187 | def ns_to_asctime(ns): | |
188 | return time.asctime(time.localtime(ns/NSEC_PER_SEC)) | |
189 | ||
190 | ||
191 | def ns_to_hour(ns): | |
ced36aab AB |
192 | date = time.localtime(ns / NSEC_PER_SEC) |
193 | return '%02d:%02d:%02d' % (date.tm_hour, date.tm_min, date.tm_sec) | |
bd3cd7c5 JD |
194 | |
195 | ||
196 | def ns_to_hour_nsec(ns, multi_day=False, gmt=False): | |
197 | if gmt: | |
ced36aab | 198 | date = time.gmtime(ns / NSEC_PER_SEC) |
bd3cd7c5 | 199 | else: |
ced36aab | 200 | date = time.localtime(ns / NSEC_PER_SEC) |
bd3cd7c5 | 201 | if multi_day: |
ced36aab AB |
202 | return ('%04d-%02d-%02d %02d:%02d:%02date.%09d' % |
203 | (date.tm_year, date.tm_mon, date.tm_mday, date.tm_hour, | |
204 | date.tm_min, date.tm_sec, ns % NSEC_PER_SEC)) | |
bd3cd7c5 | 205 | else: |
ced36aab AB |
206 | return ('%02d:%02d:%02date.%09d' % |
207 | (date.tm_hour, date.tm_min, date.tm_sec, ns % NSEC_PER_SEC)) | |
bd3cd7c5 JD |
208 | |
209 | ||
210 | def ns_to_sec(ns): | |
ced36aab | 211 | return '%lu.%09u' % (ns / NSEC_PER_SEC, ns % NSEC_PER_SEC) |
bd3cd7c5 JD |
212 | |
213 | ||
214 | def ns_to_day(ns): | |
ced36aab AB |
215 | date = time.localtime(ns/NSEC_PER_SEC) |
216 | return '%04d-%02d-%02d' % (date.tm_year, date.tm_mon, date.tm_mday) | |
bd3cd7c5 JD |
217 | |
218 | ||
219 | def sec_to_hour(ns): | |
ced36aab AB |
220 | date = time.localtime(ns) |
221 | return '%02d:%02d:%02d' % (date.tm_hour, date.tm_min, date.tm_sec) | |
bd3cd7c5 JD |
222 | |
223 | ||
224 | def sec_to_nsec(sec): | |
225 | return sec * NSEC_PER_SEC | |
226 | ||
227 | ||
228 | def seq_to_ipv4(ip): | |
3f52a605 | 229 | return '{}.{}.{}.{}'.format(ip[0], ip[1], ip[2], ip[3]) |
bd3cd7c5 JD |
230 | |
231 | ||
232 | def int_to_ipv4(ip): | |
3f52a605 | 233 | return socket.inet_ntoa(struct.pack('!I', ip)) |
bd3cd7c5 JD |
234 | |
235 | ||
236 | def str_to_bytes(value): | |
3f52a605 AB |
237 | num = '' |
238 | unit = '' | |
bd3cd7c5 | 239 | for i in value: |
3f52a605 | 240 | if i.isdigit() or i == '.': |
bd3cd7c5 JD |
241 | num = num + i |
242 | elif i.isalnum(): | |
243 | unit = unit + i | |
244 | num = float(num) | |
5faa923d | 245 | if not unit: |
bd3cd7c5 | 246 | return int(num) |
3f52a605 | 247 | if unit in ['B']: |
bd3cd7c5 | 248 | return int(num) |
3f52a605 | 249 | if unit in ['k', 'K', 'kB', 'KB']: |
bd3cd7c5 | 250 | return int(num * 1024) |
3f52a605 | 251 | if unit in ['m', 'M', 'mB', 'MB']: |
bd3cd7c5 | 252 | return int(num * 1024 * 1024) |
3f52a605 | 253 | if unit in ['g', 'G', 'gB', 'GB']: |
bd3cd7c5 | 254 | return int(num * 1024 * 1024 * 1024) |
3f52a605 | 255 | if unit in ['t', 'T', 'tB', 'TB']: |
bd3cd7c5 | 256 | return int(num * 1024 * 1024 * 1024 * 1024) |
3f52a605 | 257 | print('Unit', unit, 'not understood') |
bd3cd7c5 JD |
258 | return None |
259 | ||
260 | ||
261 | def get_v4_addr_str(ip): | |
262 | # depending on the version of lttng-modules, the v4addr is a | |
263 | # string (< 2.6) or sequence (>= 2.6) | |
264 | try: | |
265 | return seq_to_ipv4(ip) | |
266 | except TypeError: | |
267 | return int_to_ipv4(ip) |