Repository: newrelic/newrelic-ruby-agent (Ruby)

Issue:
"Unable to determine source code info" on instrumenting private methods
## Description

When using add_method_tracer on a private method, this warning is printed to the newrelic log:


```
[2022-11-04 13:54:24 +0000 M1MBP.local (29101)] WARN : Unable to determine source code info for 'Foo', method 'secret_method' - NameError: undefined method `secret_method' for class `#<Class:Foo>'

          klass.method(method_name)
               ^^^^^^^
```

## Expected Behavior
No warning is printed.

## Steps to Reproduce

```ruby
class Foo
  include NewRelic::Agent::MethodTracer

  private

  def secret_method
  end
  add_method_tracer :secret_method
end
```

## Your Environment
newrelic 8.12.0
ruby 3.1.2

## Additional context

instance_methods here - 
https://github.com/newrelic/newrelic-ruby-agent/blob/9a8d24072f84ac971302220ae2473a49d85678ed/lib/new_relic/agent/method_tracer_helpers.rb#L109-L114 doesn't include private methods. Perhaps it should be `(klass.instance_methods + klass.private_instance_methods).include?(method_name)` ?



Discussion:
https://issues.newrelic.com/browse/NEWRELIC-5063
Hello @jdelStrother! 
Thanks for letting us bringing this to our attention. 
Also, thanks for the suggested fix! That seemed to do the trick #1593 



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56539bf02a..ab05d7a6cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,15 @@
 
     Unicorn, Rainbows, or FastCGI web applications using Rack v3.0.0 may previously have had the "dispatcher" value incorrectly reported as "Webrick" instead of "Unicorn", "Rainbows", or "FastCGI". This issue has now been addressed. [PR#1585](https://github.com/newrelic/newrelic-ruby-agent/pull/1585)
 
+  * **Bugfix: add_method_tracer fails to record code level metric attributes on private methods**
+
+    When using add_method_tracer on a private method, the agent was unable to record code level metrics for the method. This resulted in the following being logged to the newrelic_agent.log file.
+    ```
+    WARN : Unable to determine source code info for 'Example', method 'private_method' - NameError: undefined method 'private_method' for class '#<Class:Example>'
+    ```
+    Thanks to @jdelStrother for bringing this issue to our attention and suggesting a fix! [PR#1593](https://github.com/newrelic/newrelic-ruby-agent/pull/1593)
+
+
   * **Bugfix: Category is a required keyword arg for NewRelic::Agent::Tracer.in_transaction**
 
     When support for Ruby 2.0 was dropped in version 8.0.0 of the agent, the agent API methods were updated to use the required keyword argument feature built into Ruby, rather than manually raising ArgumentErrors. The API method `NewRelic::Agent::Tracer.in_transaction` removed the ArgumentError raised by the agent, but did not update the method arguments to identify category as a required keyword argument. This is now resolved. Thank you to @tatzsuzuki for bringing this to our attention. [PR#](https://github.com/newrelic/newrelic-ruby-agent/pull/1587)
diff --git a/lib/new_relic/agent/method_tracer_helpers.rb b/lib/new_relic/agent/method_tracer_helpers.rb
index a86f49bdbd..23fd22ad4d 100644
--- a/lib/new_relic/agent/method_tracer_helpers.rb
+++ b/lib/new_relic/agent/method_tracer_helpers.rb
@@ -106,7 +106,7 @@ def namespace_and_location(object, method_name)
         klass = object.singleton_class? ? klassify_singleton(object) : object
         name = klass.name || '(Anonymous)'
         is_class_method = false
-        method = if klass.instance_methods.include?(method_name)
+        method = if (klass.instance_methods + klass.private_instance_methods).include?(method_name)
           klass.instance_method(method_name)
         else
           is_class_method = true


Test patch:
diff --git a/test/new_relic/agent/method_tracer_helpers_test.rb b/test/new_relic/agent/method_tracer_helpers_test.rb
index afcc152ad8..718736d0ec 100644
--- a/test/new_relic/agent/method_tracer_helpers_test.rb
+++ b/test/new_relic/agent/method_tracer_helpers_test.rb
@@ -8,6 +8,8 @@ module ::The
   class Example
     def self.class_method; end
     def instance_method; end
+    private # rubocop:disable Layout/EmptyLinesAroundAccessModifier
+    def private_method; end
   end
 end
 
@@ -83,6 +85,18 @@ def test_provides_accurate_info_for_an_instance_method
     end
   end
 
+  def test_provides_accurate_info_for_an_instance_method
+    with_config(:'code_level_metrics.enabled' => true) do
+      info = NewRelic::Agent::MethodTracerHelpers.code_information(::The::Example, :private_method)
+
+      assert_equal({filepath: __FILE__,
+        lineno: The::Example.instance_method(:private_method).source_location.last,
+        function: 'private_method',
+        namespace: 'The::Example'},
+        info)
+    end
+  end
+
   def test_provides_accurate_info_for_an_anonymous_instance_method
     with_config(:'code_level_metrics.enabled' => true) do
       klass = Class.new do