Class: MoesifRack::MoesifMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/moesif_rack/moesif_middleware.rb

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ MoesifMiddleware

Returns a new instance of MoesifMiddleware.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/moesif_rack/moesif_middleware.rb', line 12

def initialize app, options = {}
  @app = app
  if not options['application_id']
    raise 'application_id requird for Moesif Middleware'
  end
  @api_client = MoesifApi::MoesifAPIClient.new(options['application_id'])
  @api_controller = @api_client.api

  @api_version = options['api_version']
  @identify_user = options['identify_user']
  @identify_company = options['identify_company']
  @get_metadata = options['get_metadata']
  @identify_session = options['identify_session']
  @mask_data = options['mask_data']
  @skip = options['skip']
  @debug = options['debug']
  @config_dict = Hash.new
  @disable_transaction_id = options['disable_transaction_id'] || false
  @log_body = options.fetch('log_body', true)
  @sampling_percentage = get_config(nil)
  if not @sampling_percentage.is_a? Numeric
    raise "Sampling Percentage should be a number"
  end
  @capture_outoing_requests = options['capture_outoing_requests']
  if @capture_outoing_requests
    if @debug
      puts 'Start Capturing outgoing requests'
    end
    require_relative '../../moesif_capture_outgoing/httplog.rb'
    MoesifCaptureOutgoing.start_capture_outgoing(options)
  end
end

Instance Method Details

#call(env) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/moesif_rack/moesif_middleware.rb', line 90

def call env
  start_time = Time.now.utc.iso8601

  if @debug
    puts 'inside moesif middleware'
  end

  status, headers, body = @app.call env
  end_time = Time.now.utc.iso8601

  process_send = lambda do
    req = Rack::Request.new(env)
    complex_copy = env.dup

    req_headers = {}
    complex_copy.select {|k,v| k.start_with? 'HTTP_'}.each do |key, val|
      new_key = key.sub(/^HTTP_/, '')
      new_key = new_key.sub('_', '-')
      req_headers[new_key] = val
    end

    req_body_string = req.body.read
    req.body.rewind
    req_body_transfer_encoding = nil
    req_body = nil

    if @log_body
      if req_body_string && req_body_string.length != 0
        begin
          req_body = JSON.parse(req_body_string)
        rescue
          req_body = Base64.encode64(req_body_string)
          req_body_transfer_encoding = 'base64'
        end
      end
    end

    rsp_headers = headers.dup

    rsp_body_string = get_response_body(body);
    rsp_body_transfer_encoding = nil
    rsp_body = nil

    if @log_body
      if rsp_body_string && rsp_body_string.length != 0
        begin
          rsp_body = JSON.parse(rsp_body_string)
        rescue
          rsp_body = Base64.encode64(rsp_body_string)
          rsp_body_transfer_encoding = 'base64'
        end
      end
    end

    event_req = MoesifApi::EventRequestModel.new()
    event_req.time = start_time
    event_req.uri = req.url
    event_req.verb = req.request_method

    if @api_version
      event_req.api_version = @api_version
    end

    # Add Transaction Id to the Request Header
    if !@disable_transaction_id
      req_trans_id = req_headers["X-MOESIF_TRANSACTION_ID"]
      if !req_trans_id.nil?
        transaction_id = req_trans_id
        if transaction_id.strip.empty?
          transaction_id = SecureRandom.uuid
        end
      else
        transaction_id = SecureRandom.uuid
      end
      # Add Transaction Id to Request Header
      req_headers["X-Moesif-Transaction-Id"] = transaction_id
      # Filter out the old key as HTTP Headers case are not preserved
      if req_headers.key?("X-MOESIF_TRANSACTION_ID")
        req_headers = req_headers.except("X-MOESIF_TRANSACTION_ID")
      end
    end

    # Add Transaction Id to the Response Header
    if !transaction_id.nil?  
      rsp_headers["X-Moesif-Transaction-Id"] = transaction_id
    end

    # Add Transaction Id to the Repsonse Header sent to the client
    if !transaction_id.nil?  
      headers["X-Moesif-Transaction-Id"] = transaction_id
    end

    event_req.ip_address = get_client_address(req.env)
    event_req.headers = req_headers
    event_req.body = req_body
    event_req.transfer_encoding = req_body_transfer_encoding

    event_rsp = MoesifApi::EventResponseModel.new()
    event_rsp.time = end_time
    event_rsp.status = status
    event_rsp.headers = rsp_headers
    event_rsp.body = rsp_body
    event_rsp.transfer_encoding = rsp_body_transfer_encoding

    event_model = MoesifApi::EventModel.new()
    event_model.request = event_req
    event_model.response = event_rsp
    
    if @identify_user
      if @debug
        puts "calling identify user proc"
      end
      event_model.user_id = @identify_user.call(env, headers, body)
    end

    if @identify_company
      if @debug
        puts "calling identify company proc"
      end
      event_model.company_id = @identify_company.call(env, headers, body)
    end

    if @get_metadata
      if @debug
        puts "calling get_metadata proc"
      end
      event_model. = @get_metadata.call(env, headers, body)
    end

    if @identify_session
      if @debug
        puts "calling identify session proc"
      end
      event_model.session_token = @identify_session.call(env, headers, body)
    end
    if @mask_data
      if @debug
        puts "calling mask_data proc"
      end
      event_model = @mask_data.call(event_model)
    end

    if @debug
      puts "sending data to moesif"
      puts event_model.to_json
    end
    # Perform the API call through the SDK function
    begin
      @random_percentage = Random.rand(0.00..100.00)
      if @sampling_percentage > @random_percentage
        event_api_response = @api_controller.create_event(event_model)
        cached_config_etag = @config_dict.keys[0]
        event_response_config_etag = event_api_response[:x_moesif_config_etag]

        if !event_response_config_etag.nil? && cached_config_etag != event_response_config_etag && Time.now.utc > @last_updated_time + 30
          @sampling_percentage = get_config(cached_config_etag)
        end
        if @debug
          puts("Event successfully sent to Moesif")
        end
      else
        if @debug
          puts("Skipped Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s)
        end
      end
    rescue MoesifApi::APIException => e
      if e.response_code.between?(401, 403)
        puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
      end
      if @debug
        puts "Error sending event to Moesif, with status code: "
        puts e.response_code
      end
    end

  end

  should_skip = false

  if @skip
    if @skip.call(env, headers, body)
      should_skip = true;
    end
  end

  if !should_skip
    if @debug
      process_send.call
    else
      Thread.start(&process_send)
    end
  end

  [status, headers, body]
end

#get_config(cached_config_etag) ⇒ Object



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
# File 'lib/moesif_rack/moesif_middleware.rb', line 45

def get_config(cached_config_etag)
  sample_rate = 100
  begin
    # Calling the api
    config_api_response = @api_controller.get_app_config()
    # Fetch the response ETag
    response_config_etag = JSON.parse( config_api_response.to_json )["headers"]["x_moesif_config_etag"]
    # Remove ETag from the global dict if exist
    if !cached_config_etag.nil? && @config_dict.key?(cached_config_etag)
        @config_dict.delete(cached_config_etag)
    end
    # Fetch the response body
    @config_dict[response_config_etag] = JSON.parse(JSON.parse( config_api_response.to_json )["raw_body"])
    # 
    app_config = @config_dict[response_config_etag]
    # Fetch the sample rate
    if !app_config.nil?
      sample_rate = app_config.fetch("sample_rate", 100)
    end
    # Set the last updated time
    @last_updated_time = Time.now.utc
    rescue
      # Set the last updated time
      @last_updated_time = Time.now.utc
  end
  # Return the sample rate
  return sample_rate
end

#get_response_body(response) ⇒ Object



286
287
288
289
290
# File 'lib/moesif_rack/moesif_middleware.rb', line 286

def get_response_body(response)
  body = response.respond_to?(:body) ? response.body : response
  body = body.inject("") { |i, a| i << a } if body.respond_to?(:each)
  body.to_s
end

#update_companies_batch(company_profiles) ⇒ Object



86
87
88
# File 'lib/moesif_rack/moesif_middleware.rb', line 86

def update_companies_batch(company_profiles)
  CompanyHelper.new.update_companies_batch(@api_controller, @debug, company_profiles)
end

#update_company(company_profile) ⇒ Object



82
83
84
# File 'lib/moesif_rack/moesif_middleware.rb', line 82

def update_company(company_profile)
  CompanyHelper.new.update_company(@api_controller, @debug, company_profile)
end

#update_user(user_profile) ⇒ Object



74
75
76
# File 'lib/moesif_rack/moesif_middleware.rb', line 74

def update_user()
  UserHelper.new.update_user(@api_controller, @debug, )
end

#update_users_batch(user_profiles) ⇒ Object



78
79
80
# File 'lib/moesif_rack/moesif_middleware.rb', line 78

def update_users_batch(user_profiles)
  UserHelper.new.update_users_batch(@api_controller, @debug, user_profiles)
end