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)


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

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



138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/stackify_apm/middleware.rb', line 138

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



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

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
# 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)
        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.



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

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)


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

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)


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

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)


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

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)


127
128
129
130
131
# File 'lib/stackify_apm/middleware.rb', line 127

def streaming?(env)
  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



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

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)


133
134
135
# File 'lib/stackify_apm/middleware.rb', line 133

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