stackify-ruby-apm 1.10.0 → 1.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/stackify_apm/agent.rb +0 -2
- data/lib/stackify_apm/config.rb +33 -5
- data/lib/stackify_apm/context.rb +4 -1
- data/lib/stackify_apm/context/prefix.rb +30 -0
- data/lib/stackify_apm/context/request/headers.rb +30 -0
- data/lib/stackify_apm/context_builder.rb +1 -0
- data/lib/stackify_apm/helper/database_helper.rb +39 -1
- data/lib/stackify_apm/instrumenter_helper.rb +90 -4
- data/lib/stackify_apm/logger/log_device.rb +7 -5
- data/lib/stackify_apm/logger/logger_high_version.rb +5 -1
- data/lib/stackify_apm/logger/logger_lower_version.rb +5 -1
- data/lib/stackify_apm/middleware.rb +21 -3
- data/lib/stackify_apm/normalizers/active_record.rb +16 -8
- data/lib/stackify_apm/root_info.rb +7 -1
- data/lib/stackify_apm/serializers/transactions.rb +5 -0
- data/lib/stackify_apm/span/context.rb +39 -1
- data/lib/stackify_apm/spies.rb +4 -2
- data/lib/stackify_apm/spies/action_dispatch.rb +6 -1
- data/lib/stackify_apm/spies/curb.rb +41 -20
- data/lib/stackify_apm/spies/curb/easy.rb +220 -92
- data/lib/stackify_apm/spies/curb/multi.rb +26 -12
- data/lib/stackify_apm/spies/custom_instrumenter.rb +25 -4
- data/lib/stackify_apm/spies/delayed_job.rb +49 -0
- data/lib/stackify_apm/spies/httparty.rb +45 -24
- data/lib/stackify_apm/spies/httpclient.rb +41 -20
- data/lib/stackify_apm/spies/httprb.rb +39 -18
- data/lib/stackify_apm/spies/log4r.rb +59 -0
- data/lib/stackify_apm/spies/logger.rb +116 -0
- data/lib/stackify_apm/spies/logging.rb +65 -0
- data/lib/stackify_apm/spies/net_http.rb +38 -20
- data/lib/stackify_apm/spies/redis.rb +36 -30
- data/lib/stackify_apm/spies/sequel.rb +28 -11
- data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +27 -25
- data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +27 -24
- data/lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb +18 -8
- data/lib/stackify_apm/spies/stackify_logger.rb +28 -16
- data/lib/stackify_apm/spies/yell.rb +64 -0
- data/lib/stackify_apm/util.rb +10 -9
- data/lib/stackify_apm/version.rb +1 -1
- data/stackify-ruby-apm.gemspec +1 -0
- metadata +23 -2
| @@ -14,19 +14,33 @@ module StackifyRubyAPM | |
| 14 14 | 
             
                      def self.http(urls_with_config, _multi_options = {}, &blk)
         | 
| 15 15 | 
             
                        return http_without_apm(urls_with_config, _multi_options = {}, &blk) unless StackifyRubyAPM.current_transaction
         | 
| 16 16 | 
             
                        http_without_apm(urls_with_config, _multi_options = {}) do |c, code, method|
         | 
| 17 | 
            -
                           | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 17 | 
            +
                          begin
         | 
| 18 | 
            +
                            status_code = code.zero? ? 404 : code
         | 
| 19 | 
            +
                            method = method.upcase
         | 
| 20 | 
            +
                            uri = c.url.to_s.strip
         | 
| 21 | 
            +
                            name = "#{method} #{uri}"
         | 
| 22 | 
            +
                            type = "ext.Curb.Multi.#{method}"
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                            ctx = Span::Context.new(
         | 
| 25 | 
            +
                              CATEGORY: 'Web External',
         | 
| 26 | 
            +
                              SUBCATEGORY: 'Execute',
         | 
| 27 | 
            +
                              URL: uri,
         | 
| 28 | 
            +
                              STATUS: status_code,
         | 
| 29 | 
            +
                              METHOD: method
         | 
| 30 | 
            +
                            )
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                            if StackifyRubyAPM.agent.config.prefix_enabled
         | 
| 33 | 
            +
                              ctx.update_request_body(c.post_body || "")
         | 
| 34 | 
            +
                              ctx.update_request_headers(c.headers || Hash.new)
         | 
| 35 | 
            +
                              ctx.update_response_body(c.body || "")
         | 
| 36 | 
            +
                              ctx.update_response_headers(c.proxy_headers || Hash.new)
         | 
| 37 | 
            +
                            end
         | 
| 38 | 
            +
                          rescue Exception => e
         | 
| 39 | 
            +
                            StackifyRubyAPM.agent.error "[CurbMultiSpy] Error: creating span context."
         | 
| 40 | 
            +
                            StackifyRubyAPM.agent.error "[CurbMultiSpy] #{e.inspect}"
         | 
| 41 | 
            +
                            return blk.call(c, code, method)
         | 
| 42 | 
            +
                          end
         | 
| 22 43 |  | 
| 23 | 
            -
                          ctx = Span::Context.new(
         | 
| 24 | 
            -
                            CATEGORY: 'Web External',
         | 
| 25 | 
            -
                            SUBCATEGORY: 'Execute',
         | 
| 26 | 
            -
                            URL: uri,
         | 
| 27 | 
            -
                            STATUS: status_code,
         | 
| 28 | 
            -
                            METHOD: method
         | 
| 29 | 
            -
                          )
         | 
| 30 44 | 
             
                          # Creates new span from HTTP result
         | 
| 31 45 | 
             
                          StackifyRubyAPM.span name, type, context: ctx do
         | 
| 32 46 | 
             
                            blk.call(c, code, method)
         | 
| @@ -24,16 +24,37 @@ module StackifyRubyAPM | |
| 24 24 | 
             
                  return unless !to_instrument.nil? && !to_instrument.empty? && defined?(to_instrument['instrumentation']) && (to_instrument['instrumentation'].count > 0)
         | 
| 25 25 |  | 
| 26 26 | 
             
                  to_instrument['instrumentation'].each do |custom_spy|
         | 
| 27 | 
            -
                    current_class = custom_spy['class']
         | 
| 27 | 
            +
                    current_class = defined?(custom_spy['class']) ? custom_spy['class'] : nil
         | 
| 28 | 
            +
                    current_module = defined?(custom_spy['module']) ? custom_spy['module'] : nil
         | 
| 28 29 | 
             
                    current_method = custom_spy['method']
         | 
| 29 30 | 
             
                    tracked_func = custom_spy['trackedFunction']
         | 
| 30 31 | 
             
                    tracked_func_name = defined?(custom_spy['trackedFunctionName']) ? custom_spy['trackedFunctionName'] : ''
         | 
| 31 32 | 
             
                    transaction = defined?(custom_spy['transaction']) ? custom_spy['transaction'] : nil
         | 
| 32 33 | 
             
                    file_path = defined?(custom_spy['file_path']) ? custom_spy['file_path'] : nil
         | 
| 33 34 |  | 
| 34 | 
            -
                     | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 35 | 
            +
                    if current_class
         | 
| 36 | 
            +
                      tracked_function_tpl = tracked_func_name.nil? ? '{{ClassName}}.{{MethodName}}' : tracked_func_name
         | 
| 37 | 
            +
                      tracked_function_name = tracked_function_tpl.to_s.sub '{{ClassName}}', current_class
         | 
| 38 | 
            +
                      tracked_function_name = tracked_function_name.to_s.sub '{{MethodName}}', current_method
         | 
| 39 | 
            +
                    elsif current_module
         | 
| 40 | 
            +
                      tracked_function_tpl = tracked_func_name.nil? ? '{{ModuleName}}.{{MethodName}}' : tracked_func_name
         | 
| 41 | 
            +
                      tracked_function_name = tracked_function_tpl.to_s.sub '{{ModuleName}}', current_module
         | 
| 42 | 
            +
                      tracked_function_name = tracked_function_name.to_s.sub '{{MethodName}}', current_method
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                    begin
         | 
| 46 | 
            +
                      if current_module
         | 
| 47 | 
            +
                        if file_path.nil?
         | 
| 48 | 
            +
                          config.logger.send(:info, "[StackifyRubyAPM] Error: Missing file_path in module which is required in custom instrumentation.")
         | 
| 49 | 
            +
                        else
         | 
| 50 | 
            +
                          require file_path
         | 
| 51 | 
            +
                          StackifyRubyAPM::InstrumenterHelper.patched_module(tracked_func, current_module, file_path,
         | 
| 52 | 
            +
                            current_method: current_method, tracked_function_name: tracked_function_name, is_transaction: transaction)
         | 
| 53 | 
            +
                        end
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                    rescue => e
         | 
| 56 | 
            +
                      throw e
         | 
| 57 | 
            +
                    end
         | 
| 37 58 |  | 
| 38 59 | 
             
                    if !class_exists?(current_class) && !file_path.nil?
         | 
| 39 60 | 
             
                      begin
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Monkey patch for the delayed_job class for running async tasks.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module StackifyRubyAPM
         | 
| 7 | 
            +
              # @api private
         | 
| 8 | 
            +
              module Spies
         | 
| 9 | 
            +
                # @api private
         | 
| 10 | 
            +
                class DelayedJobSpy
         | 
| 11 | 
            +
                  def install
         | 
| 12 | 
            +
                    Delayed::Backend::Base.class_eval do
         | 
| 13 | 
            +
                      alias_method 'invoke_job_without_apm', 'invoke_job'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      def invoke_job(*args, &block)
         | 
| 16 | 
            +
                        ret = nil
         | 
| 17 | 
            +
                        begin
         | 
| 18 | 
            +
                          name = nil
         | 
| 19 | 
            +
                          if payload_object.is_a?(::Delayed::PerformableMethod)
         | 
| 20 | 
            +
                            object = payload_object.object
         | 
| 21 | 
            +
                            klass = object.is_a?(Class) ? object : object.class
         | 
| 22 | 
            +
                            class_name = klass.name
         | 
| 23 | 
            +
                            separator = payload_object.object.is_a?(Class) ? '.' : '#'
         | 
| 24 | 
            +
                            method_name = payload_object.method_name
         | 
| 25 | 
            +
                            name = "#{class_name}#{separator}#{method_name}"
         | 
| 26 | 
            +
                          else
         | 
| 27 | 
            +
                            name = payload_object.class.name
         | 
| 28 | 
            +
                          end
         | 
| 29 | 
            +
                          ctx = StackifyRubyAPM::Context.new
         | 
| 30 | 
            +
                          ctx.category = 'Delayed::Job'
         | 
| 31 | 
            +
                          transaction = StackifyRubyAPM.transaction name, 'TASK', context: ctx
         | 
| 32 | 
            +
                          ret = invoke_job_without_apm(*args, &block)
         | 
| 33 | 
            +
                        rescue StackifyRubyAPM::InternalError
         | 
| 34 | 
            +
                          raise # Don't report StackifyRubyAPM errors
         | 
| 35 | 
            +
                        rescue StandardError => e
         | 
| 36 | 
            +
                          StackifyRubyAPM.report e
         | 
| 37 | 
            +
                          raise e
         | 
| 38 | 
            +
                        ensure
         | 
| 39 | 
            +
                          transaction.submit()
         | 
| 40 | 
            +
                        end
         | 
| 41 | 
            +
                        ret
         | 
| 42 | 
            +
                      end
         | 
| 43 | 
            +
                    end
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                register 'Delayed::Backend::Base', 'delayed/backend/base', DelayedJobSpy.new
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -21,34 +21,55 @@ module StackifyRubyAPM | |
| 21 21 | 
             
                      def perform_request(http_method, path, options, &block)
         | 
| 22 22 | 
             
                        req = nil
         | 
| 23 23 | 
             
                        return perform_request_without_apm(http_method, path, options, &block) unless StackifyRubyAPM.current_transaction
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                         | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                           | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 24 | 
            +
             | 
| 25 | 
            +
                        begin
         | 
| 26 | 
            +
                          # Data configuration
         | 
| 27 | 
            +
                          #
         | 
| 28 | 
            +
                          method = http_method.to_s.gsub('Net::HTTP::', '').upcase
         | 
| 29 | 
            +
                          uri = path.strip
         | 
| 30 | 
            +
                          name = "#{method} #{uri}"
         | 
| 31 | 
            +
                          type = "ext.HTTParty.#{method}"
         | 
| 32 | 
            +
                          # Submits HTTP request
         | 
| 33 | 
            +
                          #
         | 
| 34 | 
            +
                          # req = perform_request_without_apm(http_method, path, options, &block)
         | 
| 35 | 
            +
                          # Builds span context
         | 
| 36 | 
            +
                          #
         | 
| 37 | 
            +
                          # status_code = req.code
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                          ctx = Span::Context.new(
         | 
| 40 | 
            +
                            CATEGORY: 'Web External',
         | 
| 41 | 
            +
                            SUBCATEGORY: 'Execute',
         | 
| 42 | 
            +
                            URL: uri,
         | 
| 43 | 
            +
                            STATUS: '',
         | 
| 44 | 
            +
                            METHOD: method
         | 
| 45 | 
            +
                          )
         | 
| 46 | 
            +
                        rescue Exception => e
         | 
| 47 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPartySpy] Error: creating span context."
         | 
| 48 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPartySpy] #{e.inspect}"
         | 
| 49 | 
            +
                          return perform_request_without_apm(http_method, path, options, &block)
         | 
| 50 | 
            +
                        end
         | 
| 51 | 
            +
             | 
| 44 52 | 
             
                        # Creates new span from HTTP result
         | 
| 45 53 | 
             
                        #
         | 
| 46 54 | 
             
                        # class_info = { 'classname' => 'httparty', 'hostname' => URI.parse(uri).host }
         | 
| 47 55 | 
             
                        StackifyRubyAPM.span name, type, context: ctx do
         | 
| 48 | 
            -
                           | 
| 49 | 
            -
             | 
| 50 | 
            -
                           | 
| 51 | 
            -
             | 
| 56 | 
            +
                          res = perform_request_without_apm(http_method, path, options, &block)
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                          begin
         | 
| 59 | 
            +
                            status_code = res.code
         | 
| 60 | 
            +
                            ctx.update_status(status_code)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                            if StackifyRubyAPM.agent.config.prefix_enabled
         | 
| 63 | 
            +
                              ctx.update_request_body(options[:body] || "")
         | 
| 64 | 
            +
                              ctx.update_request_headers(options[:headers] || Hash.new)
         | 
| 65 | 
            +
                              ctx.update_response_body(res.body || "")
         | 
| 66 | 
            +
                              ctx.update_response_headers(res.each_header || Hash.new)
         | 
| 67 | 
            +
                            end
         | 
| 68 | 
            +
                          rescue Exception => e
         | 
| 69 | 
            +
                            StackifyRubyAPM.agent.error '[HTTPartySpy] Error: getting status code or updating request/response context.'
         | 
| 70 | 
            +
                            StackifyRubyAPM.agent.error "[HTTPartySpy] #{e.inspect}"
         | 
| 71 | 
            +
                          end
         | 
| 72 | 
            +
                          res
         | 
| 52 73 | 
             
                        end
         | 
| 53 74 | 
             
                      end
         | 
| 54 75 | 
             
                    end
         | 
| @@ -16,31 +16,52 @@ module StackifyRubyAPM | |
| 16 16 | 
             
                        req = nil
         | 
| 17 17 | 
             
                        return request_without_apm(method, uri, *args, &block) unless StackifyRubyAPM.current_transaction
         | 
| 18 18 |  | 
| 19 | 
            -
                         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                        # Submits HTTP request
         | 
| 27 | 
            -
                        #
         | 
| 28 | 
            -
                        req = request_without_apm(method, uri, *args, &block)
         | 
| 19 | 
            +
                        begin
         | 
| 20 | 
            +
                          # Data configuration
         | 
| 21 | 
            +
                          #
         | 
| 22 | 
            +
                          method = method.upcase
         | 
| 23 | 
            +
                          uri = uri.strip
         | 
| 24 | 
            +
                          name = "#{method} #{uri}"
         | 
| 25 | 
            +
                          type = "ext.httpclient.#{method}"
         | 
| 29 26 |  | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 27 | 
            +
                          # Builds span context
         | 
| 28 | 
            +
                          #
         | 
| 29 | 
            +
                          ctx = Span::Context.new(
         | 
| 30 | 
            +
                            CATEGORY: 'Web External',
         | 
| 31 | 
            +
                            SUBCATEGORY: 'Execute',
         | 
| 32 | 
            +
                            URL: uri,
         | 
| 33 | 
            +
                            STATUS: '',
         | 
| 34 | 
            +
                            METHOD: method
         | 
| 35 | 
            +
                          )
         | 
| 36 | 
            +
                        rescue Exception => e
         | 
| 37 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPClientSpy] Error: creating span context."
         | 
| 38 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPClientSpy] #{e.inspect}"
         | 
| 39 | 
            +
                          return request_without_apm(method, uri, *args, &block)
         | 
| 40 | 
            +
                        end
         | 
| 39 41 |  | 
| 40 42 | 
             
                        # Creates new span from HTTP result
         | 
| 41 43 | 
             
                        #
         | 
| 42 44 | 
             
                        StackifyRubyAPM.span name, type, context: ctx do
         | 
| 43 | 
            -
                           | 
| 45 | 
            +
                          # Submits HTTP request
         | 
| 46 | 
            +
                          #
         | 
| 47 | 
            +
                          res = request_without_apm(method, uri, *args, &block)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                          begin
         | 
| 50 | 
            +
                            ctx.update_status(res.status_code)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                            if StackifyRubyAPM.agent.config.prefix_enabled
         | 
| 53 | 
            +
                              options = args && args[0] || Hash.new
         | 
| 54 | 
            +
                              ctx.update_request_body(options[:body] || "")
         | 
| 55 | 
            +
                              ctx.update_request_headers(options[:header] || Hash.new)
         | 
| 56 | 
            +
                              ctx.update_response_body(res.body || "")
         | 
| 57 | 
            +
                              ctx.update_response_headers(res.headers || Hash.new)
         | 
| 58 | 
            +
                            end
         | 
| 59 | 
            +
                          rescue Exception => e
         | 
| 60 | 
            +
                            StackifyRubyAPM.agent.error '[HTTPClientSpy] Error: getting status code or updating request/response context.'
         | 
| 61 | 
            +
                            StackifyRubyAPM.agent.error "[HTTPClientSpy] #{e.inspect}"
         | 
| 62 | 
            +
                          end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                          res
         | 
| 44 65 | 
             
                        end
         | 
| 45 66 | 
             
                      end
         | 
| 46 67 | 
             
                    end
         | 
| @@ -10,28 +10,49 @@ module StackifyRubyAPM | |
| 10 10 | 
             
                class HTTPRbSpy
         | 
| 11 11 | 
             
                  def install
         | 
| 12 12 | 
             
                    HTTP::Client.class_eval do
         | 
| 13 | 
            -
                      alias_method ' | 
| 13 | 
            +
                      alias_method 'perform_without_apm', 'perform'
         | 
| 14 14 |  | 
| 15 15 | 
             
                      # Make HTTP request
         | 
| 16 | 
            -
                      def  | 
| 17 | 
            -
                        return  | 
| 18 | 
            -
             | 
| 19 | 
            -
                         | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 16 | 
            +
                      def perform(req, options)
         | 
| 17 | 
            +
                        return perform_without_apm(req, options) unless StackifyRubyAPM.current_transaction
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                        begin
         | 
| 20 | 
            +
                          method = req.verb.upcase
         | 
| 21 | 
            +
                          uri = req.uri.to_s.strip
         | 
| 22 | 
            +
                          name = "#{method} #{uri}"
         | 
| 23 | 
            +
                          type = "ext.httprb.#{method}"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                          ctx = Span::Context.new(
         | 
| 26 | 
            +
                            CATEGORY: 'Web External',
         | 
| 27 | 
            +
                            SUBCATEGORY: 'Execute',
         | 
| 28 | 
            +
                            URL: uri,
         | 
| 29 | 
            +
                            STATUS: '',
         | 
| 30 | 
            +
                            METHOD: method
         | 
| 31 | 
            +
                          )
         | 
| 32 | 
            +
                        rescue Exception => e
         | 
| 33 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPRbSpy] Error: creating span context."
         | 
| 34 | 
            +
                          StackifyRubyAPM.agent.error "[HTTPRbSpy] #{e.inspect}"
         | 
| 35 | 
            +
                          return perform_without_apm(req, options)
         | 
| 36 | 
            +
                        end
         | 
| 32 37 |  | 
| 33 38 | 
             
                        StackifyRubyAPM.span name, type, context: ctx do
         | 
| 34 | 
            -
                          req
         | 
| 39 | 
            +
                          res = perform_without_apm(req, options)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                          begin
         | 
| 42 | 
            +
                            ctx.update_status(res.code)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                            if StackifyRubyAPM.agent.config.prefix_enabled
         | 
| 45 | 
            +
                              ctx.update_request_body(req.body.source || "")
         | 
| 46 | 
            +
                              ctx.update_request_headers(req.headers || Hash.new)
         | 
| 47 | 
            +
                              ctx.update_response_body(res.body || "")
         | 
| 48 | 
            +
                              ctx.update_response_headers(res.headers || Hash.new)
         | 
| 49 | 
            +
                            end
         | 
| 50 | 
            +
                          rescue Exception => e
         | 
| 51 | 
            +
                            StackifyRubyAPM.agent.error '[HTTPRbSpy] Error: getting status code or updating request/response context.'
         | 
| 52 | 
            +
                            StackifyRubyAPM.agent.error "[HTTPRbSpy] #{e.inspect}"
         | 
| 53 | 
            +
                          end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                          res
         | 
| 35 56 | 
             
                        end
         | 
| 36 57 | 
             
                      end
         | 
| 37 58 | 
             
                    end
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Monkey patch for the Log4r::Outputter class for logging log message.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            module StackifyRubyAPM
         | 
| 6 | 
            +
              module Spies
         | 
| 7 | 
            +
                class Log4rSpy
         | 
| 8 | 
            +
                  def install
         | 
| 9 | 
            +
                    Log4r::Outputter.module_eval do
         | 
| 10 | 
            +
                      alias_method 'canonical_log_without_apm', 'canonical_log'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      # Log message formatted to a logevent object
         | 
| 13 | 
            +
                      def canonical_log(logevent)
         | 
| 14 | 
            +
                        return canonical_log_without_apm(logevent) unless StackifyRubyAPM.current_transaction
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                        begin
         | 
| 17 | 
            +
                          name = 'log4r'
         | 
| 18 | 
            +
                          type = 'ext.log4r'
         | 
| 19 | 
            +
                          log_message = ''
         | 
| 20 | 
            +
                          exception = nil
         | 
| 21 | 
            +
                          msg = logevent.data
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                          case msg
         | 
| 24 | 
            +
                          when ::String
         | 
| 25 | 
            +
                            log_message = msg
         | 
| 26 | 
            +
                          when ::Exception
         | 
| 27 | 
            +
                            log_message = msg.message
         | 
| 28 | 
            +
                            exception = "(#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
         | 
| 29 | 
            +
                          else
         | 
| 30 | 
            +
                            log_message = msg.inspect
         | 
| 31 | 
            +
                          end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                          ctx = Span::Context.new(
         | 
| 34 | 
            +
                            CATEGORY: 'Log',
         | 
| 35 | 
            +
                            SUBCATEGORY: 'Log4r',
         | 
| 36 | 
            +
                            LEVEL: Log4r::LNAMES[logevent.level] || 'ANY',
         | 
| 37 | 
            +
                            MESSAGE: log_message
         | 
| 38 | 
            +
                          )
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                          if exception
         | 
| 41 | 
            +
                            ctx.EXCEPTION = exception
         | 
| 42 | 
            +
                          end
         | 
| 43 | 
            +
                        rescue Exception => e
         | 
| 44 | 
            +
                          StackifyRubyAPM.agent.error "[Log4rSpy] Error: creating span context."
         | 
| 45 | 
            +
                          StackifyRubyAPM.agent.error "[Log4rSpy] #{e.inspect}"
         | 
| 46 | 
            +
                          return canonical_log_without_apm(logevent)
         | 
| 47 | 
            +
                        end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                        StackifyRubyAPM.span name, type, context: ctx do
         | 
| 50 | 
            +
                          canonical_log_without_apm(logevent)
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                register 'Log4r::Outputter', 'log4r', Log4rSpy.new
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| @@ -0,0 +1,116 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Monkey patch for the Logger class for logging log messages.
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            module StackifyRubyAPM
         | 
| 7 | 
            +
              module Spies
         | 
| 8 | 
            +
                class LoggerSpy
         | 
| 9 | 
            +
                  NAME = 'logger'
         | 
| 10 | 
            +
                  TYPE = 'core.devlog'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def install
         | 
| 13 | 
            +
                    Logger.class_eval do
         | 
| 14 | 
            +
                      alias_method 'debug_without_apm', 'debug'
         | 
| 15 | 
            +
                      alias_method 'info_without_apm', 'info'
         | 
| 16 | 
            +
                      alias_method 'warn_without_apm', 'warn'
         | 
| 17 | 
            +
                      alias_method 'error_without_apm', 'error'
         | 
| 18 | 
            +
                      alias_method 'fatal_without_apm', 'fatal'
         | 
| 19 | 
            +
                      alias_method 'unknown_without_apm', 'unknown'
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      def debug(progname = nil, &block)
         | 
| 22 | 
            +
                        return debug_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 23 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('DEBUG', nil, progname, &block)
         | 
| 24 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 25 | 
            +
                          debug_without_apm(progname, &block)
         | 
| 26 | 
            +
                        end
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      def info(progname = nil, &block)
         | 
| 30 | 
            +
                        return info_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 31 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('INFO', nil, progname, &block)
         | 
| 32 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 33 | 
            +
                          info_without_apm(progname, &block)
         | 
| 34 | 
            +
                        end
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      def warn(progname = nil, &block)
         | 
| 38 | 
            +
                        return warn_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 39 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('WARN', nil, progname, &block)
         | 
| 40 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 41 | 
            +
                          warn_without_apm(progname, &block)
         | 
| 42 | 
            +
                        end
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                      def error(progname = nil, &block)
         | 
| 46 | 
            +
                        return error_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 47 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('ERROR', nil, progname, &block)
         | 
| 48 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 49 | 
            +
                          error_without_apm(progname, &block)
         | 
| 50 | 
            +
                        end
         | 
| 51 | 
            +
                      end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      def fatal(progname = nil, &block)
         | 
| 54 | 
            +
                        return fatal_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 55 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('FATAL', nil, progname, &block)
         | 
| 56 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 57 | 
            +
                          fatal_without_apm(progname, &block)
         | 
| 58 | 
            +
                        end
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                      def unknown(progname = nil, &block)
         | 
| 62 | 
            +
                        return unknown_without_apm(progname, &block) unless StackifyRubyAPM.current_transaction
         | 
| 63 | 
            +
                        ctx = StackifyRubyAPM::Spies::LoggerSpy.get_log_context('UNKNOWN', nil, progname, &block)
         | 
| 64 | 
            +
                        StackifyRubyAPM.span NAME, TYPE, context: ctx do
         | 
| 65 | 
            +
                          unknown_without_apm(progname, &block)
         | 
| 66 | 
            +
                        end
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  # create and return logger span context
         | 
| 72 | 
            +
                  def self.get_log_context(severity, message, progname)
         | 
| 73 | 
            +
                    ctx = nil
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    begin
         | 
| 76 | 
            +
                      log_message = ''
         | 
| 77 | 
            +
                      exception = nil
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      if message.nil?
         | 
| 80 | 
            +
                        msg = progname
         | 
| 81 | 
            +
                      else
         | 
| 82 | 
            +
                        msg = message
         | 
| 83 | 
            +
                      end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      case msg
         | 
| 86 | 
            +
                      when ::String
         | 
| 87 | 
            +
                        log_message = msg
         | 
| 88 | 
            +
                      when ::Exception
         | 
| 89 | 
            +
                        log_message = msg.message
         | 
| 90 | 
            +
                        exception = "(#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
         | 
| 91 | 
            +
                      else
         | 
| 92 | 
            +
                        log_message = msg.inspect
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                      ctx = Span::Context.new(
         | 
| 96 | 
            +
                        CATEGORY: 'Log',
         | 
| 97 | 
            +
                        SUBCATEGORY: 'Logger',
         | 
| 98 | 
            +
                        LEVEL: severity || 'ANY',
         | 
| 99 | 
            +
                        MESSAGE: log_message
         | 
| 100 | 
            +
                      )
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                      if exception
         | 
| 103 | 
            +
                        ctx.EXCEPTION = exception
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    rescue Exception => e
         | 
| 106 | 
            +
                      StackifyRubyAPM.agent.error "[LoggerSpy] Error: creating span context."
         | 
| 107 | 
            +
                      StackifyRubyAPM.agent.error "[LoggerSpy] #{e.inspect}"
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    ctx
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                register 'Logger', 'logger', LoggerSpy.new
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
            end
         |