sentry-ruby 0.3.0 → 4.3.0
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/README.md +102 -24
- metadata +41 -54
- data/.craft.yml +0 -19
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -31
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -16
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/sentry/backtrace.rb +0 -128
- data/lib/sentry/benchmarks/benchmark_transport.rb +0 -14
- data/lib/sentry/breadcrumb/sentry_logger.rb +0 -87
- data/lib/sentry/breadcrumb.rb +0 -25
- data/lib/sentry/breadcrumb_buffer.rb +0 -47
- data/lib/sentry/client.rb +0 -80
- data/lib/sentry/configuration.rb +0 -387
- data/lib/sentry/core_ext/object/deep_dup.rb +0 -57
- data/lib/sentry/core_ext/object/duplicable.rb +0 -153
- data/lib/sentry/dsn.rb +0 -48
- data/lib/sentry/event.rb +0 -177
- data/lib/sentry/hub.rb +0 -137
- data/lib/sentry/interface.rb +0 -22
- data/lib/sentry/interfaces/exception.rb +0 -11
- data/lib/sentry/interfaces/request.rb +0 -95
- data/lib/sentry/interfaces/single_exception.rb +0 -14
- data/lib/sentry/interfaces/stacktrace.rb +0 -57
- data/lib/sentry/linecache.rb +0 -44
- data/lib/sentry/logger.rb +0 -20
- data/lib/sentry/rack/capture_exception.rb +0 -45
- data/lib/sentry/rack/tracing.rb +0 -39
- data/lib/sentry/rack.rb +0 -5
- data/lib/sentry/scope.rb +0 -214
- data/lib/sentry/span.rb +0 -155
- data/lib/sentry/transaction.rb +0 -113
- data/lib/sentry/transaction_event.rb +0 -29
- data/lib/sentry/transport/configuration.rb +0 -21
- data/lib/sentry/transport/dummy_transport.rb +0 -14
- data/lib/sentry/transport/http_transport.rb +0 -65
- data/lib/sentry/transport/state.rb +0 -40
- data/lib/sentry/transport.rb +0 -97
- data/lib/sentry/utils/exception_cause_chain.rb +0 -20
- data/lib/sentry/utils/real_ip.rb +0 -70
- data/lib/sentry/utils/request_id.rb +0 -16
- data/lib/sentry/version.rb +0 -3
- data/lib/sentry-ruby.rb +0 -123
- data/sentry-ruby.gemspec +0 -26
    
        data/lib/sentry/backtrace.rb
    DELETED
    
    | @@ -1,128 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            ## Inspired by Rails' and Airbrake's backtrace parsers.
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module Sentry
         | 
| 6 | 
            -
              # Front end to parsing the backtrace for each notice
         | 
| 7 | 
            -
              class Backtrace
         | 
| 8 | 
            -
                # Handles backtrace parsing line by line
         | 
| 9 | 
            -
                class Line
         | 
| 10 | 
            -
                  RB_EXTENSION = ".rb"
         | 
| 11 | 
            -
                  # regexp (optional leading X: on windows, or JRuby9000 class-prefix)
         | 
| 12 | 
            -
                  RUBY_INPUT_FORMAT = /
         | 
| 13 | 
            -
                    ^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
         | 
| 14 | 
            -
                    (\d+)
         | 
| 15 | 
            -
                    (?: :in \s `([^']+)')?$
         | 
| 16 | 
            -
                  /x.freeze
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                  # org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
         | 
| 19 | 
            -
                  JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                  # The file portion of the line (such as app/models/user.rb)
         | 
| 22 | 
            -
                  attr_reader :file
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  # The line number portion of the line
         | 
| 25 | 
            -
                  attr_reader :number
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                  # The method of the line (such as index)
         | 
| 28 | 
            -
                  attr_reader :method
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  # The module name (JRuby)
         | 
| 31 | 
            -
                  attr_reader :module_name
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                  attr_reader :in_app_pattern
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  # Parses a single line of a given backtrace
         | 
| 36 | 
            -
                  # @param [String] unparsed_line The raw line from +caller+ or some backtrace
         | 
| 37 | 
            -
                  # @return [Line] The parsed backtrace line
         | 
| 38 | 
            -
                  def self.parse(unparsed_line, in_app_pattern)
         | 
| 39 | 
            -
                    ruby_match = unparsed_line.match(RUBY_INPUT_FORMAT)
         | 
| 40 | 
            -
                    if ruby_match
         | 
| 41 | 
            -
                      _, file, number, method = ruby_match.to_a
         | 
| 42 | 
            -
                      file.sub!(/\.class$/, RB_EXTENSION)
         | 
| 43 | 
            -
                      module_name = nil
         | 
| 44 | 
            -
                    else
         | 
| 45 | 
            -
                      java_match = unparsed_line.match(JAVA_INPUT_FORMAT)
         | 
| 46 | 
            -
                      _, module_name, method, file, number = java_match.to_a
         | 
| 47 | 
            -
                    end
         | 
| 48 | 
            -
                    new(file, number, method, module_name, in_app_pattern)
         | 
| 49 | 
            -
                  end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                  def initialize(file, number, method, module_name, in_app_pattern)
         | 
| 52 | 
            -
                    @file = file
         | 
| 53 | 
            -
                    @module_name = module_name
         | 
| 54 | 
            -
                    @number = number.to_i
         | 
| 55 | 
            -
                    @method = method
         | 
| 56 | 
            -
                    @in_app_pattern = in_app_pattern
         | 
| 57 | 
            -
                  end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                  def in_app
         | 
| 60 | 
            -
                    if file =~ in_app_pattern
         | 
| 61 | 
            -
                      true
         | 
| 62 | 
            -
                    else
         | 
| 63 | 
            -
                      false
         | 
| 64 | 
            -
                    end
         | 
| 65 | 
            -
                  end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                  # Reconstructs the line in a readable fashion
         | 
| 68 | 
            -
                  def to_s
         | 
| 69 | 
            -
                    "#{file}:#{number}:in `#{method}'"
         | 
| 70 | 
            -
                  end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                  def ==(other)
         | 
| 73 | 
            -
                    to_s == other.to_s
         | 
| 74 | 
            -
                  end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  def inspect
         | 
| 77 | 
            -
                    "<Line:#{self}>"
         | 
| 78 | 
            -
                  end
         | 
| 79 | 
            -
                end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                # holder for an Array of Backtrace::Line instances
         | 
| 84 | 
            -
                attr_reader :lines
         | 
| 85 | 
            -
                attr_reader :configuration
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                def self.parse(backtrace, configuration:)
         | 
| 88 | 
            -
                  ruby_lines = backtrace.is_a?(Array) ? backtrace : backtrace.split(/\n\s*/)
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                  ruby_lines = configuration.backtrace_cleanup_callback.call(ruby_lines) if configuration&.backtrace_cleanup_callback
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                  in_app_pattern ||= begin
         | 
| 93 | 
            -
                    project_root = configuration.project_root&.to_s
         | 
| 94 | 
            -
                    Regexp.new("^(#{project_root}/)?#{configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
         | 
| 95 | 
            -
                  end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                  lines = ruby_lines.to_a.map do |unparsed_line|
         | 
| 98 | 
            -
                    Line.parse(unparsed_line, in_app_pattern)
         | 
| 99 | 
            -
                  end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  new(lines)
         | 
| 102 | 
            -
                end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                def initialize(lines)
         | 
| 105 | 
            -
                  @lines = lines
         | 
| 106 | 
            -
                end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                def inspect
         | 
| 109 | 
            -
                  "<Backtrace: " + lines.map(&:inspect).join(", ") + ">"
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                def to_s
         | 
| 113 | 
            -
                  content = []
         | 
| 114 | 
            -
                  lines.each do |line|
         | 
| 115 | 
            -
                    content << line
         | 
| 116 | 
            -
                  end
         | 
| 117 | 
            -
                  content.join("\n")
         | 
| 118 | 
            -
                end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                def ==(other)
         | 
| 121 | 
            -
                  if other.respond_to?(:lines)
         | 
| 122 | 
            -
                    lines == other.lines
         | 
| 123 | 
            -
                  else
         | 
| 124 | 
            -
                    false
         | 
| 125 | 
            -
                  end
         | 
| 126 | 
            -
                end
         | 
| 127 | 
            -
              end
         | 
| 128 | 
            -
            end
         | 
| @@ -1,87 +0,0 @@ | |
| 1 | 
            -
            require 'logger'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sentry
         | 
| 4 | 
            -
              class Breadcrumb
         | 
| 5 | 
            -
                module SentryLogger
         | 
| 6 | 
            -
                  LEVELS = {
         | 
| 7 | 
            -
                    ::Logger::DEBUG => 'debug',
         | 
| 8 | 
            -
                    ::Logger::INFO => 'info',
         | 
| 9 | 
            -
                    ::Logger::WARN => 'warn',
         | 
| 10 | 
            -
                    ::Logger::ERROR => 'error',
         | 
| 11 | 
            -
                    ::Logger::FATAL => 'fatal'
         | 
| 12 | 
            -
                  }.freeze
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  def add(*args, &block)
         | 
| 15 | 
            -
                    super
         | 
| 16 | 
            -
                    add_breadcrumb(*args, &block)
         | 
| 17 | 
            -
                  end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  def add_breadcrumb(severity, message = nil, progname = nil)
         | 
| 20 | 
            -
                    # because the breadcrumbs now belongs to different Hub's Scope in different threads
         | 
| 21 | 
            -
                    # we need to make sure the current thread's Hub has been set before adding breadcrumbs
         | 
| 22 | 
            -
                    return unless Sentry.get_current_hub
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    category = "logger"
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                    # this is because the nature of Ruby Logger class:
         | 
| 27 | 
            -
                    #
         | 
| 28 | 
            -
                    # when given 1 argument, the argument will become both message and progname
         | 
| 29 | 
            -
                    #
         | 
| 30 | 
            -
                    # ```
         | 
| 31 | 
            -
                    # logger.info("foo")
         | 
| 32 | 
            -
                    # # message == progname == "foo"
         | 
| 33 | 
            -
                    # ```
         | 
| 34 | 
            -
                    #
         | 
| 35 | 
            -
                    # and to specify progname with a different message,
         | 
| 36 | 
            -
                    # we need to pass the progname as the argument and pass the message as a proc
         | 
| 37 | 
            -
                    #
         | 
| 38 | 
            -
                    # ```
         | 
| 39 | 
            -
                    # logger.info("progname") { "the message" }
         | 
| 40 | 
            -
                    # ```
         | 
| 41 | 
            -
                    #
         | 
| 42 | 
            -
                    # so the condition below is to replicate the similar behavior
         | 
| 43 | 
            -
                    if message.nil?
         | 
| 44 | 
            -
                      if block_given?
         | 
| 45 | 
            -
                        message = yield
         | 
| 46 | 
            -
                        category = progname
         | 
| 47 | 
            -
                      else
         | 
| 48 | 
            -
                        message = progname
         | 
| 49 | 
            -
                      end
         | 
| 50 | 
            -
                    end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                    return if ignored_logger?(progname) || message.empty?
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                    # some loggers will add leading/trailing space as they (incorrectly, mind you)
         | 
| 55 | 
            -
                    # think of logging as a shortcut to std{out,err}
         | 
| 56 | 
            -
                    message = message.to_s.strip
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                    last_crumb = current_breadcrumbs.peek
         | 
| 59 | 
            -
                    # try to avoid dupes from logger broadcasts
         | 
| 60 | 
            -
                    if last_crumb.nil? || last_crumb.message != message
         | 
| 61 | 
            -
                      level = Sentry::Breadcrumb::SentryLogger::LEVELS.fetch(severity, nil)
         | 
| 62 | 
            -
                      crumb = Sentry::Breadcrumb.new(
         | 
| 63 | 
            -
                        level: level,
         | 
| 64 | 
            -
                        category: category,
         | 
| 65 | 
            -
                        message: message,
         | 
| 66 | 
            -
                        type: severity >= 3 ? "error" : level
         | 
| 67 | 
            -
                      )
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                      Sentry.add_breadcrumb(crumb)
         | 
| 70 | 
            -
                    end
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  private
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  def ignored_logger?(progname)
         | 
| 76 | 
            -
                    progname == LOGGER_PROGNAME ||
         | 
| 77 | 
            -
                      Sentry.configuration.exclude_loggers.include?(progname)
         | 
| 78 | 
            -
                  end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
                  def current_breadcrumbs
         | 
| 81 | 
            -
                    Sentry.get_current_scope.breadcrumbs
         | 
| 82 | 
            -
                  end
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
              end
         | 
| 85 | 
            -
            end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
            ::Logger.send(:prepend, Sentry::Breadcrumb::SentryLogger)
         | 
    
        data/lib/sentry/breadcrumb.rb
    DELETED
    
    | @@ -1,25 +0,0 @@ | |
| 1 | 
            -
            module Sentry
         | 
| 2 | 
            -
              class Breadcrumb
         | 
| 3 | 
            -
                attr_accessor :category, :data, :message, :level, :timestamp, :type
         | 
| 4 | 
            -
             | 
| 5 | 
            -
                def initialize(category: nil, data: nil, message: nil, timestamp: nil, level: nil, type: nil)
         | 
| 6 | 
            -
                  @category = category
         | 
| 7 | 
            -
                  @data = data || {}
         | 
| 8 | 
            -
                  @level = level
         | 
| 9 | 
            -
                  @message = message
         | 
| 10 | 
            -
                  @timestamp = timestamp || Sentry.utc_now.to_i
         | 
| 11 | 
            -
                  @type = type
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                def to_hash
         | 
| 15 | 
            -
                  {
         | 
| 16 | 
            -
                    :category => @category,
         | 
| 17 | 
            -
                    :data => @data,
         | 
| 18 | 
            -
                    :level => @level,
         | 
| 19 | 
            -
                    :message => @message,
         | 
| 20 | 
            -
                    :timestamp => @timestamp,
         | 
| 21 | 
            -
                    :type => @type
         | 
| 22 | 
            -
                  }
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
              end
         | 
| 25 | 
            -
            end
         | 
| @@ -1,47 +0,0 @@ | |
| 1 | 
            -
            require "sentry/breadcrumb"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sentry
         | 
| 4 | 
            -
              class BreadcrumbBuffer
         | 
| 5 | 
            -
                include Enumerable
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                attr_accessor :buffer
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                def initialize(size = 100)
         | 
| 10 | 
            -
                  @buffer = Array.new(size)
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def record(crumb)
         | 
| 14 | 
            -
                  yield(crumb) if block_given?
         | 
| 15 | 
            -
                  @buffer.slice!(0)
         | 
| 16 | 
            -
                  @buffer << crumb
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                def members
         | 
| 20 | 
            -
                  @buffer.compact
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                def peek
         | 
| 24 | 
            -
                  members.last
         | 
| 25 | 
            -
                end
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                def each(&block)
         | 
| 28 | 
            -
                  members.each(&block)
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                def empty?
         | 
| 32 | 
            -
                  members.none?
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def to_hash
         | 
| 36 | 
            -
                  {
         | 
| 37 | 
            -
                    :values => members.map(&:to_hash)
         | 
| 38 | 
            -
                  }
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                def dup
         | 
| 42 | 
            -
                  copy = super
         | 
| 43 | 
            -
                  copy.buffer = buffer.deep_dup
         | 
| 44 | 
            -
                  copy
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
            end
         | 
    
        data/lib/sentry/client.rb
    DELETED
    
    | @@ -1,80 +0,0 @@ | |
| 1 | 
            -
            require "sentry/transport"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module Sentry
         | 
| 4 | 
            -
              class Client
         | 
| 5 | 
            -
                attr_reader :transport, :configuration
         | 
| 6 | 
            -
             | 
| 7 | 
            -
                def initialize(configuration)
         | 
| 8 | 
            -
                  @configuration = configuration
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  if transport_class = configuration.transport.transport_class
         | 
| 11 | 
            -
                    @transport = transport_class.new(configuration)
         | 
| 12 | 
            -
                  else
         | 
| 13 | 
            -
                    @transport =
         | 
| 14 | 
            -
                      case configuration.dsn&.scheme
         | 
| 15 | 
            -
                      when 'http', 'https'
         | 
| 16 | 
            -
                        HTTPTransport.new(configuration)
         | 
| 17 | 
            -
                      else
         | 
| 18 | 
            -
                        DummyTransport.new(configuration)
         | 
| 19 | 
            -
                      end
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                def capture_event(event, scope, hint = nil)
         | 
| 24 | 
            -
                  scope.apply_to_event(event, hint)
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                  if configuration.async?
         | 
| 27 | 
            -
                    begin
         | 
| 28 | 
            -
                      # We have to convert to a JSON-like hash, because background job
         | 
| 29 | 
            -
                      # processors (esp ActiveJob) may not like weird types in the event hash
         | 
| 30 | 
            -
                      configuration.async.call(event.to_json_compatible)
         | 
| 31 | 
            -
                    rescue => e
         | 
| 32 | 
            -
                      configuration.logger.error(LOGGER_PROGNAME) { "async event sending failed: #{e.message}" }
         | 
| 33 | 
            -
                      send_event(event, hint)
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
                  else
         | 
| 36 | 
            -
                    send_event(event, hint)
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                  event
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                def event_from_exception(exception)
         | 
| 43 | 
            -
                  return unless @configuration.exception_class_allowed?(exception)
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                  Event.new(configuration: configuration).tap do |event|
         | 
| 46 | 
            -
                    event.add_exception_interface(exception)
         | 
| 47 | 
            -
                  end
         | 
| 48 | 
            -
                end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                def event_from_message(message)
         | 
| 51 | 
            -
                  Event.new(configuration: configuration, message: message)
         | 
| 52 | 
            -
                end
         | 
| 53 | 
            -
             | 
| 54 | 
            -
                def event_from_transaction(transaction)
         | 
| 55 | 
            -
                  TransactionEvent.new(configuration: configuration).tap do |event|
         | 
| 56 | 
            -
                    event.transaction = transaction.name
         | 
| 57 | 
            -
                    event.contexts.merge!(trace: transaction.get_trace_context)
         | 
| 58 | 
            -
                    event.timestamp = transaction.timestamp
         | 
| 59 | 
            -
                    event.start_timestamp = transaction.start_timestamp
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                    finished_spans = transaction.span_recorder.spans.select { |span| span.timestamp && span != transaction }
         | 
| 62 | 
            -
                    event.spans = finished_spans.map(&:to_hash)
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
                end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                def send_event(event, hint = nil)
         | 
| 67 | 
            -
                  return false unless configuration.sending_allowed?
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  event = configuration.before_send.call(event, hint) if configuration.before_send
         | 
| 70 | 
            -
                  if event.nil?
         | 
| 71 | 
            -
                    configuration.logger.info(LOGGER_PROGNAME) { "Discarded event because before_send returned nil" }
         | 
| 72 | 
            -
                    return
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  transport.send_event(event)
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                  event
         | 
| 78 | 
            -
                end
         | 
| 79 | 
            -
              end
         | 
| 80 | 
            -
            end
         |