Class: StackifyRubyAPM::Middleware Private

Inherits:
Object
  • Object
show all
Defined in:
lib/stackify_apm/middleware.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Constant Summary collapse

CONTENT_TYPE_REGEX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

%r{text\/html|application\/xhtml\+xml/}
CONTENT_DISPOSITION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'Content-Disposition'.freeze
ATTACHMENT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

'attachment'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Middleware

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Middleware.



32
33
34
# File 'lib/stackify_apm/middleware.rb', line 32

def initialize(app)
  @app = app
end

Instance Attribute Details

#configurationObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



26
27
28
# File 'lib/stackify_apm/middleware.rb', line 26

def configuration
  @configuration
end

#rack_bodyObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



26
27
28
# File 'lib/stackify_apm/middleware.rb', line 26

def rack_body
  @rack_body
end

#rack_headersObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



26
27
28
# File 'lib/stackify_apm/middleware.rb', line 26

def rack_headers
  @rack_headers
end

#rack_statusObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



26
27
28
# File 'lib/stackify_apm/middleware.rb', line 26

def rack_status
  @rack_status
end

Instance Method Details

#attachment?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


125
126
127
# File 'lib/stackify_apm/middleware.rb', line 125

def attachment?
  @rack_headers[CONTENT_DISPOSITION] && @rack_headers[CONTENT_DISPOSITION].include?(ATTACHMENT)
end

#build_prefix_context(transaction, context) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Add prefix instrument data to transaction context if enabled



142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/stackify_apm/middleware.rb', line 142

def build_prefix_context(transaction, context)
  return nil unless @configuration.prefix_enabled.is_a?(TrueClass)

  source = nil
  body = @rack_body
  body.each { |fragment| source ? (source << fragment.to_s) : (source = fragment.to_s) }

  transaction.context.prefix.request_body = context && context.request && context.request.body || ""
  transaction.context.prefix.request_headers = context && context.request && context.request.headers || Hash.new
  transaction.context.prefix.response_body = source || ""
  transaction.context.prefix.response_headers = @rack_headers || Hash.new
end

#build_transaction(env, context = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Start of transaction building with params: name, type, context



100
101
102
103
# File 'lib/stackify_apm/middleware.rb', line 100

def build_transaction(env, context=nil)
  context = context || StackifyRubyAPM.build_context(env)
  StackifyRubyAPM.transaction 'Rack', 'WEBAPP', context: context
end

#call(env) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This is where the requests are received, built into a transaction, and then submitted

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/stackify_apm/middleware.rb', line 40

def call(env)
  begin
    context = StackifyRubyAPM.build_context(env)
    transaction = build_transaction(env, context) if running?
    resp = @app.call env

    @rack_status = resp[0].to_i
    @rack_headers = resp[1]
    @rack_body = resp[2]
    @configuration = config

    build_prefix_context(transaction, context)

    if okay_to_modify?
      @configuration.already_instrumented_flag = true
      if @configuration.rum_enabled.is_a?(TrueClass)
        # close old response body proxy to close all db connections
        @rack_body.close if @rack_body.respond_to?(:close)
        response = Rack::Response.new @rack_body, @rack_status, @rack_headers
        response.set_cookie(@configuration.rum_cookie_name, value: transaction.id, path: @configuration.rum_cookie_path)
        resp = response.finish
      end
      if @configuration.rum_auto_injection.is_a?(TrueClass)
        response_manupulate = StackifyRubyAPM::ResponseManipulator.new(env, resp, @configuration)
        response_string = response_manupulate.adjust_pagehtml_response
        if response_string
          response = Rack::Response.new(response_string, resp[0].to_i, resp[1])
          resp = response.finish
        else
          resp
        end
      else
        resp
      end
    else
      resp
    end

    submit_transaction(transaction, *resp) if transaction
  rescue InternalError
    raise # Don't report StackifyRubyAPM errors
  rescue StandardError
    transaction.submit('500', status: 500) if transaction
    raise
  ensure
    transaction.release if transaction
  end

  resp
end

#configObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



109
110
111
# File 'lib/stackify_apm/middleware.rb', line 109

def config
  StackifyRubyAPM.agent.config
end

#modifiable_content_type?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


121
122
123
# File 'lib/stackify_apm/middleware.rb', line 121

def modifiable_content_type?
  @rack_headers['Content-Type'] =~ self.class::CONTENT_TYPE_REGEX
end

#okay_to_modify?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


113
114
115
116
117
118
119
# File 'lib/stackify_apm/middleware.rb', line 113

def okay_to_modify?
  return false if xhr?
  return false unless modifiable_content_type?
  return false if @rack_status == 404 || @rack_status == 501
  return false if attachment?
  true
end

#running?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


105
106
107
# File 'lib/stackify_apm/middleware.rb', line 105

def running?
  StackifyRubyAPM.running?
end

#streaming?(env) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


129
130
131
132
133
134
135
# File 'lib/stackify_apm/middleware.rb', line 129

def streaming?(env)
  # Not used
  # Possible use of ActiveSupport.on_load(:action_controller_base)
  return false unless defined?(ActionController::Live)

  env['action_controller.instance'].class.included_modules.include?(ActionController::Live)
end

#submit_transaction(transaction, status, headers, _body) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

rubocop:enable Metrics/PerceivedComplexity rubocop:enable Metrics/CyclomaticComplexity



93
94
95
96
# File 'lib/stackify_apm/middleware.rb', line 93

def submit_transaction(transaction, status, headers, _body)
  result = status.to_i
  transaction.submit(result, status: status, headers: headers)
end

#xhr?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


137
138
139
# File 'lib/stackify_apm/middleware.rb', line 137

def xhr?
  @rack_headers['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'
end