strace_log 0.1.3 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +59 -88
- data/bin/strace-stat +14 -2
- data/lib/strace_log.rb +132 -126
- metadata +3 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bf0ec0832d7b894a0b0bef334b4e7614313db881e9f2b1fc0e867943f2974d5a
|
4
|
+
data.tar.gz: 3f95e1df8f7d617df9783fbd9bd23de39ef4bbcd972c51de082bf81aae3390b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b01896fcb02a1ff979a5a4486450c81a935fd24759bfae2c47fc1d4e0509be344d7882805c88b7950c224c3ddf438aed7cb7fc6fb02c4ca29716f4a3098729b
|
7
|
+
data.tar.gz: 03272c4affd1a38c0a58ed141c6b0d88e4dc67139e0c4b6be162f800e2298b25c41b71553b02301bcb54dbc763f769c804ddaa0bbc372abdb13217248de818a5
|
data/README.md
CHANGED
@@ -25,104 +25,75 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
Run command with strace:
|
27
27
|
|
28
|
-
$ strace -
|
28
|
+
$ strace -T -o strace.log command
|
29
29
|
|
30
|
-
|
30
|
+
Output statistics of strace log by mount point to CSV file:
|
31
31
|
|
32
|
-
$ strace-stat strace.log
|
32
|
+
$ strace-stat -s -o strace.csv strace.log
|
33
|
+
|
34
|
+
Option for `strace-stat`:
|
35
|
+
|
36
|
+
Usage: strace-stat [options] [FILE]
|
37
|
+
FILE filename of strace log (default: stdin)
|
38
|
+
-o, --output OUTFILE output CSV filename
|
39
|
+
-s, --stat output statistics by mount point (default: statistics by each path)
|
40
|
+
-t, --table TABLEFILE filename of mounted file system table (default:/etc/mtab)
|
41
|
+
-c, --column TABLECOLUMN column number of mount point in mtab (default:2)
|
33
42
|
|
34
43
|
## Classes
|
35
44
|
|
36
45
|
* StraceLog::ParsedCall
|
37
|
-
* StraceLog::IOCounter
|
38
46
|
* StraceLog::Stat
|
39
47
|
|
40
48
|
## Example
|
41
49
|
|
42
|
-
$ strace -
|
43
|
-
|
44
|
-
$
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
dup2: 0.000213,
|
90
|
-
lseek: 0.000112,
|
91
|
-
clock_gettime: 0.000343,
|
92
|
-
write: 1.229899,
|
93
|
-
munmap: 0.000110,
|
94
|
-
}
|
95
|
-
|
96
|
-
/bin/dd:
|
97
|
-
ok={execve:1}
|
98
|
-
time={execve:0.000479}
|
99
|
-
|
100
|
-
/dev/zero:
|
101
|
-
ok={close:2, dup2:1, lseek:1, open:1, read:10000}
|
102
|
-
size={read:5120000}
|
103
|
-
time={close:0.000224, dup2:0.000112, lseek:0.000112, open:0.000119, read:1.176062}
|
104
|
-
|
105
|
-
/etc/ld.so.preload:
|
106
|
-
fail={access:1}
|
107
|
-
time={access:0.000157}
|
108
|
-
|
109
|
-
...
|
110
|
-
|
111
|
-
/usr/share/locale/locale.alias:
|
112
|
-
ok={close:1, fstat:1, open:1, read:2}
|
113
|
-
size={read:2512}
|
114
|
-
time={close:0.000202, fstat:0.000216, open:0.000124, read:0.000221}
|
115
|
-
|
116
|
-
stderr:
|
117
|
-
ok={close:1, write:3}
|
118
|
-
size={write:90}
|
119
|
-
time={close:0.000022, write:0.000243}
|
120
|
-
|
121
|
-
tmpfile:
|
122
|
-
ok={close:2, dup2:1, open:1, write:10000}
|
123
|
-
size={write:5120000}
|
124
|
-
time={close:0.005866, dup2:0.000101, open:0.000154, write:1.229656}
|
125
|
-
|
50
|
+
$ strace -T -o strace.log dd if=/dev/zero of=tmpfile count=10000
|
51
|
+
$ strace-stat -s -o strace.csv strace.log
|
52
|
+
$ cat strace.csv
|
53
|
+
path,syscall,calls,errors,time,size
|
54
|
+
*,execve,1,0,0.009673,
|
55
|
+
*,brk,4,0,0.000057,
|
56
|
+
*,mmap,10,0,0.000285,
|
57
|
+
*,access,1,1,0.000021,
|
58
|
+
*,open,39,32,0.001220,
|
59
|
+
*,stat,27,21,0.000470,
|
60
|
+
*,read,10003,0,0.123271,5123334
|
61
|
+
*,fstat,5,0,0.000147,
|
62
|
+
*,mprotect,4,0,0.000075,
|
63
|
+
*,close,10,0,0.000311,
|
64
|
+
*,arch_prctl,1,0,0.000012,
|
65
|
+
*,rt_sigaction,4,0,0.000050,
|
66
|
+
*,dup2,2,0,0.000037,
|
67
|
+
*,lseek,1,0,0.000006,
|
68
|
+
*,write,10003,0,0.246277,5120136
|
69
|
+
*,munmap,1,0,0.000049,
|
70
|
+
*,exit_group,1,0,0.000000,
|
71
|
+
/,execve,1,0,0.009673,
|
72
|
+
/,access,1,1,0.000021,
|
73
|
+
/,open,29,24,0.000885,
|
74
|
+
/,stat,19,14,0.000346,
|
75
|
+
/,read,3,0,0.000101,3334
|
76
|
+
/,fstat,5,0,0.000147,
|
77
|
+
/,mmap,5,0,0.000181,
|
78
|
+
/,close,5,0,0.000167,
|
79
|
+
/home,open,9,8,0.000251,
|
80
|
+
/home,stat,8,7,0.000124,
|
81
|
+
/home,dup2,1,0,0.000030,
|
82
|
+
/home,close,2,0,0.000054,
|
83
|
+
/home,write,10000,0,0.246116,5120000
|
84
|
+
/dev,open,1,0,0.000084,
|
85
|
+
/dev,dup2,1,0,0.000007,
|
86
|
+
/dev,close,2,0,0.000049,
|
87
|
+
/dev,lseek,1,0,0.000006,
|
88
|
+
/dev,read,10000,0,0.123170,5120000
|
89
|
+
stderr,write,3,0,0.000161,136
|
90
|
+
stderr,close,1,0,0.000041,
|
91
|
+
|
92
|
+
(path=* means total sum for each system call)
|
93
|
+
|
94
|
+
Same example using pipe:
|
95
|
+
|
96
|
+
$ strace -T -s 0 -o '|strace-stat -s -o strace.csv' dd if=/dev/zero of=tmpfile count=10000
|
126
97
|
|
127
98
|
## Contributing
|
128
99
|
|
data/bin/strace-stat
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "strace_log"
|
4
|
+
require 'optparse'
|
4
5
|
|
5
|
-
|
6
|
+
params = {}
|
7
|
+
outfile = nil
|
8
|
+
|
9
|
+
opt = OptionParser.new
|
10
|
+
opt.on('-o OUTFILE','--output','output CSV filename') {|v| outfile = v}
|
11
|
+
opt.on('-s','--stat','output statistics by mount point (default: statistics by each path)') {|v| params[:sum] = true}
|
12
|
+
opt.on('-t TABLEFILE','--table','filename of mounted file system table (default:/etc/mtab)') {|v| params[:table] = v}
|
13
|
+
opt.on('-c TABLECOLUMN','--column','column number of mount point in mtab (default:2)') {|v| params[:column] = v.to_i}
|
14
|
+
opt.banner += ' [STRACE_LOG_FILE]'
|
15
|
+
opt.parse!(ARGV)
|
16
|
+
|
17
|
+
stat = StraceLog::Stat.new(**params)
|
6
18
|
stat.parse(ARGF)
|
7
|
-
stat.
|
19
|
+
stat.write(outfile)
|
data/lib/strace_log.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
require 'strscan'
|
2
|
+
require 'pathname'
|
3
|
+
require 'csv'
|
2
4
|
|
3
5
|
module StraceLog
|
4
6
|
|
5
|
-
VERSION = "0.1
|
7
|
+
VERSION = "0.2.1"
|
6
8
|
|
7
9
|
class ParsedCall
|
8
10
|
ESCAPES = [ /x[\da-f][\da-f]/i, /n/, /t/, /r/, /\\/, /"/, /\d+/]
|
9
11
|
|
10
12
|
def initialize(line)
|
13
|
+
@size = nil
|
11
14
|
if /^(?:(\d\d:\d\d:\d\d|\d+)(?:\.(\d+))? )?[+-]{3}.*[+-]{3}$/ =~ line
|
12
15
|
@mesg = line
|
13
16
|
else
|
@@ -17,13 +20,13 @@ module StraceLog
|
|
17
20
|
@usec = s[2]
|
18
21
|
@func = s[3]
|
19
22
|
@args = scan_items(s,/\s*\)\s*/)
|
20
|
-
s.scan(/\s*= ([^=<>\s]+)(?:\s+([^<>]+))?(?: <([\d.]+)>)?$/)
|
23
|
+
s.scan(/\s*= ([^=<>\s]+(?:<[^<>]*>)?)(?:\s+([^<>]+))?(?: <([\d.]+)>)?$/)
|
21
24
|
@ret = s[1]
|
22
25
|
@mesg = s[2]
|
23
26
|
@elap = s[3]
|
24
27
|
end
|
25
28
|
end
|
26
|
-
attr_reader :time, :usec, :func, :args, :ret , :mesg, :elap
|
29
|
+
attr_reader :time, :usec, :func, :args, :ret , :mesg, :elap, :size
|
27
30
|
|
28
31
|
def scan_items(s,close)
|
29
32
|
args = []
|
@@ -81,81 +84,77 @@ module StraceLog
|
|
81
84
|
def scan_other(s)
|
82
85
|
s.scan(/[^"\\,{}()\[\]]+/)
|
83
86
|
end
|
84
|
-
end
|
85
|
-
|
86
87
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
@size = {}
|
93
|
-
@time = {}
|
94
|
-
@rename = []
|
88
|
+
def set_size
|
89
|
+
sz = @ret.to_i
|
90
|
+
if sz >= 0
|
91
|
+
@size = sz
|
92
|
+
end
|
95
93
|
end
|
96
|
-
|
94
|
+
end
|
97
95
|
|
98
|
-
def add(h,func,c)
|
99
|
-
h[func] = (h[func] || 0) + c
|
100
|
-
end
|
101
96
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
97
|
+
class Stat
|
98
|
+
|
99
|
+
class Counter
|
100
|
+
def initialize
|
101
|
+
@calls = 0
|
102
|
+
@errors = 0
|
103
|
+
@time = 0
|
104
|
+
@size = nil
|
107
105
|
end
|
108
|
-
|
109
|
-
end
|
106
|
+
attr_reader :calls, :errors, :size, :time
|
110
107
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
108
|
+
def count(call)
|
109
|
+
@calls += 1
|
110
|
+
@errors += 1 if call.ret == "-1"
|
111
|
+
@time += call.elap.to_f if call.elap
|
112
|
+
@size = (@size||0) + call.size if call.size
|
115
113
|
end
|
116
|
-
count(fc)
|
117
|
-
end
|
118
114
|
|
119
|
-
|
120
|
-
|
121
|
-
|
115
|
+
def to_a
|
116
|
+
[@calls,@errors,"%.6f"%@time,@size]
|
117
|
+
end
|
122
118
|
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
120
|
+
class CallCounter
|
121
|
+
def initialize(path)
|
122
|
+
@path = path
|
123
|
+
@rename = []
|
124
|
+
@counter = {}
|
129
125
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
keys = @size.keys.sort
|
136
|
-
Kernel.print " size={"+keys.map{|k| "#{k}:#{@size[k]}"}.join(", ")+"}\n"
|
126
|
+
attr_reader :path, :rename
|
127
|
+
|
128
|
+
def count(call)
|
129
|
+
c = (@counter[call.func] ||= Counter.new)
|
130
|
+
c.count(call)
|
137
131
|
end
|
138
|
-
|
139
|
-
|
140
|
-
|
132
|
+
|
133
|
+
def rename_as(newpath)
|
134
|
+
@rename << @path
|
135
|
+
@path = newpath
|
141
136
|
end
|
142
|
-
|
143
|
-
|
137
|
+
|
138
|
+
def each
|
139
|
+
@counter.keys.map do |func|
|
140
|
+
yield [@path,func,*@counter[func].to_a]
|
141
|
+
end
|
144
142
|
end
|
145
|
-
puts
|
146
143
|
end
|
147
|
-
end
|
148
144
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
def initialize
|
145
|
+
def initialize(sum:false,table:'/etc/mtab',column:2)
|
146
|
+
@sum = sum
|
153
147
|
@stat = {}
|
154
|
-
@
|
155
|
-
@
|
148
|
+
@total = CallCounter.new('*')
|
149
|
+
if @sum
|
150
|
+
a = open(table,'r').each_line.map do |line|
|
151
|
+
line.split(/\s+/)[column-1]
|
152
|
+
end.sort.reverse
|
153
|
+
@paths = Hash[ a.map{|x| [x, /^#{x.sub(/\/$/,'')}($|\/)/] } ]
|
154
|
+
end
|
156
155
|
end
|
157
156
|
|
158
|
-
attr_reader :stat, :
|
157
|
+
attr_reader :stat, :total
|
159
158
|
|
160
159
|
def parse(a)
|
161
160
|
@fd2path = ["stdin", "stdout", "stderr"]
|
@@ -164,101 +163,108 @@ module StraceLog
|
|
164
163
|
end
|
165
164
|
end
|
166
165
|
|
167
|
-
def
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
166
|
+
def get_fd(arg)
|
167
|
+
if /([-\d]+)(<.*>)?/ =~ arg
|
168
|
+
x = $1.to_i
|
169
|
+
return x
|
170
|
+
else
|
171
|
+
raise
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def stat_call(call)
|
176
|
+
path = nil
|
177
|
+
|
178
|
+
case call.func
|
172
179
|
|
173
|
-
|
180
|
+
when /^(execve|l?stat|(read|un)?link|getc?wd|access|mkdir|mknod|chmod|chown)$/
|
181
|
+
path = call.args[0]
|
174
182
|
|
175
|
-
when /^
|
176
|
-
path =
|
177
|
-
|
178
|
-
|
179
|
-
fd = pc.ret.to_i
|
183
|
+
when /^open$/
|
184
|
+
path = call.args[0]
|
185
|
+
if call.ret != "-1"
|
186
|
+
fd = call.ret.to_i
|
180
187
|
@fd2path[fd] = path
|
181
188
|
end
|
182
189
|
|
183
|
-
when /^
|
184
|
-
|
185
|
-
|
190
|
+
when /^connect$/
|
191
|
+
fd = get_fd(call.args[0])
|
192
|
+
@fd2path[fd] = path = "socket"
|
186
193
|
|
187
|
-
when /^
|
188
|
-
fd =
|
189
|
-
|
190
|
-
if
|
194
|
+
when /^close$/
|
195
|
+
fd = get_fd(call.args[0])
|
196
|
+
path = @fd2path[fd]
|
197
|
+
if call.ret != "-1"
|
191
198
|
@fd2path[fd] = nil
|
192
199
|
end
|
193
200
|
|
201
|
+
when /^(readv?|writev?)$/
|
202
|
+
call.set_size
|
203
|
+
fd = get_fd(call.args[0])
|
204
|
+
path = @fd2path[fd]
|
205
|
+
|
206
|
+
when /^(fstat|fchmod|[fl]chown|lseek|ioctl|fcntl|getdents|sendto|recvmsg)$/
|
207
|
+
fd = get_fd(call.args[0])
|
208
|
+
path = @fd2path[fd]
|
209
|
+
|
194
210
|
when /^rename$/
|
195
|
-
|
196
|
-
|
197
|
-
rename(pc)
|
211
|
+
rename(call)
|
212
|
+
path = call.args[1]
|
198
213
|
|
199
214
|
when /^dup[23]?$/
|
200
|
-
fd =
|
201
|
-
|
202
|
-
if
|
203
|
-
fd2 =
|
215
|
+
fd = get_fd(call.args[0])
|
216
|
+
path = @fd2path[fd]
|
217
|
+
if call.ret != "-1"
|
218
|
+
fd2 = call.ret.to_i
|
204
219
|
@fd2path[fd2] = @fd2path[fd]
|
205
220
|
end
|
206
221
|
|
207
222
|
when /^mmap$/
|
208
|
-
fd =
|
209
|
-
if fd >= 0
|
210
|
-
count_fd(fd,pc)
|
211
|
-
end
|
212
|
-
|
213
|
-
when /^connect$/
|
214
|
-
fd = pc.args[0].to_i
|
215
|
-
@fd2path[fd] = path = pc.args[1]
|
216
|
-
count_path(path,pc)
|
223
|
+
fd = get_fd(call.args[4])
|
224
|
+
path = @fd2path[fd] if fd >= 0
|
217
225
|
|
226
|
+
when NilClass
|
227
|
+
return
|
218
228
|
end
|
219
|
-
end
|
220
229
|
|
221
|
-
|
222
|
-
path = @fd2path[fd]
|
223
|
-
count_path(path,pc)
|
224
|
-
end
|
225
|
-
|
226
|
-
def count_path(path,pc)
|
227
|
-
io_counter(path).count(pc)
|
228
|
-
end
|
230
|
+
@total.count(call)
|
229
231
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
232
|
+
if path
|
233
|
+
if @sum
|
234
|
+
realpath = File.exist?(path) ? Pathname.new(path).realdirpath.to_s : path
|
235
|
+
@paths.each do |mp,re|
|
236
|
+
if re =~ realpath
|
237
|
+
(@stat[mp] ||= CallCounter.new(mp)).count(call)
|
238
|
+
return
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
(@stat[path] ||= CallCounter.new(path)).count(call)
|
243
|
+
end
|
236
244
|
end
|
237
245
|
|
238
|
-
def rename(
|
239
|
-
if
|
240
|
-
oldpath =
|
241
|
-
newpath =
|
242
|
-
ioc = @stat[newpath] = @stat[oldpath]
|
246
|
+
def rename(call)
|
247
|
+
if call.ret != "-1"
|
248
|
+
oldpath = call.args[0]
|
249
|
+
newpath = call.args[1]
|
250
|
+
ioc = @stat[newpath] = (@stat[oldpath] ||= CallCounter.new(oldpath))
|
243
251
|
ioc.rename_as(newpath)
|
244
252
|
@stat.delete(oldpath)
|
245
253
|
end
|
246
254
|
end
|
247
255
|
|
248
|
-
def
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
@spent.each do |m,t|
|
256
|
-
Kernel.printf " %s: %.6f,\n",m,t
|
256
|
+
def write(file=nil)
|
257
|
+
block = proc do |w|
|
258
|
+
w << ["path","syscall","calls","errors","time","size"]
|
259
|
+
@total.each{|item| w << item}
|
260
|
+
@stat.each do |path,cntr|
|
261
|
+
cntr.each{|item| w << item}
|
262
|
+
end
|
257
263
|
end
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
264
|
+
if file
|
265
|
+
CSV.open(file,'w',&block)
|
266
|
+
else
|
267
|
+
CSV.instance(&block)
|
262
268
|
end
|
263
269
|
end
|
264
270
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strace_log
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro TANAKA
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,10 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: '0'
|
74
74
|
requirements: []
|
75
|
-
|
76
|
-
rubygems_version: 2.4.5
|
75
|
+
rubygems_version: 3.0.1
|
77
76
|
signing_key:
|
78
77
|
specification_version: 4
|
79
78
|
summary: Parse strace log
|
80
79
|
test_files: []
|
81
|
-
has_rdoc:
|