scout_rails 1.0.5.pre → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.markdown +4 -1
- data/lib/scout_rails/agent/logging.rb +44 -0
- data/lib/scout_rails/agent/reporting.rb +97 -0
- data/lib/scout_rails/agent.rb +0 -111
- data/lib/scout_rails/config.rb +21 -13
- data/lib/scout_rails/layaway.rb +27 -19
- data/lib/scout_rails/layaway_file.rb +3 -1
- data/lib/scout_rails/version.rb +1 -1
- data/lib/scout_rails.rb +2 -0
- metadata +7 -5
data/CHANGELOG.markdown
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
# 1.0.5
|
1
|
+
# 1.0.5
|
2
2
|
|
3
3
|
* Removing duplicate Enviornment#unicorn? method
|
4
4
|
* Removing logging when not instrumenting unscoped method (confusing - looks like an error)
|
5
5
|
* Recording ActiveRecord exists queries as MODEL#exists vs. SQL#UNKNOWN
|
6
|
+
* Handling log_level config option and defaulting to 'info' instead of 'debug'
|
7
|
+
* Not crashing the app when log file isn't writeable
|
8
|
+
* Handling the :reset directive. Resets the metric_lookup when provided.
|
6
9
|
|
7
10
|
# 1.0.4
|
8
11
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Contains methods specific to logging (initializing the log file, applying the log level, applying the log format, etc.)
|
2
|
+
module ScoutRails
|
3
|
+
class Agent
|
4
|
+
module Logging
|
5
|
+
def log_path
|
6
|
+
"#{environment.root}/log"
|
7
|
+
end
|
8
|
+
|
9
|
+
def init_logger
|
10
|
+
@log_file = "#{log_path}/scout_rails.log"
|
11
|
+
begin
|
12
|
+
@logger = Logger.new(@log_file)
|
13
|
+
@logger.level = log_level
|
14
|
+
apply_log_format
|
15
|
+
rescue Exception => e
|
16
|
+
@logger = Logger.new(STDOUT)
|
17
|
+
apply_log_format
|
18
|
+
@logger.error "Unable to access log file: #{e.message}"
|
19
|
+
end
|
20
|
+
@logger
|
21
|
+
end
|
22
|
+
|
23
|
+
def apply_log_format
|
24
|
+
def logger.format_message(severity, timestamp, progname, msg)
|
25
|
+
# since STDOUT isn't exclusive like the scout_rails.log file, apply a prefix.
|
26
|
+
prefix = @logdev.dev == STDOUT ? "scout_rails " : ''
|
27
|
+
prefix + "[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{Socket.gethostname} (#{$$})] #{severity} : #{msg}\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def log_level
|
32
|
+
case config.settings['log_level'].downcase
|
33
|
+
when "debug" then Logger::DEBUG
|
34
|
+
when "info" then Logger::INFO
|
35
|
+
when "warn" then Logger::WARN
|
36
|
+
when "error" then Logger::ERROR
|
37
|
+
when "fatal" then Logger::FATAL
|
38
|
+
else Logger::INFO
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # module Logging
|
42
|
+
include Logging
|
43
|
+
end # class Agent
|
44
|
+
end # moudle ScoutRails
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# Methods related to sending metrics to scoutapp.com.
|
2
|
+
module ScoutRails
|
3
|
+
class Agent
|
4
|
+
module Reporting
|
5
|
+
# Called in the worker thread. Merges in-memory metrics w/those on disk and reports metrics
|
6
|
+
# to the server.
|
7
|
+
def process_metrics
|
8
|
+
logger.debug "Processing metrics"
|
9
|
+
run_samplers
|
10
|
+
metrics = layaway.deposit_and_deliver
|
11
|
+
if metrics.any?
|
12
|
+
add_metric_ids(metrics)
|
13
|
+
# for debugging, count the total number of requests
|
14
|
+
controller_count = 0
|
15
|
+
metrics.each do |meta,stats|
|
16
|
+
if meta.metric_name =~ /\AController/
|
17
|
+
controller_count += stats.call_count
|
18
|
+
end
|
19
|
+
end
|
20
|
+
logger.debug "#{config.settings['name']} Delivering metrics for #{controller_count} requests."
|
21
|
+
response = post( checkin_uri,
|
22
|
+
Marshal.dump(:metrics => metrics, :sample => store.sample),
|
23
|
+
"Content-Type" => "application/json" )
|
24
|
+
if response and response.is_a?(Net::HTTPSuccess)
|
25
|
+
directives = Marshal.load(response.body)
|
26
|
+
self.metric_lookup.merge!(directives[:metric_lookup])
|
27
|
+
if directives[:reset]
|
28
|
+
logger.info "Resetting metric_lookup."
|
29
|
+
self.metric_lookup = Hash.new
|
30
|
+
end
|
31
|
+
store.transaction_sample_lock.synchronize do
|
32
|
+
store.sample = nil
|
33
|
+
end
|
34
|
+
logger.debug "Metric Cache Size: #{metric_lookup.size}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
logger.info "Error on checkin to #{checkin_uri.to_s}"
|
39
|
+
logger.info $!.message
|
40
|
+
logger.debug $!.backtrace
|
41
|
+
end
|
42
|
+
|
43
|
+
# Before reporting, lookup metric_id for each MetricMeta. This speeds up
|
44
|
+
# reporting on the server-side.
|
45
|
+
def add_metric_ids(metrics)
|
46
|
+
metrics.each do |meta,stats|
|
47
|
+
if metric_id = metric_lookup[meta]
|
48
|
+
meta.metric_id = metric_id
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def checkin_uri
|
54
|
+
URI.parse("http://#{config.settings['host']}/app/#{config.settings['key']}/checkin.scout?name=#{CGI.escape(config.settings['name'])}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def post(url, body, headers = Hash.new)
|
58
|
+
response = nil
|
59
|
+
request(url) do |connection|
|
60
|
+
post = Net::HTTP::Post.new( url.path +
|
61
|
+
(url.query ? ('?' + url.query) : ''),
|
62
|
+
HTTP_HEADERS.merge(headers) )
|
63
|
+
post.body = body
|
64
|
+
response=connection.request(post)
|
65
|
+
end
|
66
|
+
response
|
67
|
+
end
|
68
|
+
|
69
|
+
def request(url, &connector)
|
70
|
+
response = nil
|
71
|
+
response = http(url).start(&connector)
|
72
|
+
logger.debug "got response: #{response.inspect}"
|
73
|
+
case response
|
74
|
+
when Net::HTTPSuccess, Net::HTTPNotModified
|
75
|
+
logger.debug "/checkin OK"
|
76
|
+
when Net::HTTPBadRequest
|
77
|
+
logger.warn "/checkin FAILED: The Account Key [#{config.settings['key']}] is invalid."
|
78
|
+
else
|
79
|
+
logger.debug "/checkin FAILED: #{response.inspect}"
|
80
|
+
end
|
81
|
+
rescue Exception
|
82
|
+
logger.debug "Exception sending request to server: #{$!.message}"
|
83
|
+
ensure
|
84
|
+
response
|
85
|
+
end
|
86
|
+
|
87
|
+
# Take care of the http proxy, if specified in config.
|
88
|
+
# Given a blank string, the proxy_uri URI instance's host/port/user/pass will be nil.
|
89
|
+
# Net::HTTP::Proxy returns a regular Net::HTTP class if the first argument (host) is nil.
|
90
|
+
def http(url)
|
91
|
+
proxy_uri = URI.parse(config.settings['proxy'].to_s)
|
92
|
+
Net::HTTP::Proxy(proxy_uri.host,proxy_uri.port,proxy_uri.user,proxy_uri.password).new(url.host, url.port)
|
93
|
+
end
|
94
|
+
end # module Reporting
|
95
|
+
include Reporting
|
96
|
+
end # class Agent
|
97
|
+
end # module ScoutRails
|
data/lib/scout_rails/agent.rb
CHANGED
@@ -7,7 +7,6 @@ module ScoutRails
|
|
7
7
|
class Agent
|
8
8
|
# Headers passed up with all API requests.
|
9
9
|
HTTP_HEADERS = { "Agent-Hostname" => Socket.gethostname }
|
10
|
-
DEFAULT_HOST = 'scoutapp.com'
|
11
10
|
# see self.instance
|
12
11
|
@@instance = nil
|
13
12
|
|
@@ -93,16 +92,6 @@ module ScoutRails
|
|
93
92
|
File.expand_path(File.join("..","..",".."), __FILE__)
|
94
93
|
end
|
95
94
|
|
96
|
-
def init_logger
|
97
|
-
@log_file = "#{log_path}/scout_rails.log"
|
98
|
-
@logger = Logger.new(@log_file)
|
99
|
-
@logger.level = Logger::DEBUG
|
100
|
-
def logger.format_message(severity, timestamp, progname, msg)
|
101
|
-
prefix = "[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{Socket.gethostname} (#{$$})] #{severity} : #{msg}\n"
|
102
|
-
end
|
103
|
-
@logger
|
104
|
-
end
|
105
|
-
|
106
95
|
# The worker thread will automatically start UNLESS:
|
107
96
|
# * A supported application server isn't detected (example: running via Rails console)
|
108
97
|
# * A supported application server is detected, but it forks (Passenger). In this case,
|
@@ -129,10 +118,6 @@ module ScoutRails
|
|
129
118
|
end
|
130
119
|
end
|
131
120
|
|
132
|
-
def log_path
|
133
|
-
"#{environment.root}/log"
|
134
|
-
end
|
135
|
-
|
136
121
|
# in seconds, time between when the worker thread wakes up and runs.
|
137
122
|
def period
|
138
123
|
60
|
@@ -167,26 +152,6 @@ module ScoutRails
|
|
167
152
|
logger.debug "Done creating worker thread."
|
168
153
|
end
|
169
154
|
|
170
|
-
# Writes each payload to a file for auditing.
|
171
|
-
def write_to_file(object)
|
172
|
-
logger.debug "Writing to file"
|
173
|
-
full_path = Pathname.new(RAILS_ROOT+'/log/audit/scout')
|
174
|
-
( full_path +
|
175
|
-
"#{Time.now.strftime('%Y-%m-%d_%H:%M:%S')}.json" ).open("w") do |f|
|
176
|
-
f.puts object.to_json
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# Before reporting, lookup metric_id for each MetricMeta. This speeds up
|
181
|
-
# reporting on the server-side.
|
182
|
-
def add_metric_ids(metrics)
|
183
|
-
metrics.each do |meta,stats|
|
184
|
-
if metric_id = metric_lookup[meta]
|
185
|
-
meta.metric_id = metric_id
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
155
|
# Called from #process_metrics, which is run via the worker thread.
|
191
156
|
def run_samplers
|
192
157
|
begin
|
@@ -210,82 +175,6 @@ module ScoutRails
|
|
210
175
|
end
|
211
176
|
end
|
212
177
|
|
213
|
-
# Called in the worker thread. Merges in-memory metrics w/those on disk and reports metrics
|
214
|
-
# to the server.
|
215
|
-
def process_metrics
|
216
|
-
logger.debug "Processing metrics"
|
217
|
-
run_samplers
|
218
|
-
metrics = layaway.deposit_and_deliver
|
219
|
-
if metrics.any?
|
220
|
-
add_metric_ids(metrics)
|
221
|
-
# for debugging, count the total number of requests
|
222
|
-
controller_count = 0
|
223
|
-
metrics.each do |meta,stats|
|
224
|
-
if meta.metric_name =~ /\AController/
|
225
|
-
controller_count += stats.call_count
|
226
|
-
end
|
227
|
-
end
|
228
|
-
logger.debug "#{config.settings['name']} Delivering metrics for #{controller_count} requests."
|
229
|
-
response = post( checkin_uri,
|
230
|
-
Marshal.dump(:metrics => metrics, :sample => store.sample),
|
231
|
-
"Content-Type" => "application/json" )
|
232
|
-
if response and response.is_a?(Net::HTTPSuccess)
|
233
|
-
directives = Marshal.load(response.body)
|
234
|
-
self.metric_lookup.merge!(directives[:metric_lookup])
|
235
|
-
store.transaction_sample_lock.synchronize do
|
236
|
-
store.sample = nil
|
237
|
-
end
|
238
|
-
logger.debug "Metric Cache Size: #{metric_lookup.size}"
|
239
|
-
end
|
240
|
-
end
|
241
|
-
rescue
|
242
|
-
logger.info "Error on checkin to #{checkin_uri.to_s}"
|
243
|
-
logger.info $!.message
|
244
|
-
logger.debug $!.backtrace
|
245
|
-
end
|
246
|
-
|
247
|
-
def checkin_uri
|
248
|
-
URI.parse("http://#{config.settings['host'] || DEFAULT_HOST}/app/#{config.settings['key']}/checkin.scout?name=#{CGI.escape(config.settings['name'])}")
|
249
|
-
end
|
250
|
-
|
251
|
-
def post(url, body, headers = Hash.new)
|
252
|
-
response = nil
|
253
|
-
request(url) do |connection|
|
254
|
-
post = Net::HTTP::Post.new( url.path +
|
255
|
-
(url.query ? ('?' + url.query) : ''),
|
256
|
-
HTTP_HEADERS.merge(headers) )
|
257
|
-
post.body = body
|
258
|
-
response=connection.request(post)
|
259
|
-
end
|
260
|
-
response
|
261
|
-
end
|
262
|
-
|
263
|
-
def request(url, &connector)
|
264
|
-
response = nil
|
265
|
-
response = http(url).start(&connector)
|
266
|
-
logger.debug "got response: #{response.inspect}"
|
267
|
-
case response
|
268
|
-
when Net::HTTPSuccess, Net::HTTPNotModified
|
269
|
-
logger.debug "/checkin OK"
|
270
|
-
when Net::HTTPBadRequest
|
271
|
-
logger.warn "/checkin FAILED: The Account Key [#{config.settings['key']}] is invalid."
|
272
|
-
else
|
273
|
-
logger.debug "/checkin FAILED: #{response.inspect}"
|
274
|
-
end
|
275
|
-
rescue Exception
|
276
|
-
logger.debug "Exception sending request to server: #{$!.message}"
|
277
|
-
ensure
|
278
|
-
response
|
279
|
-
end
|
280
|
-
|
281
|
-
# Take care of the http proxy, if specified in config.
|
282
|
-
# Given a blank string, the proxy_uri URI instance's host/port/user/pass will be nil.
|
283
|
-
# Net::HTTP::Proxy returns a regular Net::HTTP class if the first argument (host) is nil.
|
284
|
-
def http(url)
|
285
|
-
proxy_uri = URI.parse(config.settings['proxy'].to_s)
|
286
|
-
Net::HTTP::Proxy(proxy_uri.host,proxy_uri.port,proxy_uri.user,proxy_uri.password).new(url.host, url.port)
|
287
|
-
end
|
288
|
-
|
289
178
|
# Loads the instrumention logic.
|
290
179
|
def load_instruments
|
291
180
|
case environment.framework
|
data/lib/scout_rails/config.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module ScoutRails
|
2
|
-
class Config
|
2
|
+
class Config
|
3
|
+
DEFAULTS = {
|
4
|
+
'host' => 'scoutapp.com',
|
5
|
+
'log_level' => 'info'
|
6
|
+
}
|
7
|
+
|
3
8
|
def initialize(config_path = nil)
|
4
9
|
@config_path = config_path
|
5
10
|
end
|
@@ -18,17 +23,20 @@ module ScoutRails
|
|
18
23
|
end
|
19
24
|
|
20
25
|
def load_file
|
21
|
-
|
22
|
-
|
26
|
+
begin
|
27
|
+
if !File.exist?(config_file)
|
28
|
+
ScoutRails::Agent.instance.logger.warn "No config file found at [#{config_file}]."
|
29
|
+
@settings = {}
|
30
|
+
else
|
31
|
+
@settings = YAML.load(ERB.new(File.read(config_file)).result(binding))[ScoutRails::Agent.instance.environment.env] || {}
|
32
|
+
end
|
33
|
+
rescue Exception => e
|
34
|
+
ScoutRails::Agent.instance.logger.warn "Unable to load the config file."
|
35
|
+
ScoutRails::Agent.instance.logger.warn e.message
|
36
|
+
ScoutRails::Agent.instance.logger.warn e.backtrace
|
23
37
|
@settings = {}
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
rescue Exception => e
|
28
|
-
ScoutRails::Agent.instance.logger.warn "Unable to load the config file."
|
29
|
-
ScoutRails::Agent.instance.logger.warn e.message
|
30
|
-
ScoutRails::Agent.instance.logger.warn e.backtrace
|
31
|
-
@settings = {}
|
38
|
+
end
|
39
|
+
@settings = DEFAULTS.merge(@settings)
|
32
40
|
end
|
33
|
-
end
|
34
|
-
end
|
41
|
+
end # Config
|
42
|
+
end # ScoutRails
|
data/lib/scout_rails/layaway.rb
CHANGED
@@ -12,19 +12,13 @@ class ScoutRails::Layaway
|
|
12
12
|
|
13
13
|
def deposit_and_deliver
|
14
14
|
new_data = ScoutRails::Agent.instance.store.metric_hash
|
15
|
-
|
16
|
-
new_data.each do |meta,stats|
|
17
|
-
if meta.metric_name =~ /\AController/
|
18
|
-
controller_count += stats.call_count
|
19
|
-
end
|
20
|
-
end
|
21
|
-
ScoutRails::Agent.instance.logger.debug "Depositing #{controller_count} requests into #{Time.at(slot).strftime("%m/%d/%y %H:%M:%S %z")} slot."
|
22
|
-
|
15
|
+
log_deposited_requests(new_data)
|
23
16
|
to_deliver = {}
|
24
17
|
file.read_and_write do |old_data|
|
25
18
|
old_data ||= Hash.new
|
26
19
|
# merge data
|
27
|
-
# if the
|
20
|
+
# if (1) there's data in the file and (2) there isn't any data yet for the current minute, this means we've
|
21
|
+
# collected all metrics for the previous slots and we're ready to deliver.
|
28
22
|
if old_data.any? and old_data[slot].nil?
|
29
23
|
to_deliver = old_data
|
30
24
|
old_data = Hash.new
|
@@ -34,16 +28,7 @@ class ScoutRails::Layaway
|
|
34
28
|
ScoutRails::Agent.instance.logger.debug "There is no data in the layaway file to deliver."
|
35
29
|
end
|
36
30
|
old_data[slot]=ScoutRails::Agent.instance.store.merge_data_and_clear(old_data[slot] || Hash.new)
|
37
|
-
|
38
|
-
old_data.each do |k,v|
|
39
|
-
controller_count = 0
|
40
|
-
new_data.each do |meta,stats|
|
41
|
-
if meta.metric_name =~ /\AController/
|
42
|
-
controller_count += stats.call_count
|
43
|
-
end
|
44
|
-
end
|
45
|
-
ScoutRails::Agent.instance.logger.debug "#{Time.at(k).strftime("%m/%d/%y %H:%M:%S %z")} => #{controller_count} requests"
|
46
|
-
end
|
31
|
+
log_saved_requests(old_data,new_data)
|
47
32
|
old_data
|
48
33
|
end
|
49
34
|
to_deliver.any? ? validate_data(to_deliver) : {}
|
@@ -73,4 +58,27 @@ class ScoutRails::Layaway
|
|
73
58
|
t -= t.sec
|
74
59
|
t.to_i
|
75
60
|
end
|
61
|
+
|
62
|
+
def log_deposited_requests(new_data)
|
63
|
+
controller_count = 0
|
64
|
+
new_data.each do |meta,stats|
|
65
|
+
if meta.metric_name =~ /\AController/
|
66
|
+
controller_count += stats.call_count
|
67
|
+
end
|
68
|
+
end
|
69
|
+
ScoutRails::Agent.instance.logger.debug "Depositing #{controller_count} requests into #{Time.at(slot).strftime("%m/%d/%y %H:%M:%S %z")} slot."
|
70
|
+
end
|
71
|
+
|
72
|
+
def log_saved_requests(old_data,new_data)
|
73
|
+
ScoutRails::Agent.instance.logger.debug "Saving the following #{old_data.size} time slots locally:"
|
74
|
+
old_data.each do |k,v|
|
75
|
+
controller_count = 0
|
76
|
+
new_data.each do |meta,stats|
|
77
|
+
if meta.metric_name =~ /\AController/
|
78
|
+
controller_count += stats.call_count
|
79
|
+
end
|
80
|
+
end
|
81
|
+
ScoutRails::Agent.instance.logger.debug "#{Time.at(k).strftime("%m/%d/%y %H:%M:%S %z")} => #{controller_count} requests"
|
82
|
+
end
|
83
|
+
end
|
76
84
|
end
|
@@ -35,8 +35,10 @@ class ScoutRails::LayawayFile
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
rescue Errno::ENOENT, Exception => e
|
38
|
-
ScoutRails::Agent.instance.logger.error(e.message)
|
38
|
+
ScoutRails::Agent.instance.logger.error("Unable to access the layaway file [#{e.message}]. The user running the app must have read+write access.")
|
39
39
|
ScoutRails::Agent.instance.logger.debug(e.backtrace.split("\n"))
|
40
|
+
# ensure the in-memory metric hash is cleared so data doesn't continue to accumulate.
|
41
|
+
ScoutRails::Agent.instance.store.metric_hash = {}
|
40
42
|
end
|
41
43
|
|
42
44
|
def get_data(f)
|
data/lib/scout_rails/version.rb
CHANGED
data/lib/scout_rails.rb
CHANGED
@@ -5,6 +5,8 @@ require 'set'
|
|
5
5
|
require 'net/http'
|
6
6
|
require File.expand_path('../scout_rails/version.rb', __FILE__)
|
7
7
|
require File.expand_path('../scout_rails/agent.rb', __FILE__)
|
8
|
+
require File.expand_path('../scout_rails/agent/logging.rb', __FILE__)
|
9
|
+
require File.expand_path('../scout_rails/agent/reporting.rb', __FILE__)
|
8
10
|
require File.expand_path('../scout_rails/layaway.rb', __FILE__)
|
9
11
|
require File.expand_path('../scout_rails/layaway_file.rb', __FILE__)
|
10
12
|
require File.expand_path('../scout_rails/config.rb', __FILE__)
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.5
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.5
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Derek Haynes
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-10-
|
13
|
+
date: 2012-10-25 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: Monitors a Ruby on Rails application and reports detailed metrics on
|
16
16
|
performance to Scout, a hosted monitoring service.
|
@@ -28,6 +28,8 @@ files:
|
|
28
28
|
- Rakefile
|
29
29
|
- lib/scout_rails.rb
|
30
30
|
- lib/scout_rails/agent.rb
|
31
|
+
- lib/scout_rails/agent/logging.rb
|
32
|
+
- lib/scout_rails/agent/reporting.rb
|
31
33
|
- lib/scout_rails/config.rb
|
32
34
|
- lib/scout_rails/environment.rb
|
33
35
|
- lib/scout_rails/instruments/active_record_instruments.rb
|
@@ -64,9 +66,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
64
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
67
|
none: false
|
66
68
|
requirements:
|
67
|
-
- - ! '
|
69
|
+
- - ! '>='
|
68
70
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
71
|
+
version: '0'
|
70
72
|
requirements: []
|
71
73
|
rubyforge_project: scout_rails
|
72
74
|
rubygems_version: 1.8.10
|