summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Barbosa Alexandre <dbalexandre@gmail.com>2016-01-26 00:04:09 +0000
committerRobert Speicher <rspeicher@gmail.com>2016-01-25 16:10:20 -0800
commit6881ba0e796fe22dd1d47bd1a7d42e532f18077a (patch)
tree654a99b8493c544fff34f6a52d2d6fa2b532b5e9
parent65d85a4403f6e5899f793acb53c64d7ad5ba7fdd (diff)
downloadgitlab-ce-6881ba0e796fe22dd1d47bd1a7d42e532f18077a.tar.gz
Merge branch 'instrumentation-signature' into 'master'
Correct arity for instrumented methods w/o args This should fix the problem of imports not working. See https://gitlab.com/gitlab-org/gitlab-ce/issues/12450#note_3380730 for the details/context of these changes. See merge request !2602
-rw-r--r--lib/gitlab/metrics/instrumentation.rb22
-rw-r--r--spec/lib/gitlab/metrics/instrumentation_spec.rb10
2 files changed, 29 insertions, 3 deletions
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index d9fce2e6758..face1921d2e 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -106,20 +106,36 @@ module Gitlab
if type == :instance
target = mod
label = "#{mod.name}##{name}"
+ method = mod.instance_method(name)
else
target = mod.singleton_class
label = "#{mod.name}.#{name}"
+ method = mod.method(name)
+ end
+
+ # Some code out there (e.g. the "state_machine" Gem) checks the arity of
+ # a method to make sure it only passes arguments when the method expects
+ # any. If we were to always overwrite a method to take an `*args`
+ # signature this would break things. As a result we'll make sure the
+ # generated method _only_ accepts regular arguments if the underlying
+ # method also accepts them.
+ if method.arity == 0
+ args_signature = '&block'
+ else
+ args_signature = '*args, &block'
end
+ send_signature = "__send__(#{alias_name.inspect}, #{args_signature})"
+
target.class_eval <<-EOF, __FILE__, __LINE__ + 1
alias_method #{alias_name.inspect}, #{name.inspect}
- def #{name}(*args, &block)
+ def #{name}(#{args_signature})
trans = Gitlab::Metrics::Instrumentation.transaction
if trans
start = Time.now
- retval = __send__(#{alias_name.inspect}, *args, &block)
+ retval = #{send_signature}
duration = (Time.now - start) * 1000.0
if duration >= Gitlab::Metrics.method_call_threshold
@@ -132,7 +148,7 @@ module Gitlab
retval
else
- __send__(#{alias_name.inspect}, *args, &block)
+ #{send_signature}
end
end
EOF
diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb
index 2a37cd40dde..ad4290c43bb 100644
--- a/spec/lib/gitlab/metrics/instrumentation_spec.rb
+++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb
@@ -66,6 +66,16 @@ describe Gitlab::Metrics::Instrumentation do
@dummy.foo
end
+
+ it 'generates a method with the correct arity when using methods without arguments' do
+ dummy = Class.new do
+ def self.test; end
+ end
+
+ described_class.instrument_method(dummy, :test)
+
+ expect(dummy.method(:test).arity).to eq(0)
+ end
end
describe 'with metrics disabled' do