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
CONTENT_LENGTH =

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-Length'.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.



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

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)


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

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



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

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



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

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



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
# File 'lib/stackify_apm/middleware.rb', line 41

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)
        response_manipulated = StackifyRubyAPM::ResponseManipulator.new(env, resp, @configuration)
        response_string = response_manipulated.adjust_pagehtml_response
        if response_string
          if @rack_headers.key?(CONTENT_LENGTH)
            content_length = response_string ? response_string.bytesize : 0
            @rack_headers[CONTENT_LENGTH] = content_length.to_s
          end

          response = Rack::Response.new(response_string, @rack_status, @rack_headers)
          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.



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

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)


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

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)


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

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)


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

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)


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

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



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

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)


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

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