moesif_rack 2.1.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d3b35f6574397e6afb25a0a8ad055d3a172ac217584ef7c67e4b895b4f2ab19
4
- data.tar.gz: 6814b22faf3fc95704b19a5a0b0cc53c7015af87d18d04a69263645c6ef08fd7
3
+ metadata.gz: d22e96756a6c9b59c31a4615d96968dd2ab335540396a65389ddda9d8604b8b2
4
+ data.tar.gz: 40e942e0599207bb00917b0894f09f3cd42260bbf1bf3fa8e50c54abde0b57c3
5
5
  SHA512:
6
- metadata.gz: e8fba367126b816b88bfafbb58dee2efdb903d4db3613f29ccf135881e3cbbbd1940ccb67bef1461bfcde52fc1ef9daeb8248fdae4de7387d387d80360341d25
7
- data.tar.gz: df26774570df0d934d90e419b4b49e7cfc935f77b62326fba96b13d0129c38a4bc48788ca50f5af0d4828e544b2cda40dd448020bb6e190f19ead8fdf852016d
6
+ metadata.gz: 8fcff7759ab68baa2d7fad3c41e34816da6fb401106ade305e199347293971d52a9be62d52114915e318e46a945060608345bfa85619a1f364680af7211bef4d
7
+ data.tar.gz: f4740cb9b0181e73884d250b6c16bcdc9223366af390ebfb399e6731c4528a8c5d20ddb04c582234d0c7e763d58991c146d6cbf4da5ebe45d8a9ef69b303cd31
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 Moesif, Inc
1
+ Copyright (c) 2023 Moesif, Inc
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -262,7 +262,7 @@ Optional. int, default 200, Maximum batch size when sending to Moesif.
262
262
  Optional. int in seconds Default 2. This is the maximum wait time (approximately) before triggering flushing of the queue and sending to Moesif.
263
263
 
264
264
  #### __`event_queue_size`__
265
- Optional. int, Default 1000, Maximum number of events to hold in queue before sending to Moesif. In case of network issues when not able to connect/send event to Moesif, skips adding new to event to queue to prevent memory overflow.
265
+ Optional. int, Default 1000000, Maximum number of events to hold in queue before sending to Moesif. In case of network issues when not able to connect/send event to Moesif, skips adding new to event to queue to prevent memory overflow.
266
266
 
267
267
  #### __`capture_outgoing_requests`__
268
268
  Optional. Boolean, Default `false`. Set to `true` to capture all outgoing API calls from your app to third parties like Stripe, Github or to your own dependencies while using [Net::HTTP](https://ruby-doc.org/stdlib-2.6.3/libdoc/net/http/rdoc/Net/HTTP.html) package. The options below is applied to outgoing API calls. When the request is outgoing, for options functions that take request and response as input arguments, the request and response objects passed in are [Request](https://www.rubydoc.info/stdlib/net/Net/HTTPRequest) request and [Response](https://www.rubydoc.info/stdlib/net/Net/HTTPResponse) response objects.
@@ -38,4 +38,23 @@ class MoesifHelpers
38
38
  log_debug 'failed to convert replacement body ' + e.to_s
39
39
  [replacement_body.to_json.to_s]
40
40
  end
41
+
42
+ def parse_multipart(multipart_form_data, content_type)
43
+ log_debug("try to parse multiple part #{content_type}")
44
+
45
+ sanitized_multipart_form_data = multipart_form_data.gsub(/\r?\n/, "\r\n")
46
+
47
+ io = StringIO.new(sanitized_multipart_form_data)
48
+ tempfile = Rack::Multipart::Parser::TEMPFILE_FACTORY
49
+ bufsize = Rack::Multipart::Parser::BUFSIZE
50
+ query_parser = Rack::Utils.default_query_parser
51
+ result = Rack::Multipart::Parser.parse(io, sanitized_multipart_form_data.length, content_type, tempfile, bufsize,
52
+ query_parser)
53
+
54
+ log_debug('multipart parse result')
55
+ log_debug(result.inspect)
56
+
57
+ # this is a hash should be treated as JSON down the road.
58
+ result.params
59
+ end
41
60
  end
@@ -18,7 +18,7 @@ module MoesifRack
18
18
  @app = app
19
19
  raise 'application_id required for Moesif Middleware' unless options['application_id']
20
20
 
21
- @api_client = MoesifApi::MoesifAPIClient.new(options['application_id'], 'moesif-rack/2.1.1')
21
+ @api_client = MoesifApi::MoesifAPIClient.new(options['application_id'], 'moesif-rack/2.2.2')
22
22
  @api_controller = @api_client.api
23
23
 
24
24
  @api_version = options['api_version']
@@ -59,7 +59,7 @@ module MoesifRack
59
59
 
60
60
  @moesif_helpers.log_debug 'Start Capturing outgoing requests'
61
61
  require_relative '../../moesif_capture_outgoing/httplog'
62
- MoesifCaptureOutgoing.start_capture_outgoing(options, @app_config, @events_queue)
62
+ MoesifCaptureOutgoing.start_capture_outgoing(options, @app_config, method(:add_to_queue), @moesif_helpers)
63
63
  end
64
64
 
65
65
  def update_user(user_profile)
@@ -94,31 +94,6 @@ module MoesifRack
94
94
  [Base64.encode64(body), 'base64']
95
95
  end
96
96
 
97
- def @moesif_helpers.log_debug(message)
98
- return unless @debug
99
-
100
- puts("#{Time.now} [Moesif Middleware] PID #{Process.pid} TID #{Thread.current.object_id} #{message}")
101
- end
102
-
103
- def parse_multipart(multipart_form_data, content_type)
104
- @moesif_helpers.log_debug("try to parse multiple part #{content_type}")
105
-
106
- sanitized_multipart_form_data = multipart_form_data.gsub(/\r?\n/, "\r\n")
107
-
108
- io = StringIO.new(sanitized_multipart_form_data)
109
- tempfile = Rack::Multipart::Parser::TEMPFILE_FACTORY
110
- bufsize = Rack::Multipart::Parser::BUFSIZE
111
- query_parser = Rack::Utils.default_query_parser
112
- result = Rack::Multipart::Parser.parse(io, sanitized_multipart_form_data.length, content_type, tempfile, bufsize,
113
- query_parser)
114
-
115
- @moesif_helpers.log_debug('multipart parse result')
116
- @moesif_helpers.log_debug(result.inspect)
117
-
118
- # this is a hash shold be treated as JSON down the road.
119
- result.params
120
- end
121
-
122
97
  def parse_body(body, headers)
123
98
  begin
124
99
  if body.instance_of?(Hash) || body.instance_of?(Array)
@@ -128,7 +103,7 @@ module MoesifRack
128
103
  parsed_body = JSON.parse(body)
129
104
  transfer_encoding = 'json'
130
105
  elsif headers.key?('content-type') && (headers['content-type'].downcase.include? 'multipart/form-data')
131
- parsed_body = parse_multipart(body, headers['content-type'])
106
+ parsed_body = @moesif_helpers.parse_multipart(body, headers['content-type'])
132
107
  transfer_encoding = 'json'
133
108
  elsif headers.key?('content-encoding') && (headers['content-encoding'].downcase.include? 'gzip')
134
109
  uncompressed_string = decompress_body(body)
@@ -143,6 +118,7 @@ module MoesifRack
143
118
  end
144
119
 
145
120
  def start_worker
121
+ @moesif_helpers.log_debug('start worker');
146
122
  Thread.new do
147
123
  loop do
148
124
  # Update the last worker run, in case the events_queue is empty
@@ -182,6 +158,18 @@ module MoesifRack
182
158
  end
183
159
  end
184
160
 
161
+ def add_to_queue(_event_model)
162
+ # Add Event to the queue
163
+ if @events_queue.size >= @event_queue_size
164
+ @moesif_helpers.log_debug("Skipped Event due to events_queue size [#{@events_queue.size}] is over max #{@event_queue_size} ")
165
+ else
166
+ @events_queue << _event_model
167
+ @moesif_helpers.log_debug('Event added to the queue ')
168
+ end
169
+
170
+ start_worker if Time.now.utc > (@last_worker_run + 60)
171
+ end
172
+
185
173
  def call(env)
186
174
  start_time = Time.now.utc.iso8601(3)
187
175
 
@@ -303,10 +291,9 @@ module MoesifRack
303
291
  end
304
292
 
305
293
  process_send = lambda do |_event_model|
306
- @moesif_helpers.log_debug 'sending data to moesif'
294
+ @moesif_helpers.log_debug 'incoming event to add to queue for sending to moesif'
307
295
  @moesif_helpers.log_debug _event_model.to_json
308
296
 
309
- # Perform the API call through the SDK function
310
297
  begin
311
298
  random_percentage = Random.rand(0.00..100.00)
312
299
 
@@ -322,15 +309,7 @@ module MoesifRack
322
309
 
323
310
  if sampling_percentage > random_percentage
324
311
  _event_model.weight = @app_config.calculate_weight(sampling_percentage)
325
- # Add Event to the queue
326
- if @events_queue.size >= @event_queue_size
327
- @moesif_helpers.log_debug("Skipped Event due to events_queue size [#{@events_queue.size}] is over max #{@event_queue_size} ")
328
- else
329
- @events_queue << _event_model
330
- @moesif_helpers.log_debug('Event added to the queue ')
331
- end
332
-
333
- start_worker if Time.now.utc > (@last_worker_run + 60)
312
+ add_to_queue(_event_model)
334
313
  else
335
314
  @moesif_helpers.log_debug('Skipped Event due to sampling percentage: ' + sampling_percentage.to_s + ' and random percentage: ' + random_percentage.to_s)
336
315
  end
@@ -7,10 +7,14 @@ module Net
7
7
  def request(request, body = nil, &block)
8
8
  # Request Start Time
9
9
  request_time = Time.now.utc.iso8601(3)
10
-
11
10
  # URL
12
11
  url = "https://#{@address}#{request.path}"
13
12
 
13
+ if (not request.body_stream.nil?) && MoesifCaptureOutgoing.should_capture_body
14
+ req_body_from_stream = request.body_stream.read
15
+ request.body_stream.rewind
16
+ end
17
+
14
18
  # Response
15
19
  @response = orig_request(request, body, &block)
16
20
 
@@ -18,7 +22,8 @@ module Net
18
22
  response_time = Time.now.utc.iso8601(3)
19
23
 
20
24
  # Log Event to Moesif
21
- MoesifCaptureOutgoing.call(url, request, request_time, @response, response_time) if started?
25
+ body_from_req_call = body
26
+ MoesifCaptureOutgoing.call(url, request, request_time, @response, response_time, body_from_req_call, req_body_from_stream) if started?
22
27
 
23
28
  @response
24
29
  end
@@ -7,7 +7,7 @@ require_relative '../../lib/moesif_rack/app_config'
7
7
 
8
8
  module MoesifCaptureOutgoing
9
9
  class << self
10
- def start_capture_outgoing(options, app_config_manager, events_queue)
10
+ def start_capture_outgoing(options, app_config_manager, add_to_queue, moesif_helpers)
11
11
  @moesif_options = options
12
12
  raise 'application_id required for Moesif Middleware' unless @moesif_options['application_id']
13
13
 
@@ -23,15 +23,21 @@ module MoesifCaptureOutgoing
23
23
  @log_body_outgoing = options.fetch('log_body_outgoing', true)
24
24
 
25
25
  @app_config = app_config_manager
26
- # @app_config and @events_queue should be shared instance from the middleware
27
- # so that we can use the same queue and same loaded @app_config
28
- @events_queue = events_queue
26
+ # @app_config is shared instance from the middleware
27
+ # so same loaded @app_config
28
+ # add_to_queue is method from the middleware so that we can add to the same queue
29
+ @add_to_queue = add_to_queue
29
30
  @sampling_percentage = 100
30
31
  @last_updated_time = Time.now.utc
32
+ @moesif_helpers = moesif_helpers
31
33
  end
32
34
 
33
- def call(url, request, request_time, response, response_time)
34
- send_moesif_event(url, request, request_time, response, response_time)
35
+ def should_capture_body
36
+ @moesif_options.nil? ? false : @moesif_options['capture_outgoing_requests'] && @log_body_outgoing
37
+ end
38
+
39
+ def call(url, request, request_time, response, response_time, body_from_req_call, req_body_from_stream)
40
+ send_moesif_event(url, request, request_time, response, response_time, body_from_req_call, req_body_from_stream)
35
41
  end
36
42
 
37
43
  def get_response_body(response)
@@ -44,18 +50,30 @@ module MoesifCaptureOutgoing
44
50
  Rack::Utils::HTTP_STATUS_CODES.detect { |_k, v| v.to_s.casecmp(response_code_name.to_s).zero? }.first
45
51
  end
46
52
 
47
- def send_moesif_event(url, request, request_time, response, response_time)
53
+ def send_moesif_event(url, request, request_time, response, response_time, body_from_req_call, req_body_from_stream)
48
54
  if url.downcase.include? 'moesif'
49
- puts 'Skip sending as it is moesif Event' if @debug
55
+ @moesif_helpers.log_debug 'Skip adding to queue as it is moesif Event'
50
56
  else
51
57
  response.code = transform_response_code(response.code) if response.code.is_a?(Symbol)
52
58
 
59
+ # Request headers
60
+ req_headers = request.each_header.collect.to_h
61
+ req_content_type = req_headers['content-type'].nil? ? req_headers['Content-Type'] : req_headers['content-type']
62
+
53
63
  # Request Body
54
- req_body_string = request.body.nil? || request.body.empty? ? nil : request.body
64
+ req_body_string = request.body.nil? || request.body.empty? ? body_from_req_call : request.body
55
65
  req_body_transfer_encoding = nil
56
66
  req_body = nil
57
67
 
58
- if @log_body_outgoing && (req_body_string && req_body_string.length != 0)
68
+ if @log_body_outgoing && (not req_content_type.nil?) && (req_content_type.downcase.include? 'multipart/form-data')
69
+ @moesif_helpers.log_debug 'outgoing request is multipart, parsing req_body_from_stream'
70
+ begin
71
+ req_body = @moesif_helpers.parse_multipart(req_body_from_stream, req_content_type)
72
+ rescue StandardError => e
73
+ @moesif_helpers.log_debug 'outgoing request is multipart, but failed to process req_body_from_stream: ' + req_body_from_stream.to_s + e.to_s
74
+ req_body = nil
75
+ end
76
+ elsif @log_body_outgoing && (req_body_string && req_body_string.length != 0)
59
77
  begin
60
78
  req_body = JSON.parse(req_body_string)
61
79
  rescue StandardError
@@ -83,8 +101,9 @@ module MoesifCaptureOutgoing
83
101
  event_req.time = request_time
84
102
  event_req.uri = url
85
103
  event_req.verb = request.method.to_s.upcase
86
- event_req.headers = request.each_header.collect.to_h
104
+ event_req.headers = req_headers
87
105
  event_req.api_version = nil
106
+
88
107
  event_req.body = req_body
89
108
  event_req.transfer_encoding = req_body_transfer_encoding
90
109
 
@@ -155,19 +174,14 @@ module MoesifCaptureOutgoing
155
174
 
156
175
  if @sampling_percentage > @random_percentage
157
176
  event_model.weight = @app_config.calculate_weight(@sampling_percentage)
158
- if @debug
159
- puts 'Sending Outgoing Request Data to Moesif'
160
- puts event_model.to_json
161
- end
162
-
163
- # we put in the queue and format abot it.
164
- unless @events_queue.nil?
165
- @events_queue << event_model
166
- puts('Outgoing Event successfully added to event queue') if @debug
167
- return
168
- end
169
- elsif @debug
170
- puts('Skipped outgoing Event due to sampling percentage: ' + @sampling_percentage.to_s + ' and random percentage: ' + @random_percentage.to_s)
177
+ @moesif_helpers.log_debug 'Adding Outgoing Request Data to Queue'
178
+ @moesif_helpers.log_debug event_model.to_json
179
+ # we put in the queue and forget it.
180
+ @add_to_queue.call(event_model)
181
+ @moesif_helpers.log_debug 'Finished adding outgoing request data to Queue'
182
+
183
+ else
184
+ @moesif_helpers.log_debug('Skipped outgoing Event due to sampling percentage: ' + @sampling_percentage.to_s + ' and random percentage: ' + @random_percentage.to_s)
171
185
  end
172
186
  rescue MoesifApi::APIException => e
173
187
  if e.response_code.between?(401, 403)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moesif_rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moesif, Inc
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-09-26 00:00:00.000000000 Z
12
+ date: 2023-11-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit