appsignal 3.12.6-java → 3.13.0-java
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/CHANGELOG.md +38 -0
- data/lib/appsignal/check_in/cron.rb +80 -0
- data/lib/appsignal/check_in.rb +46 -0
- data/lib/appsignal/helpers/heartbeat.rb +20 -0
- data/lib/appsignal/helpers/instrumentation.rb +3 -0
- data/lib/appsignal/integrations/http.rb +2 -7
- data/lib/appsignal/version.rb +1 -1
- data/lib/appsignal.rb +13 -3
- data/spec/lib/appsignal/check_in_spec.rb +342 -0
- data/spec/lib/appsignal/integrations/http_spec.rb +0 -21
- metadata +7 -6
- data/lib/appsignal/heartbeat.rb +0 -59
- data/lib/appsignal/helpers/heartbeats.rb +0 -44
- data/spec/lib/appsignal/heartbeat_spec.rb +0 -127
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: ebb12a4ab096308cdac9176f3575e5ac9c3a1afc7e330c8681d097302d29cdaf
         | 
| 4 | 
            +
              data.tar.gz: a5be1a3498ff49fe1e6de1d09abe81bb4d2ce2a5cc44a69e6fa45ebe9b9d8496
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: fc298f6b093e86d085ab2abf5da045d10aa51fd0a12f894b73d83632eca383589c89f49ced7054eab77c68d02468333622527c3e9dd4375d5627062773a0f9af
         | 
| 7 | 
            +
              data.tar.gz: 8311cc2b6c88447565c87cc231c50e3aa0640905cef72f400cb1620057ae22ef779da497dac76287ec9404957684fe838fd6c6471d9fcc5081b5cde94e747f05
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,42 @@ | |
| 1 1 | 
             
            # AppSignal for Ruby gem Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 3.13.0
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            _Published on 2024-08-14._
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ### Changed
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            - Remove the HTTP gem's exception handling. Errors from the HTTP gem will no longer always be reported. The error will be reported only when an HTTP request is made in an instrumented context. This gives applications the opportunity to add their own custom exception handling.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              ```ruby
         | 
| 12 | 
            +
              begin
         | 
| 13 | 
            +
                HTTP.get("https://appsignal.com/error")
         | 
| 14 | 
            +
              rescue => error
         | 
| 15 | 
            +
                # Either handle the error or report it to AppSignal
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
              ```
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              (minor [2a452ff0](https://github.com/appsignal/appsignal-ruby/commit/2a452ff07e0b0938b1623fa8846af6ef37917ec2))
         | 
| 20 | 
            +
            - Rename heartbeats to cron check-ins. Calls to `Appsignal.heartbeat` and `Appsignal::Heartbeat` should be replaced with calls to `Appsignal::CheckIn.cron` and `Appsignal::CheckIn::Cron`, for example:
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              ```ruby
         | 
| 23 | 
            +
              # Before
         | 
| 24 | 
            +
              Appsignal.heartbeat("do_something") do
         | 
| 25 | 
            +
                do_something
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              # After
         | 
| 29 | 
            +
              Appsignal::CheckIn.cron("do_something") do
         | 
| 30 | 
            +
                do_something
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
              ```
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              (patch [2f686cd0](https://github.com/appsignal/appsignal-ruby/commit/2f686cd00d5daa6e0854a8cacfe0e874a3a7c146))
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            ### Deprecated
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            - Calls to `Appsignal.heartbeat` and `Appsignal::Heartbeat` will emit a deprecation warning. (patch [2f686cd0](https://github.com/appsignal/appsignal-ruby/commit/2f686cd00d5daa6e0854a8cacfe0e874a3a7c146))
         | 
| 39 | 
            +
             | 
| 3 40 | 
             
            ## 3.12.6
         | 
| 4 41 |  | 
| 5 42 | 
             
            _Published on 2024-08-05._
         | 
| @@ -18,6 +55,7 @@ _Published on 2024-08-05._ | |
| 18 55 | 
             
                raise "some error"
         | 
| 19 56 | 
             
              end
         | 
| 20 57 |  | 
| 58 | 
            +
              # After
         | 
| 21 59 | 
             
              begin
         | 
| 22 60 | 
             
                raise "some error"
         | 
| 23 61 | 
             
              rescue => error
         | 
| @@ -0,0 +1,80 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Appsignal
         | 
| 4 | 
            +
              module CheckIn
         | 
| 5 | 
            +
                class Cron
         | 
| 6 | 
            +
                  class << self
         | 
| 7 | 
            +
                    # @api private
         | 
| 8 | 
            +
                    def transmitter
         | 
| 9 | 
            +
                      @transmitter ||= Appsignal::Transmitter.new(
         | 
| 10 | 
            +
                        "#{Appsignal.config[:logging_endpoint]}/check_ins/json"
         | 
| 11 | 
            +
                      )
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def emit_initializer_deprecation_warning
         | 
| 15 | 
            +
                      return if @initializer_deprecation_warning_emitted
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      callers = caller
         | 
| 18 | 
            +
                      Appsignal::Utils::StdoutAndLoggerMessage.warning(
         | 
| 19 | 
            +
                        "Passing a `name` keyword argument to `Appsignal::CheckIn::Cron.new` is deprecated. " \
         | 
| 20 | 
            +
                          "Please use the `identifier` keyword argument instead, " \
         | 
| 21 | 
            +
                          "in the following file and elsewhere, to remove this message.\n#{callers[2]}"
         | 
| 22 | 
            +
                      )
         | 
| 23 | 
            +
                      @initializer_deprecation_warning_emitted = true
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  # @api private
         | 
| 28 | 
            +
                  attr_reader :identifier, :digest
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def initialize(identifier: nil, name: nil)
         | 
| 31 | 
            +
                    @identifier = identifier || name || raise(ArgumentError, "missing keyword: :identifier")
         | 
| 32 | 
            +
                    Cron.emit_initializer_deprecation_warning unless name.nil?
         | 
| 33 | 
            +
                    @digest = SecureRandom.hex(8)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def start
         | 
| 37 | 
            +
                    transmit_event("start")
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def finish
         | 
| 41 | 
            +
                    transmit_event("finish")
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  private
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  def event(kind)
         | 
| 47 | 
            +
                    {
         | 
| 48 | 
            +
                      :identifier => @identifier,
         | 
| 49 | 
            +
                      :digest => @digest,
         | 
| 50 | 
            +
                      :kind => kind,
         | 
| 51 | 
            +
                      :timestamp => Time.now.utc.to_i,
         | 
| 52 | 
            +
                      :check_in_type => "cron"
         | 
| 53 | 
            +
                    }
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  def transmit_event(kind)
         | 
| 57 | 
            +
                    unless Appsignal.active?
         | 
| 58 | 
            +
                      Appsignal.internal_logger.debug(
         | 
| 59 | 
            +
                        "AppSignal not active, not transmitting cron check-in event"
         | 
| 60 | 
            +
                      )
         | 
| 61 | 
            +
                      return
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                    response = self.class.transmitter.transmit(event(kind))
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    if response.code.to_i >= 200 && response.code.to_i < 300
         | 
| 67 | 
            +
                      Appsignal.internal_logger.debug(
         | 
| 68 | 
            +
                        "Transmitted cron check-in `#{identifier}` (#{digest}) #{kind} event"
         | 
| 69 | 
            +
                      )
         | 
| 70 | 
            +
                    else
         | 
| 71 | 
            +
                      Appsignal.internal_logger.error(
         | 
| 72 | 
            +
                        "Failed to transmit cron check-in #{kind} event: status code was #{response.code}"
         | 
| 73 | 
            +
                      )
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                  rescue => e
         | 
| 76 | 
            +
                    Appsignal.internal_logger.error("Failed to transmit cron check-in #{kind} event: #{e}")
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
              end
         | 
| 80 | 
            +
            end
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Appsignal
         | 
| 4 | 
            +
              module CheckIn
         | 
| 5 | 
            +
                class << self
         | 
| 6 | 
            +
                  # Track cron check-ins.
         | 
| 7 | 
            +
                  #
         | 
| 8 | 
            +
                  # Track the execution of certain processes by sending a cron check-in.
         | 
| 9 | 
            +
                  #
         | 
| 10 | 
            +
                  # To track the duration of a piece of code, pass a block to {.cron}
         | 
| 11 | 
            +
                  # to report both when the process starts, and when it finishes.
         | 
| 12 | 
            +
                  #
         | 
| 13 | 
            +
                  # If an exception is raised within the block, the finish event will not
         | 
| 14 | 
            +
                  # be reported, triggering a notification about the missing cron check-in.
         | 
| 15 | 
            +
                  # The exception will bubble outside of the cron check-in block.
         | 
| 16 | 
            +
                  #
         | 
| 17 | 
            +
                  # @example Send a cron check-in
         | 
| 18 | 
            +
                  #   Appsignal::CheckIn.cron("send_invoices")
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  # @example Send a cron check-in with duration
         | 
| 21 | 
            +
                  #   Appsignal::CheckIn.cron("send_invoices") do
         | 
| 22 | 
            +
                  #     # your code
         | 
| 23 | 
            +
                  #   end
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  # @param name [String] name of the cron check-in to report.
         | 
| 26 | 
            +
                  # @yield the block to monitor.
         | 
| 27 | 
            +
                  # @return [void]
         | 
| 28 | 
            +
                  # @since 3.13.0
         | 
| 29 | 
            +
                  # @see https://docs.appsignal.com/check-ins/cron
         | 
| 30 | 
            +
                  def cron(identifier)
         | 
| 31 | 
            +
                    cron = Appsignal::CheckIn::Cron.new(:identifier => identifier)
         | 
| 32 | 
            +
                    output = nil
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    if block_given?
         | 
| 35 | 
            +
                      cron.start
         | 
| 36 | 
            +
                      output = yield
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    cron.finish
         | 
| 40 | 
            +
                    output
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
            end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            require "appsignal/check_in/cron"
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Appsignal
         | 
| 4 | 
            +
              module Helpers
         | 
| 5 | 
            +
                module Heartbeat
         | 
| 6 | 
            +
                  # @deprecated Use {Appsignal::CheckIn.cron} instead.
         | 
| 7 | 
            +
                  def heartbeat(name, &block)
         | 
| 8 | 
            +
                    unless @heartbeat_helper_deprecation_warning_emitted
         | 
| 9 | 
            +
                      callers = caller
         | 
| 10 | 
            +
                      Appsignal::Utils::StdoutAndLoggerMessage.warning \
         | 
| 11 | 
            +
                        "The helper Appsignal.heartbeat has been deprecated. " \
         | 
| 12 | 
            +
                          "Please update the helper call to Appsignal::CheckIn.cron " \
         | 
| 13 | 
            +
                          "in the following file and elsewhere to remove this message.\n#{callers.first}"
         | 
| 14 | 
            +
                      @heartbeat_helper_deprecation_warning_emitted = true
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                    Appsignal::CheckIn.cron(name, &block)
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -300,7 +300,10 @@ module Appsignal | |
| 300 300 | 
             
                  # @see .send_error
         | 
| 301 301 | 
             
                  # @see https://docs.appsignal.com/ruby/instrumentation/integrating-appsignal.html
         | 
| 302 302 | 
             
                  #   AppSignal integration guide
         | 
| 303 | 
            +
                  # @see https://docs.appsignal.com/ruby/instrumentation/exception-handling.html
         | 
| 304 | 
            +
                  #   Exception handling guide
         | 
| 303 305 | 
             
                  #
         | 
| 306 | 
            +
                  # @deprecated Use `rescue => error` with {.report_error} instead.
         | 
| 304 307 | 
             
                  # @param tags [Hash, nil]
         | 
| 305 308 | 
             
                  # @param namespace [String] the namespace for this error.
         | 
| 306 309 | 
             
                  # @yield yields the given block.
         | 
| @@ -8,13 +8,8 @@ module Appsignal | |
| 8 8 | 
             
                    parsed_request_uri = uri.is_a?(URI) ? uri : URI.parse(uri.to_s)
         | 
| 9 9 | 
             
                    request_uri = "#{parsed_request_uri.scheme}://#{parsed_request_uri.host}"
         | 
| 10 10 |  | 
| 11 | 
            -
                     | 
| 12 | 
            -
                       | 
| 13 | 
            -
                        super
         | 
| 14 | 
            -
                      end
         | 
| 15 | 
            -
                    rescue Exception => error # rubocop:disable Lint/RescueException
         | 
| 16 | 
            -
                      Appsignal.set_error(error)
         | 
| 17 | 
            -
                      raise error
         | 
| 11 | 
            +
                    Appsignal.instrument("request.http_rb", "#{verb.upcase} #{request_uri}") do
         | 
| 12 | 
            +
                      super
         | 
| 18 13 | 
             
                    end
         | 
| 19 14 | 
             
                  end
         | 
| 20 15 | 
             
                end
         | 
    
        data/lib/appsignal/version.rb
    CHANGED
    
    
    
        data/lib/appsignal.rb
    CHANGED
    
    | @@ -6,7 +6,7 @@ require "stringio" | |
| 6 6 |  | 
| 7 7 | 
             
            require "appsignal/logger"
         | 
| 8 8 | 
             
            require "appsignal/utils/stdout_and_logger_message"
         | 
| 9 | 
            -
            require "appsignal/helpers/ | 
| 9 | 
            +
            require "appsignal/helpers/heartbeat"
         | 
| 10 10 | 
             
            require "appsignal/helpers/instrumentation"
         | 
| 11 11 | 
             
            require "appsignal/helpers/metrics"
         | 
| 12 12 |  | 
| @@ -18,7 +18,7 @@ require "appsignal/helpers/metrics" | |
| 18 18 | 
             
            # {Appsignal::Helpers::Metrics}) for ease of use.
         | 
| 19 19 | 
             
            module Appsignal
         | 
| 20 20 | 
             
              class << self
         | 
| 21 | 
            -
                include Helpers:: | 
| 21 | 
            +
                include Helpers::Heartbeat
         | 
| 22 22 | 
             
                include Helpers::Instrumentation
         | 
| 23 23 | 
             
                include Helpers::Metrics
         | 
| 24 24 |  | 
| @@ -461,6 +461,16 @@ module Appsignal | |
| 461 461 | 
             
                        "Please update the constant name to Appsignal::Probes " \
         | 
| 462 462 | 
             
                        "in the following file to remove this message.\n#{callers.first}"
         | 
| 463 463 | 
             
                    Appsignal::Probes
         | 
| 464 | 
            +
                  when :Heartbeat
         | 
| 465 | 
            +
                    unless @heartbeat_constant_deprecation_warning_emitted
         | 
| 466 | 
            +
                      callers = caller
         | 
| 467 | 
            +
                      Appsignal::Utils::StdoutAndLoggerMessage.warning \
         | 
| 468 | 
            +
                        "The constant Appsignal::Heartbeat has been deprecated. " \
         | 
| 469 | 
            +
                          "Please update the constant name to Appsignal::CheckIn::Cron " \
         | 
| 470 | 
            +
                          "in the following file and elsewhere to remove this message.\n#{callers.first}"
         | 
| 471 | 
            +
                      @heartbeat_constant_deprecation_warning_emitted = true
         | 
| 472 | 
            +
                    end
         | 
| 473 | 
            +
                    Appsignal::CheckIn::Cron
         | 
| 464 474 | 
             
                  else
         | 
| 465 475 | 
             
                    super
         | 
| 466 476 | 
             
                  end
         | 
| @@ -489,4 +499,4 @@ require "appsignal/integrations/railtie" if defined?(::Rails) | |
| 489 499 | 
             
            require "appsignal/transaction"
         | 
| 490 500 | 
             
            require "appsignal/version"
         | 
| 491 501 | 
             
            require "appsignal/transmitter"
         | 
| 492 | 
            -
            require "appsignal/ | 
| 502 | 
            +
            require "appsignal/check_in"
         | 
| @@ -0,0 +1,342 @@ | |
| 1 | 
            +
            describe Appsignal::Heartbeat do
         | 
| 2 | 
            +
              let(:err_stream) { std_stream }
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              after do
         | 
| 5 | 
            +
                Appsignal.instance_variable_set(:@heartbeat_constant_deprecation_warning_emitted, false)
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              it "returns the Cron constant calling the Heartbeat constant" do
         | 
| 9 | 
            +
                silence { expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron) }
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              it "prints a deprecation warning to STDERR" do
         | 
| 13 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 14 | 
            +
                  expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                expect(err_stream.read)
         | 
| 18 | 
            +
                  .to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              it "does not print a deprecation warning to STDERR more than once" do
         | 
| 22 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 23 | 
            +
                  expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                expect(err_stream.read)
         | 
| 27 | 
            +
                  .to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                err_stream.truncate(0)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 32 | 
            +
                  expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                expect(err_stream.read)
         | 
| 36 | 
            +
                  .not_to include("appsignal WARNING: The constant Appsignal::Heartbeat has been deprecated.")
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              it "logs a warning" do
         | 
| 40 | 
            +
                logs =
         | 
| 41 | 
            +
                  capture_logs do
         | 
| 42 | 
            +
                    silence do
         | 
| 43 | 
            +
                      expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                expect(logs).to contains_log(
         | 
| 48 | 
            +
                  :warn,
         | 
| 49 | 
            +
                  "The constant Appsignal::Heartbeat has been deprecated."
         | 
| 50 | 
            +
                )
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              it "does not log a warning more than once" do
         | 
| 54 | 
            +
                logs =
         | 
| 55 | 
            +
                  capture_logs do
         | 
| 56 | 
            +
                    silence do
         | 
| 57 | 
            +
                      expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 58 | 
            +
                    end
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                expect(logs).to contains_log(
         | 
| 62 | 
            +
                  :warn,
         | 
| 63 | 
            +
                  "The constant Appsignal::Heartbeat has been deprecated."
         | 
| 64 | 
            +
                )
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                logs =
         | 
| 67 | 
            +
                  capture_logs do
         | 
| 68 | 
            +
                    silence do
         | 
| 69 | 
            +
                      expect(Appsignal::Heartbeat).to be(Appsignal::CheckIn::Cron)
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                expect(logs).not_to contains_log(
         | 
| 74 | 
            +
                  :warn,
         | 
| 75 | 
            +
                  "The constant Appsignal::Heartbeat has been deprecated."
         | 
| 76 | 
            +
                )
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            describe "Appsignal.heartbeat" do
         | 
| 81 | 
            +
              let(:err_stream) { std_stream }
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              before do
         | 
| 84 | 
            +
                Appsignal.instance_variable_set(:@heartbeat_helper_deprecation_warning_emitted, false)
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
              it "should forward the call to Appsignal::CheckIn.cron" do
         | 
| 88 | 
            +
                expect(Appsignal::CheckIn).to receive(:cron).with("heartbeat-name")
         | 
| 89 | 
            +
                expect do
         | 
| 90 | 
            +
                  Appsignal.heartbeat("heartbeat-name")
         | 
| 91 | 
            +
                end.not_to raise_error
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                block = proc { 42 }
         | 
| 94 | 
            +
                expect(Appsignal::CheckIn).to receive(:cron).with("heartbeat-name") do |&given_block|
         | 
| 95 | 
            +
                  expect(given_block).to be(block)
         | 
| 96 | 
            +
                end.and_return("output")
         | 
| 97 | 
            +
                expect(Appsignal.heartbeat("heartbeat-name", &block)).to eq("output")
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              it "prints a deprecation warning to STDERR" do
         | 
| 101 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 102 | 
            +
                  Appsignal.heartbeat("heartbeat-name")
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                expect(err_stream.read)
         | 
| 106 | 
            +
                  .to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
         | 
| 107 | 
            +
              end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
              it "does not print a deprecation warning to STDERR more than once" do
         | 
| 110 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 111 | 
            +
                  Appsignal.heartbeat("heartbeat-name")
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                expect(err_stream.read)
         | 
| 115 | 
            +
                  .to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                err_stream.truncate(0)
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                capture_std_streams(std_stream, err_stream) do
         | 
| 120 | 
            +
                  Appsignal.heartbeat("heartbeat-name")
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                expect(err_stream.read)
         | 
| 124 | 
            +
                  .not_to include("appsignal WARNING: The helper Appsignal.heartbeat has been deprecated.")
         | 
| 125 | 
            +
              end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
              it "logs a warning" do
         | 
| 128 | 
            +
                logs =
         | 
| 129 | 
            +
                  capture_logs do
         | 
| 130 | 
            +
                    silence do
         | 
| 131 | 
            +
                      Appsignal.heartbeat("heartbeat-name")
         | 
| 132 | 
            +
                    end
         | 
| 133 | 
            +
                  end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                expect(logs).to contains_log(
         | 
| 136 | 
            +
                  :warn,
         | 
| 137 | 
            +
                  "The helper Appsignal.heartbeat has been deprecated."
         | 
| 138 | 
            +
                )
         | 
| 139 | 
            +
              end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
              it "does not log a warning more than once" do
         | 
| 142 | 
            +
                logs =
         | 
| 143 | 
            +
                  capture_logs do
         | 
| 144 | 
            +
                    silence do
         | 
| 145 | 
            +
                      Appsignal.heartbeat("heartbeat-name")
         | 
| 146 | 
            +
                    end
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                expect(logs).to contains_log(
         | 
| 150 | 
            +
                  :warn,
         | 
| 151 | 
            +
                  "The helper Appsignal.heartbeat has been deprecated."
         | 
| 152 | 
            +
                )
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                logs =
         | 
| 155 | 
            +
                  capture_logs do
         | 
| 156 | 
            +
                    silence do
         | 
| 157 | 
            +
                      Appsignal.heartbeat("heartbeat-name")
         | 
| 158 | 
            +
                    end
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                expect(logs).not_to contains_log(
         | 
| 162 | 
            +
                  :warn,
         | 
| 163 | 
            +
                  "The helper Appsignal.heartbeat has been deprecated."
         | 
| 164 | 
            +
                )
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
            end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            describe Appsignal::CheckIn::Cron do
         | 
| 169 | 
            +
              let(:config) { project_fixture_config }
         | 
| 170 | 
            +
              let(:cron_checkin) { described_class.new(:name => "cron-checkin-name") }
         | 
| 171 | 
            +
              let(:transmitter) { Appsignal::Transmitter.new("http://cron_checkins/", config) }
         | 
| 172 | 
            +
             | 
| 173 | 
            +
              before(:each) do
         | 
| 174 | 
            +
                allow(Appsignal).to receive(:active?).and_return(true)
         | 
| 175 | 
            +
                config.logger = Logger.new(StringIO.new)
         | 
| 176 | 
            +
                allow(Appsignal::CheckIn::Cron).to receive(:transmitter).and_return(transmitter)
         | 
| 177 | 
            +
              end
         | 
| 178 | 
            +
             | 
| 179 | 
            +
              describe "when Appsignal is not active" do
         | 
| 180 | 
            +
                it "should not transmit any events" do
         | 
| 181 | 
            +
                  allow(Appsignal).to receive(:active?).and_return(false)
         | 
| 182 | 
            +
                  expect(transmitter).not_to receive(:transmit)
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                  cron_checkin.start
         | 
| 185 | 
            +
                  cron_checkin.finish
         | 
| 186 | 
            +
                end
         | 
| 187 | 
            +
              end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
              describe "#start" do
         | 
| 190 | 
            +
                it "should send a cron check-in start" do
         | 
| 191 | 
            +
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 192 | 
            +
                    :identifier => "cron-checkin-name",
         | 
| 193 | 
            +
                    :kind => "start",
         | 
| 194 | 
            +
                    :check_in_type => "cron"
         | 
| 195 | 
            +
                  )).and_return(Net::HTTPResponse.new(nil, "200", nil))
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                  expect(Appsignal.internal_logger).to receive(:debug).with(
         | 
| 198 | 
            +
                    "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) start event"
         | 
| 199 | 
            +
                  )
         | 
| 200 | 
            +
                  expect(Appsignal.internal_logger).not_to receive(:error)
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                  cron_checkin.start
         | 
| 203 | 
            +
                end
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                it "should log an error if it fails" do
         | 
| 206 | 
            +
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 207 | 
            +
                    :identifier => "cron-checkin-name",
         | 
| 208 | 
            +
                    :kind => "start",
         | 
| 209 | 
            +
                    :check_in_type => "cron"
         | 
| 210 | 
            +
                  )).and_return(Net::HTTPResponse.new(nil, "499", nil))
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  expect(Appsignal.internal_logger).not_to receive(:debug)
         | 
| 213 | 
            +
                  expect(Appsignal.internal_logger).to receive(:error).with(
         | 
| 214 | 
            +
                    "Failed to transmit cron check-in start event: status code was 499"
         | 
| 215 | 
            +
                  )
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                  cron_checkin.start
         | 
| 218 | 
            +
                end
         | 
| 219 | 
            +
              end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
              describe "#finish" do
         | 
| 222 | 
            +
                it "should send a cron check-in finish" do
         | 
| 223 | 
            +
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 224 | 
            +
                    :identifier => "cron-checkin-name",
         | 
| 225 | 
            +
                    :kind => "finish",
         | 
| 226 | 
            +
                    :check_in_type => "cron"
         | 
| 227 | 
            +
                  )).and_return(Net::HTTPResponse.new(nil, "200", nil))
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  expect(Appsignal.internal_logger).to receive(:debug).with(
         | 
| 230 | 
            +
                    "Transmitted cron check-in `cron-checkin-name` (#{cron_checkin.digest}) finish event"
         | 
| 231 | 
            +
                  )
         | 
| 232 | 
            +
                  expect(Appsignal.internal_logger).not_to receive(:error)
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                  cron_checkin.finish
         | 
| 235 | 
            +
                end
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                it "should log an error if it fails" do
         | 
| 238 | 
            +
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 239 | 
            +
                    :identifier => "cron-checkin-name",
         | 
| 240 | 
            +
                    :kind => "finish",
         | 
| 241 | 
            +
                    :check_in_type => "cron"
         | 
| 242 | 
            +
                  )).and_return(Net::HTTPResponse.new(nil, "499", nil))
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                  expect(Appsignal.internal_logger).not_to receive(:debug)
         | 
| 245 | 
            +
                  expect(Appsignal.internal_logger).to receive(:error).with(
         | 
| 246 | 
            +
                    "Failed to transmit cron check-in finish event: status code was 499"
         | 
| 247 | 
            +
                  )
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                  cron_checkin.finish
         | 
| 250 | 
            +
                end
         | 
| 251 | 
            +
              end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
              describe ".cron" do
         | 
| 254 | 
            +
                describe "when a block is given" do
         | 
| 255 | 
            +
                  it "should send a cron check-in start and finish and return the block output" do
         | 
| 256 | 
            +
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 257 | 
            +
                      :kind => "start",
         | 
| 258 | 
            +
                      :identifier => "cron-checkin-with-block",
         | 
| 259 | 
            +
                      :check_in_type => "cron"
         | 
| 260 | 
            +
                    )).and_return(nil)
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 263 | 
            +
                      :kind => "finish",
         | 
| 264 | 
            +
                      :identifier => "cron-checkin-with-block",
         | 
| 265 | 
            +
                      :check_in_type => "cron"
         | 
| 266 | 
            +
                    )).and_return(nil)
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                    output = Appsignal::CheckIn.cron("cron-checkin-with-block") { "output" }
         | 
| 269 | 
            +
                    expect(output).to eq("output")
         | 
| 270 | 
            +
                  end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                  it "should not send a cron check-in finish event when an error is raised" do
         | 
| 273 | 
            +
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 274 | 
            +
                      :kind => "start",
         | 
| 275 | 
            +
                      :identifier => "cron-checkin-with-block",
         | 
| 276 | 
            +
                      :check_in_type => "cron"
         | 
| 277 | 
            +
                    )).and_return(nil)
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    expect(transmitter).not_to receive(:transmit).with(hash_including(
         | 
| 280 | 
            +
                      :kind => "finish",
         | 
| 281 | 
            +
                      :identifier => "cron-checkin-with-block",
         | 
| 282 | 
            +
                      :check_in_type => "cron"
         | 
| 283 | 
            +
                    ))
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                    expect do
         | 
| 286 | 
            +
                      Appsignal::CheckIn.cron("cron-checkin-with-block") { raise "error" }
         | 
| 287 | 
            +
                    end.to raise_error(RuntimeError, "error")
         | 
| 288 | 
            +
                  end
         | 
| 289 | 
            +
                end
         | 
| 290 | 
            +
             | 
| 291 | 
            +
                describe "when no block is given" do
         | 
| 292 | 
            +
                  it "should only send a cron check-in finish event" do
         | 
| 293 | 
            +
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 294 | 
            +
                      :kind => "finish",
         | 
| 295 | 
            +
                      :identifier => "cron-checkin-without-block",
         | 
| 296 | 
            +
                      :check_in_type => "cron"
         | 
| 297 | 
            +
                    )).and_return(nil)
         | 
| 298 | 
            +
             | 
| 299 | 
            +
                    Appsignal::CheckIn.cron("cron-checkin-without-block")
         | 
| 300 | 
            +
                  end
         | 
| 301 | 
            +
                end
         | 
| 302 | 
            +
              end
         | 
| 303 | 
            +
             | 
| 304 | 
            +
              describe "#initialize" do
         | 
| 305 | 
            +
                describe "when initialised with deprecated heartbeat keyword names" do
         | 
| 306 | 
            +
                  let(:err_stream) { std_stream }
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                  after do
         | 
| 309 | 
            +
                    described_class.instance_variable_set(:@initializer_deprecation_warning_emitted, false)
         | 
| 310 | 
            +
                  end
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                  it "can be initialised" do
         | 
| 313 | 
            +
                    cron_checkin = described_class.new(:name => "cron-checkin-name")
         | 
| 314 | 
            +
                    expect(cron_checkin.identifier).to eq("cron-checkin-name")
         | 
| 315 | 
            +
                  end
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                  it "logs a deprecation warning" do
         | 
| 318 | 
            +
                    capture_std_streams(std_stream, err_stream) do
         | 
| 319 | 
            +
                      expect(described_class.new(:name => "cron-checkin-name"))
         | 
| 320 | 
            +
                        .to be_a(Appsignal::CheckIn::Cron)
         | 
| 321 | 
            +
                    end
         | 
| 322 | 
            +
             | 
| 323 | 
            +
                    expect(err_stream.read)
         | 
| 324 | 
            +
                      .to include(
         | 
| 325 | 
            +
                        "appsignal WARNING: Passing a `name` keyword argument to " \
         | 
| 326 | 
            +
                          "`Appsignal::CheckIn::Cron.new` is deprecated."
         | 
| 327 | 
            +
                      )
         | 
| 328 | 
            +
                  end
         | 
| 329 | 
            +
                end
         | 
| 330 | 
            +
             | 
| 331 | 
            +
                it "can be initialised with cron check-in keyword names" do
         | 
| 332 | 
            +
                  cron_checkin = described_class.new(:identifier => "cron-checkin-name")
         | 
| 333 | 
            +
                  expect(cron_checkin.identifier).to eq("cron-checkin-name")
         | 
| 334 | 
            +
                end
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                it "raises an error when no identifier is given" do
         | 
| 337 | 
            +
                  expect do
         | 
| 338 | 
            +
                    described_class.new
         | 
| 339 | 
            +
                  end.to raise_error(ArgumentError, "missing keyword: :identifier")
         | 
| 340 | 
            +
                end
         | 
| 341 | 
            +
              end
         | 
| 342 | 
            +
            end
         | 
| @@ -67,27 +67,6 @@ if DependencyHelper.http_present? | |
| 67 67 | 
             
                  end
         | 
| 68 68 | 
             
                end
         | 
| 69 69 |  | 
| 70 | 
            -
                context "with an HTTP exception" do
         | 
| 71 | 
            -
                  let(:error) { ExampleException.new("oh no!") }
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  it "reports the exception and re-raises it" do
         | 
| 74 | 
            -
                    stub_request(:get, "https://www.google.com").and_raise(error)
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                    expect do
         | 
| 77 | 
            -
                      HTTP.get("https://www.google.com")
         | 
| 78 | 
            -
                    end.to raise_error(ExampleException)
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                    expect(transaction).to have_namespace(Appsignal::Transaction::HTTP_REQUEST)
         | 
| 81 | 
            -
                    expect(transaction).to include_event(
         | 
| 82 | 
            -
                      "body" => "",
         | 
| 83 | 
            -
                      "body_format" => Appsignal::EventFormatter::DEFAULT,
         | 
| 84 | 
            -
                      "name" => "request.http_rb",
         | 
| 85 | 
            -
                      "title" => "GET https://www.google.com"
         | 
| 86 | 
            -
                    )
         | 
| 87 | 
            -
                    expect(transaction).to have_error(error.class.name, error.message)
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 70 | 
             
                context "with various URI objects" do
         | 
| 92 71 | 
             
                  it "parses an object responding to #to_s" do
         | 
| 93 72 | 
             
                    request_uri = Struct.new(:uri) do
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: appsignal
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.13.0
         | 
| 5 5 | 
             
            platform: java
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Robert Beekman
         | 
| @@ -10,7 +10,7 @@ authors: | |
| 10 10 | 
             
            autorequire:
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date: 2024-08- | 
| 13 | 
            +
            date: 2024-08-14 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: rack
         | 
| @@ -200,6 +200,8 @@ files: | |
| 200 200 | 
             
            - lib/appsignal.rb
         | 
| 201 201 | 
             
            - lib/appsignal/auth_check.rb
         | 
| 202 202 | 
             
            - lib/appsignal/capistrano.rb
         | 
| 203 | 
            +
            - lib/appsignal/check_in.rb
         | 
| 204 | 
            +
            - lib/appsignal/check_in/cron.rb
         | 
| 203 205 | 
             
            - lib/appsignal/cli.rb
         | 
| 204 206 | 
             
            - lib/appsignal/cli/demo.rb
         | 
| 205 207 | 
             
            - lib/appsignal/cli/diagnose.rb
         | 
| @@ -223,8 +225,7 @@ files: | |
| 223 225 | 
             
            - lib/appsignal/extension.rb
         | 
| 224 226 | 
             
            - lib/appsignal/extension/jruby.rb
         | 
| 225 227 | 
             
            - lib/appsignal/garbage_collection.rb
         | 
| 226 | 
            -
            - lib/appsignal/heartbeat.rb
         | 
| 227 | 
            -
            - lib/appsignal/helpers/heartbeats.rb
         | 
| 228 | 
            +
            - lib/appsignal/helpers/heartbeat.rb
         | 
| 228 229 | 
             
            - lib/appsignal/helpers/instrumentation.rb
         | 
| 229 230 | 
             
            - lib/appsignal/helpers/metrics.rb
         | 
| 230 231 | 
             
            - lib/appsignal/hooks.rb
         | 
| @@ -326,6 +327,7 @@ files: | |
| 326 327 | 
             
            - spec/lib/appsignal/auth_check_spec.rb
         | 
| 327 328 | 
             
            - spec/lib/appsignal/capistrano2_spec.rb
         | 
| 328 329 | 
             
            - spec/lib/appsignal/capistrano3_spec.rb
         | 
| 330 | 
            +
            - spec/lib/appsignal/check_in_spec.rb
         | 
| 329 331 | 
             
            - spec/lib/appsignal/cli/demo_spec.rb
         | 
| 330 332 | 
             
            - spec/lib/appsignal/cli/diagnose/paths_spec.rb
         | 
| 331 333 | 
             
            - spec/lib/appsignal/cli/diagnose/utils_spec.rb
         | 
| @@ -350,7 +352,6 @@ files: | |
| 350 352 | 
             
            - spec/lib/appsignal/extension_install_failure_spec.rb
         | 
| 351 353 | 
             
            - spec/lib/appsignal/extension_spec.rb
         | 
| 352 354 | 
             
            - spec/lib/appsignal/garbage_collection_spec.rb
         | 
| 353 | 
            -
            - spec/lib/appsignal/heartbeat_spec.rb
         | 
| 354 355 | 
             
            - spec/lib/appsignal/hooks/action_cable_spec.rb
         | 
| 355 356 | 
             
            - spec/lib/appsignal/hooks/action_mailer_spec.rb
         | 
| 356 357 | 
             
            - spec/lib/appsignal/hooks/active_support_notifications/finish_with_state_shared_examples.rb
         | 
| @@ -502,7 +503,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 502 503 | 
             
                - !ruby/object:Gem::Version
         | 
| 503 504 | 
             
                  version: '0'
         | 
| 504 505 | 
             
            requirements: []
         | 
| 505 | 
            -
            rubygems_version: 3. | 
| 506 | 
            +
            rubygems_version: 3.3.7
         | 
| 506 507 | 
             
            signing_key:
         | 
| 507 508 | 
             
            specification_version: 4
         | 
| 508 509 | 
             
            summary: Logs performance and exception data from your app to appsignal.com
         | 
    
        data/lib/appsignal/heartbeat.rb
    DELETED
    
    | @@ -1,59 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Appsignal
         | 
| 4 | 
            -
              class Heartbeat
         | 
| 5 | 
            -
                class << self
         | 
| 6 | 
            -
                  # @api private
         | 
| 7 | 
            -
                  def transmitter
         | 
| 8 | 
            -
                    @transmitter ||= Appsignal::Transmitter.new(
         | 
| 9 | 
            -
                      "#{Appsignal.config[:logging_endpoint]}/heartbeats/json"
         | 
| 10 | 
            -
                    )
         | 
| 11 | 
            -
                  end
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                attr_reader :name, :id
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                def initialize(name:)
         | 
| 17 | 
            -
                  @name = name
         | 
| 18 | 
            -
                  @id = SecureRandom.hex(8)
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                def start
         | 
| 22 | 
            -
                  transmit_event("start")
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                def finish
         | 
| 26 | 
            -
                  transmit_event("finish")
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                private
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                def event(kind)
         | 
| 32 | 
            -
                  {
         | 
| 33 | 
            -
                    :name => name,
         | 
| 34 | 
            -
                    :id => @id,
         | 
| 35 | 
            -
                    :kind => kind,
         | 
| 36 | 
            -
                    :timestamp => Time.now.utc.to_i
         | 
| 37 | 
            -
                  }
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                def transmit_event(kind)
         | 
| 41 | 
            -
                  unless Appsignal.active?
         | 
| 42 | 
            -
                    Appsignal.internal_logger.debug("AppSignal not active, not transmitting heartbeat event")
         | 
| 43 | 
            -
                    return
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  response = self.class.transmitter.transmit(event(kind))
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                  if response.code.to_i >= 200 && response.code.to_i < 300
         | 
| 49 | 
            -
                    Appsignal.internal_logger.debug("Transmitted heartbeat `#{name}` (#{id}) #{kind} event")
         | 
| 50 | 
            -
                  else
         | 
| 51 | 
            -
                    Appsignal.internal_logger.error(
         | 
| 52 | 
            -
                      "Failed to transmit heartbeat event: status code was #{response.code}"
         | 
| 53 | 
            -
                    )
         | 
| 54 | 
            -
                  end
         | 
| 55 | 
            -
                rescue => e
         | 
| 56 | 
            -
                  Appsignal.internal_logger.error("Failed to transmit heartbeat event: #{e}")
         | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
              end
         | 
| 59 | 
            -
            end
         | 
| @@ -1,44 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Appsignal
         | 
| 4 | 
            -
              module Helpers
         | 
| 5 | 
            -
                module Heartbeats
         | 
| 6 | 
            -
                  # Track heartbeats
         | 
| 7 | 
            -
                  #
         | 
| 8 | 
            -
                  # Track the execution of certain processes by sending a hearbeat.
         | 
| 9 | 
            -
                  #
         | 
| 10 | 
            -
                  # To track the duration of a piece of code, pass a block to {.heartbeat}
         | 
| 11 | 
            -
                  # to report both when the process starts, and when it finishes.
         | 
| 12 | 
            -
                  #
         | 
| 13 | 
            -
                  # If an exception is raised within the block, the finish event will not
         | 
| 14 | 
            -
                  # be reported, triggering a notification about the missing heartbeat. The
         | 
| 15 | 
            -
                  # exception will bubble outside of the heartbeat block.
         | 
| 16 | 
            -
                  #
         | 
| 17 | 
            -
                  # @example Send a heartbeat
         | 
| 18 | 
            -
                  #   Appsignal.heartbeat("send_invoices")
         | 
| 19 | 
            -
                  #
         | 
| 20 | 
            -
                  # @example Send a heartbeat with duration
         | 
| 21 | 
            -
                  #   Appsignal.heartbeat("send_invoices") do
         | 
| 22 | 
            -
                  #     # your code
         | 
| 23 | 
            -
                  #   end
         | 
| 24 | 
            -
                  #
         | 
| 25 | 
            -
                  # @param name [String] name of the heartbeat to report.
         | 
| 26 | 
            -
                  # @yield the block to monitor.
         | 
| 27 | 
            -
                  # @return [void]
         | 
| 28 | 
            -
                  # @since 3.7.0
         | 
| 29 | 
            -
                  # @see https://docs.appsignal.com/heartbeats
         | 
| 30 | 
            -
                  def heartbeat(name)
         | 
| 31 | 
            -
                    heartbeat = Appsignal::Heartbeat.new(:name => name)
         | 
| 32 | 
            -
                    output = nil
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                    if block_given?
         | 
| 35 | 
            -
                      heartbeat.start
         | 
| 36 | 
            -
                      output = yield
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                    heartbeat.finish
         | 
| 40 | 
            -
                    output
         | 
| 41 | 
            -
                  end
         | 
| 42 | 
            -
                end
         | 
| 43 | 
            -
              end
         | 
| 44 | 
            -
            end
         | 
| @@ -1,127 +0,0 @@ | |
| 1 | 
            -
            describe Appsignal::Heartbeat do
         | 
| 2 | 
            -
              let(:config) { project_fixture_config }
         | 
| 3 | 
            -
              let(:heartbeat) { described_class.new(:name => "heartbeat-name") }
         | 
| 4 | 
            -
              let(:transmitter) { Appsignal::Transmitter.new("http://heartbeats/", config) }
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              before(:each) do
         | 
| 7 | 
            -
                allow(Appsignal).to receive(:active?).and_return(true)
         | 
| 8 | 
            -
                config.logger = Logger.new(StringIO.new)
         | 
| 9 | 
            -
                allow(Appsignal::Heartbeat).to receive(:transmitter).and_return(transmitter)
         | 
| 10 | 
            -
              end
         | 
| 11 | 
            -
             | 
| 12 | 
            -
              describe "when Appsignal is not active" do
         | 
| 13 | 
            -
                it "should not transmit any events" do
         | 
| 14 | 
            -
                  allow(Appsignal).to receive(:active?).and_return(false)
         | 
| 15 | 
            -
                  expect(transmitter).not_to receive(:transmit)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                  heartbeat.start
         | 
| 18 | 
            -
                  heartbeat.finish
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
              end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
              describe "#start" do
         | 
| 23 | 
            -
                it "should send a heartbeat start" do
         | 
| 24 | 
            -
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 25 | 
            -
                    :name => "heartbeat-name",
         | 
| 26 | 
            -
                    :kind => "start"
         | 
| 27 | 
            -
                  )).and_return(Net::HTTPResponse.new(nil, "200", nil))
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  expect(Appsignal.internal_logger).to receive(:debug).with(
         | 
| 30 | 
            -
                    "Transmitted heartbeat `heartbeat-name` (#{heartbeat.id}) start event"
         | 
| 31 | 
            -
                  )
         | 
| 32 | 
            -
                  expect(Appsignal.internal_logger).not_to receive(:error)
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                  heartbeat.start
         | 
| 35 | 
            -
                end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                it "should log an error if it fails" do
         | 
| 38 | 
            -
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 39 | 
            -
                    :name => "heartbeat-name",
         | 
| 40 | 
            -
                    :kind => "start"
         | 
| 41 | 
            -
                  )).and_return(Net::HTTPResponse.new(nil, "499", nil))
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  expect(Appsignal.internal_logger).not_to receive(:debug)
         | 
| 44 | 
            -
                  expect(Appsignal.internal_logger).to receive(:error).with(
         | 
| 45 | 
            -
                    "Failed to transmit heartbeat event: status code was 499"
         | 
| 46 | 
            -
                  )
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                  heartbeat.start
         | 
| 49 | 
            -
                end
         | 
| 50 | 
            -
              end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
              describe "#finish" do
         | 
| 53 | 
            -
                it "should send a heartbeat finish" do
         | 
| 54 | 
            -
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 55 | 
            -
                    :name => "heartbeat-name",
         | 
| 56 | 
            -
                    :kind => "finish"
         | 
| 57 | 
            -
                  )).and_return(Net::HTTPResponse.new(nil, "200", nil))
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                  expect(Appsignal.internal_logger).to receive(:debug).with(
         | 
| 60 | 
            -
                    "Transmitted heartbeat `heartbeat-name` (#{heartbeat.id}) finish event"
         | 
| 61 | 
            -
                  )
         | 
| 62 | 
            -
                  expect(Appsignal.internal_logger).not_to receive(:error)
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                  heartbeat.finish
         | 
| 65 | 
            -
                end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                it "should log an error if it fails" do
         | 
| 68 | 
            -
                  expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 69 | 
            -
                    :name => "heartbeat-name",
         | 
| 70 | 
            -
                    :kind => "finish"
         | 
| 71 | 
            -
                  )).and_return(Net::HTTPResponse.new(nil, "499", nil))
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  expect(Appsignal.internal_logger).not_to receive(:debug)
         | 
| 74 | 
            -
                  expect(Appsignal.internal_logger).to receive(:error).with(
         | 
| 75 | 
            -
                    "Failed to transmit heartbeat event: status code was 499"
         | 
| 76 | 
            -
                  )
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                  heartbeat.finish
         | 
| 79 | 
            -
                end
         | 
| 80 | 
            -
              end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
              describe ".heartbeat" do
         | 
| 83 | 
            -
                describe "when a block is given" do
         | 
| 84 | 
            -
                  it "should send a heartbeat start and finish and return the block output" do
         | 
| 85 | 
            -
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 86 | 
            -
                      :kind => "start",
         | 
| 87 | 
            -
                      :name => "heartbeat-with-block"
         | 
| 88 | 
            -
                    )).and_return(nil)
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 91 | 
            -
                      :kind => "finish",
         | 
| 92 | 
            -
                      :name => "heartbeat-with-block"
         | 
| 93 | 
            -
                    )).and_return(nil)
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                    output = Appsignal.heartbeat("heartbeat-with-block") { "output" }
         | 
| 96 | 
            -
                    expect(output).to eq("output")
         | 
| 97 | 
            -
                  end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                  it "should not send a heartbeat finish event when an error is raised" do
         | 
| 100 | 
            -
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 101 | 
            -
                      :kind => "start",
         | 
| 102 | 
            -
                      :name => "heartbeat-with-block"
         | 
| 103 | 
            -
                    )).and_return(nil)
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                    expect(transmitter).not_to receive(:transmit).with(hash_including(
         | 
| 106 | 
            -
                      :kind => "finish",
         | 
| 107 | 
            -
                      :name => "heartbeat-with-block"
         | 
| 108 | 
            -
                    ))
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                    expect do
         | 
| 111 | 
            -
                      Appsignal.heartbeat("heartbeat-with-block") { raise "error" }
         | 
| 112 | 
            -
                    end.to raise_error(RuntimeError, "error")
         | 
| 113 | 
            -
                  end
         | 
| 114 | 
            -
                end
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                describe "when no block is given" do
         | 
| 117 | 
            -
                  it "should only send a heartbeat finish event" do
         | 
| 118 | 
            -
                    expect(transmitter).to receive(:transmit).with(hash_including(
         | 
| 119 | 
            -
                      :kind => "finish",
         | 
| 120 | 
            -
                      :name => "heartbeat-without-block"
         | 
| 121 | 
            -
                    )).and_return(nil)
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                    Appsignal.heartbeat("heartbeat-without-block")
         | 
| 124 | 
            -
                  end
         | 
| 125 | 
            -
                end
         | 
| 126 | 
            -
              end
         | 
| 127 | 
            -
            end
         |