/
base.rb
162 lines (137 loc) · 4.23 KB
/
base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
module Mri
module Instrumentation
module Runner
class Base
attr_reader :run_with,
:result
def initialize( replace = false, &block )
@probes = []
@replace = replace
instance_eval( &block ) if block_given?
end
# Instrument with the given probes
#
def probes( *probes )
probes.empty? ? @probes : self.probes=( probes )
end
# Attach to a given PID
#
def pid( pid = nil )
pid ? self.pid=( pid ) : @pid
end
# Run a given command
#
def command( command = nil )
command ? self.command=( command ) : @command
end
# The desired profiling strategy
#
def strategy( strategy = nil )
if strategy
self.strategy=( strategy )
else
@strategy_instance ||= setup_strategy( @strategy || :calltime )
end
end
# Run this definition
#
def run!
generate do
run_command? ? run_command : attach_to_pid
end
end
private
# Probes setter
#
def probes=( probes )
@probes = setup_probes( probes.map{|p| p.to_s } )
end
# Pid setter
#
def pid=( pid )
@run_with = :pid
@pid = pid
end
# Command setter
#
def command=( command )
@run_with = :command
@command = command
end
# Strategy setter
#
def strategy=( strategy )
@strategy = strategy
end
# Generates a dtrace script / stream
#
def generate
Tempfile.open( 'mri_instrumentation' ) do |file|
file << d_stream()
file.flush
#%x[mate #{file.path}]
cmd = "sudo dtrace -s #{file.path} #{yield}"
@result = replace? ? exec( cmd ) : %x[#{cmd}]
end
end
# Should we replace the current process ?
#
def replace?
@replace
end
# Are we running a command ?
#
def run_command?
@run_with == :command
end
# Attach to the given PID
#
def attach_to_pid
"-p #{@pid.to_s}"
end
# Run the given command
#
def run_command
"-c '#{@command}'"
end
# Convert given probe signatures to probe instances
#
def setup_probes( probes )
probes.map do |probe|
probe_group?( probe ) ? probes_grouped( probe ) : probe_definition( probe )
end.flatten
end
# Yields a probe definition from a probe
#
def probe_definition( probe )
Mri::Instrumentation.probes.detect{|p| p.name == probe }
end
# Yields all probes that's a member of the given group signature
#
def probes_grouped( group )
Mri::Instrumentation.probes.select{|p| p.group == group.to_sym }
end
# Is the given probe signature a probe group signature ?
#
def probe_group?( probe )
Mri::Instrumentation.groups.include?( probe.to_sym )
end
# Returns qualified
#
def setup_strategy( strategy )
Object.module_eval("Mri::Instrumentation::Strategy::#{strategy_const( strategy )}", __FILE__, __LINE__)
end
# Constant representation of a given strategy signature
#
def strategy_const( strategy )
strategy.to_s.gsub( /\/(.?)/ ) { "::#{$1.upcase}" }.gsub( /(?:^|_)(.)/ ) { $1.upcase }
end
# Build the D stream
#
def d_stream
Mri::Instrumentation::Strategy::Builder.new( self.strategy, self.probes ).to_s
end
end
end
end
end