moesif_rack 1.3.8 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7bb716388bcb7fda82c1f7cfc11530c01e9f0a9bbf6e4d84a171eae0cb75898
4
- data.tar.gz: fb000cc8620126bc8031c678b89cd03c55bc0a32cd8c1c2889db84818261e6b0
3
+ metadata.gz: 9d8635baa7838edc611616b3fcd19d30c6a8c9034f985b1a48df744eae3fc252
4
+ data.tar.gz: bf138ca57419057dafdc088f076e3b632a623cd5d268012e6e67a9ce60372ea9
5
5
  SHA512:
6
- metadata.gz: 92511aab26e9a6f09d46fbdedbb2925aa0dc66cdd4537acaff8fe19d158dbbde9cc0531bd6374f544d3de448f32b8edad54d298824a9ee1ff8c0ce6687c7eb9c
7
- data.tar.gz: 4d0e8d6ed2561a87ce9aa396a4510b66d91c186e409f44137bcaa3ef624298d1b8bf9195e62e837650ddf38e02eed07f41f91a2d18db73a973455b330903b66c
6
+ metadata.gz: 25e43ffa1f612ed39c3ddcee9a55b29ff8f81ed0f9e7d36651d605232aec4ef3ba55cf2e072bd99e72ce46fccc565591872bb58ddd982d65da86a7305f0f4784
7
+ data.tar.gz: '095a38e7f8dc9e4ba2fbf9ffd40dfd2ac01fcd72b5475915266274a807c53b70054f823109648e73319557efc07c61ddfb95f99a5d4586855b3db1f0fed7573a'
data/README.md CHANGED
@@ -22,7 +22,7 @@ gem install moesif_rack
22
22
  and if you have a `Gemfile` in your project, please add this line to
23
23
 
24
24
  ```
25
- gem 'moesif_rack', '~> 1.3.8'
25
+ gem 'moesif_rack', '~> 1.4.2'
26
26
 
27
27
  ```
28
28
 
@@ -126,12 +126,10 @@ Optional.
126
126
  identify_user is a Proc that takes env, headers, and body as arguments and returns a user_id string. This helps us attribute requests to unique users. Even though Moesif can automatically retrieve the user_id without this, this is highly recommended to ensure accurate attribution.
127
127
 
128
128
  ```ruby
129
-
130
129
  moesif_options['identify_user'] = Proc.new { |env, headers, body|
131
130
 
132
- #snip
133
-
134
- 'my_user_id'
131
+ # Add your custom code that returns a string for user id
132
+ '12345'
135
133
  }
136
134
 
137
135
  ```
@@ -145,13 +143,24 @@ identify_company is a Proc that takes env, headers, and body as arguments and re
145
143
 
146
144
  moesif_options['identify_company'] = Proc.new { |env, headers, body|
147
145
 
148
- #snip
149
-
150
- 'my_company_id'
146
+ # Add your custom code that returns a string for company id
147
+ '67890'
151
148
  }
152
149
 
153
150
  ```
154
151
 
152
+ #### __`identify_session`__
153
+
154
+ Optional. A Proc that takes env, headers, body and returns a string.
155
+
156
+ ```ruby
157
+
158
+ moesif_options['identify_session'] = Proc.new { |env, headers, body|
159
+ # Add your custom code that returns a string for session/API token
160
+ 'XXXXXXXXX'
161
+ }
162
+ ```
163
+
155
164
  #### __`get_metadata`__
156
165
 
157
166
  Optional.
@@ -162,31 +171,15 @@ metadata to this event.
162
171
  ```ruby
163
172
 
164
173
  moesif_options['get_metadata'] = Proc.new { |env, headers, body|
165
-
166
- #snip
174
+ # Add your custom code that returns a dictionary
167
175
  value = {
168
- 'foo' => 'abc',
169
- 'bar' => '123'
176
+ 'datacenter' => 'westus',
177
+ 'deployment_version' => 'v1.2.3'
170
178
  }
171
-
172
179
  value
173
180
  }
174
181
  ```
175
182
 
176
- #### __`identify_session`__
177
-
178
- Optional. A Proc that takes env, headers, body and returns a string.
179
-
180
- ```ruby
181
-
182
- moesif_options['identify_session'] = Proc.new { |env, headers, body|
183
-
184
- #snip
185
-
186
- 'the_session_token'
187
- }
188
-
189
- ```
190
183
 
191
184
  #### __`mask_data`__
192
185
 
@@ -196,9 +189,8 @@ With mask_data, you can make modifications to headers or body of the event befor
196
189
  ```ruby
197
190
 
198
191
  moesif_options['mask_data'] = Proc.new { |event_model|
199
-
200
- #snip
201
-
192
+ # Add your custom code that returns a event_model after modifying any fields
193
+ event_model.response.body.password = nil
202
194
  event_model
203
195
  }
204
196
 
@@ -213,9 +205,7 @@ Optional. A Proc that takes env, headers, body and returns a boolean.
213
205
  ```ruby
214
206
 
215
207
  moesif_options['skip'] = Proc.new { |env, headers, body|
216
-
217
- #snip
218
-
208
+ # Add your custom code that returns true to skip logging the API call
219
209
  false
220
210
  }
221
211
 
@@ -232,7 +222,7 @@ Optional. Boolean. Default false. If true, it will print out debug messages. In
232
222
 
233
223
  Optional. Boolean. Default true. If false, will not log request and response body to Moesif.
234
224
 
235
- #### __`capture_outoing_requests`__
225
+ #### __`capture_outgoing_requests`__
236
226
  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.
237
227
 
238
228
 
@@ -245,9 +235,8 @@ identify_user_outgoing is a Proc that takes request and response as arguments an
245
235
 
246
236
  moesif_options['identify_user_outgoing'] = Proc.new { |request, response|
247
237
 
248
- #snip
249
-
250
- 'the_user_id'
238
+ # Add your custom code that returns a string for user id
239
+ '12345'
251
240
  }
252
241
 
253
242
  ```
@@ -261,9 +250,8 @@ identify_company_outgoing is a Proc that takes request and response as arguments
261
250
 
262
251
  moesif_options['identify_company_outgoing'] = Proc.new { |request, response|
263
252
 
264
- #snip
265
-
266
- 'the_company_id'
253
+ # Add your custom code that returns a string for company id
254
+ '67890'
267
255
  }
268
256
 
269
257
  ```
@@ -279,12 +267,11 @@ metadata to this event.
279
267
 
280
268
  moesif_options['get_metadata_outgoing'] = Proc.new { |request, response|
281
269
 
282
- #snip
270
+ # Add your custom code that returns a dictionary
283
271
  value = {
284
- 'foo' => 'abc',
285
- 'bar' => '123'
272
+ 'datacenter' => 'westus',
273
+ 'deployment_version' => 'v1.2.3'
286
274
  }
287
-
288
275
  value
289
276
  }
290
277
  ```
@@ -297,9 +284,8 @@ Optional. A Proc that takes request, response and returns a string.
297
284
 
298
285
  moesif_options['identify_session_outgoing'] = Proc.new { |request, response|
299
286
 
300
- #snip
301
-
302
- 'the_session_token'
287
+ # Add your custom code that returns a string for session/API token
288
+ 'XXXXXXXXX'
303
289
  }
304
290
 
305
291
  ```
@@ -312,8 +298,7 @@ Optional. A Proc that takes request, response and returns a boolean. If `true` w
312
298
 
313
299
  moesif_options['skip_outgoing'] = Proc.new{ |request, response|
314
300
 
315
- #snip
316
-
301
+ # Add your custom code that returns true to skip logging the API call
317
302
  false
318
303
  }
319
304
 
@@ -328,8 +313,8 @@ With mask_data_outgoing, you can make modifications to headers or body of the ev
328
313
 
329
314
  moesif_options['mask_data_outgoing'] = Proc.new { |event_model|
330
315
 
331
- #snip
332
-
316
+ # Add your custom code that returns a event_model after modifying any fields
317
+ event_model.response.body.password = nil
333
318
  event_model
334
319
  }
335
320
 
@@ -341,103 +326,169 @@ Optional. Boolean. Default true. If false, will not log request and response bod
341
326
 
342
327
  ## Update User
343
328
 
344
- ### update_user method
345
- A method is attached to the moesif middleware object to update the user profile or metadata.
346
- The metadata field can be any custom data you want to set on the user. The `user_id` field is required.
329
+ ### Update a Single User
330
+ Create or update a user profile in Moesif.
331
+ The metadata field can be any customer demographic or other info you want to store.
332
+ Only the `user_id` field is required.
333
+ This method is a convenient helper that calls the Moesif API lib.
334
+ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-a-user).
347
335
 
348
336
  ```ruby
349
- metadata = JSON.parse('{'\
350
- '"email": "testrubyapi@user.com",'\
351
- '"name": "ruby api user",'\
352
- '"custom": "testdata"'\
353
- '}')
354
-
355
- campaign_model = {"utm_source" => "Newsletter",
356
- "utm_medium" => "Email"}
337
+ metadata = {
338
+ :email => 'john@acmeinc.com',
339
+ :first_name => 'John',
340
+ :last_name => 'Doe',
341
+ :title => 'Software Engineer',
342
+ :salesInfo => {
343
+ :stage => 'Customer',
344
+ :lifetime_value => 24000,
345
+ :accountOwner => 'mary@contoso.com',
346
+ }
347
+ }
357
348
 
358
- user_model = { "user_id" => "12345",
359
- "company_id" => "67890",
360
- "modified_time" => Time.now.utc.iso8601,
361
- "metadata" => metadata,
362
- "campaign" => campaign_model }
349
+ # Campaign object is optional, but useful if you want to track ROI of acquisition channels
350
+ # See https://www.moesif.com/docs/api#users for campaign schema
351
+ campaign = MoesifApi::CampaignModel.new()
352
+ campaign.utm_source = "google"
353
+ campaign.utm_medium = "cpc"
354
+ campaign.utm_campaign = "adwords"
355
+ campaign.utm_term = "api+tooling"
356
+ campaign.utm_content = "landing"
357
+
358
+ # Only user_id is required.
359
+ # metadata can be any custom object
360
+ user = MoesifApi::UserModel.new()
361
+ user.user_id = "12345"
362
+ user.company_id = "67890" # If set, associate user with a company object
363
+ user.campaign = campaign
364
+ user.metadata = metadata
363
365
 
364
366
  update_user = MoesifRack::MoesifMiddleware.new(@app, @options).update_user(user_model)
365
367
  ```
366
368
 
367
- ### update_users_batch method
368
- A method is attached to the moesif middleware object to update the users profile or metadata in batch.
369
- The metadata field can be any custom data you want to set on the user. The `user_id` field is required.
369
+ ### Update Users in Batch
370
+ Similar to update_user, but used to update a list of users in one batch.
371
+ Only the `user_id` field is required.
372
+ This method is a convenient helper that calls the Moesif API lib.
373
+ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-users-in-batch).
370
374
 
371
375
  ```ruby
372
- metadata = JSON.parse('{'\
373
- '"email": "testrubyapi@user.com",'\
374
- '"name": "ruby api user",'\
375
- '"custom": "testdata"'\
376
- '}')
377
-
378
- user_models = []
379
-
380
- user_model_A = { "user_id" => "12345",
381
- "company_id" => "67890",
382
- "modified_time" => Time.now.utc.iso8601,
383
- "metadata" => metadata }
384
-
385
- user_model_B = { "user_id" => "1234",
386
- "company_id" => "6789",
387
- "modified_time" => Time.now.utc.iso8601,
388
- "metadata" => metadata }
389
-
390
- user_models << user_model_A << user_model_B
391
- response = MoesifRack::MoesifMiddleware.new(@app, @options).update_users_batch(user_models)
376
+ users = []
377
+
378
+ metadata = {
379
+ :email => 'john@acmeinc.com',
380
+ :first_name => 'John',
381
+ :last_name => 'Doe',
382
+ :title => 'Software Engineer',
383
+ :salesInfo => {
384
+ :stage => 'Customer',
385
+ :lifetime_value => 24000,
386
+ :accountOwner => 'mary@contoso.com',
387
+ }
388
+ }
389
+
390
+ # Campaign object is optional, but useful if you want to track ROI of acquisition channels
391
+ # See https://www.moesif.com/docs/api#users for campaign schema
392
+ campaign = MoesifApi::CampaignModel.new()
393
+ campaign.utm_source = "google"
394
+ campaign.utm_medium = "cpc"
395
+ campaign.utm_campaign = "adwords"
396
+ campaign.utm_term = "api+tooling"
397
+ campaign.utm_content = "landing"
398
+
399
+ # Only user_id is required.
400
+ # metadata can be any custom object
401
+ user = MoesifApi::UserModel.new()
402
+ user.user_id = "12345"
403
+ user.company_id = "67890" # If set, associate user with a company object
404
+ user.campaign = campaign
405
+ user.metadata = metadata
406
+
407
+ users << user
408
+
409
+ response = MoesifRack::MoesifMiddleware.new(@app, @options).update_users_batch(users)
392
410
  ```
393
411
 
394
412
  ## Update Company
395
413
 
396
- ### update_company method
397
- A method is attached to the moesif middleware object to update the company profile or metadata.
398
- The metadata field can be any custom data you want to set on the company. The `company_id` field is required.
414
+ ### Update a Single Company
415
+ Create or update a company profile in Moesif.
416
+ The metadata field can be any company demographic or other info you want to store.
417
+ Only the `company_id` field is required.
418
+ This method is a convenient helper that calls the Moesif API lib.
419
+ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-a-company).
399
420
 
400
421
  ```ruby
401
- metadata = JSON.parse('{'\
402
- '"email": "testrubyapi@company.com",'\
403
- '"name": "ruby api company",'\
404
- '"custom": "testdata"'\
405
- '}')
406
-
407
- campaign_model = {"utm_source" => "Adwords",
408
- "utm_medium" => "Twitter"}
422
+ metadata = {
423
+ :org_name => 'Acme, Inc',
424
+ :plan_name => 'Free',
425
+ :deal_stage => 'Lead',
426
+ :mrr => 24000,
427
+ :demographics => {
428
+ :alexa_ranking => 500000,
429
+ :employee_count => 47
430
+ }
431
+ }
409
432
 
410
- company_model = { "company_id" => "12345",
411
- "company_domain" => "acmeinc.com",
412
- "metadata" => metadata,
413
- "campaign" => campaign_model }
433
+ # Campaign object is optional, but useful if you want to track ROI of acquisition channels
434
+ # See https://www.moesif.com/docs/api#update-a-company for campaign schema
435
+ campaign = MoesifApi::CampaignModel.new()
436
+ campaign.utm_source = "google"
437
+ campaign.utm_medium = "cpc"
438
+ campaign.utm_campaign = "adwords"
439
+ campaign.utm_term = "api+tooling"
440
+ campaign.utm_content = "landing"
441
+
442
+ # Only company_id is required.
443
+ # metadata can be any custom object
444
+ company = MoesifApi::CompanyModel.new()
445
+ company.company_id = "67890"
446
+ company.company_domain = "acmeinc.com" # If domain is set, Moesif will enrich your profiles with publicly available info
447
+ company.campaign = campaign
448
+ company.metadata = metadata
414
449
 
415
450
  update_company = MoesifRack::MoesifMiddleware.new(@app, @options).update_company(company_model)
416
451
  ```
417
452
 
418
- ### update_companies_batch method
419
- A method is attached to the moesif middleware object to update the companies profile or metadata in batch.
420
- The metadata field can be any custom data you want to set on the company. The `company_id` field is required.
453
+ ### Update Companies in Batch
454
+ Similar to update_company, but used to update a list of companies in one batch.
455
+ Only the `company_id` field is required.
456
+ This method is a convenient helper that calls the Moesif API lib.
457
+ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-companies-in-batch).
421
458
 
422
459
  ```ruby
423
- metadata = JSON.parse('{'\
424
- '"email": "testrubyapi@user.com",'\
425
- '"name": "ruby api user",'\
426
- '"custom": "testdata"'\
427
- '}')
428
-
429
- company_models = []
430
-
431
- company_model_A = { "company_id" => "12345",
432
- "company_domain" => "nowhere.com",
433
- "metadata" => metadata }
434
-
435
- company_model_B = { "company_id" => "67890",
436
- "company_domain" => "acmeinc.com",
437
- "metadata" => metadata }
460
+ companies = []
461
+
462
+ metadata = {
463
+ :org_name => 'Acme, Inc',
464
+ :plan_name => 'Free',
465
+ :deal_stage => 'Lead',
466
+ :mrr => 24000,
467
+ :demographics => {
468
+ :alexa_ranking => 500000,
469
+ :employee_count => 47
470
+ }
471
+ }
438
472
 
439
- company_models << company_model_A << company_model_B
440
- response = MoesifRack::MoesifMiddleware.new(@app, @options).update_companies_batch(company_models)
473
+ # Campaign object is optional, but useful if you want to track ROI of acquisition channels
474
+ # See https://www.moesif.com/docs/api#update-a-company for campaign schema
475
+ campaign = MoesifApi::CampaignModel.new()
476
+ campaign.utm_source = "google"
477
+ campaign.utm_medium = "cpc"
478
+ campaign.utm_campaign = "adwords"
479
+ campaign.utm_term = "api+tooling"
480
+ campaign.utm_content = "landing"
481
+
482
+ # Only company_id is required.
483
+ # metadata can be any custom object
484
+ company = MoesifApi::CompanyModel.new()
485
+ company.company_id = "67890"
486
+ company.company_domain = "acmeinc.com" # If domain is set, Moesif will enrich your profiles with publicly available info
487
+ company.campaign = campaign
488
+ company.metadata = metadata
489
+
490
+ companies << company
491
+ response = MoesifRack::MoesifMiddleware.new(@app, @options).update_companies_batch(companies)
441
492
  ```
442
493
 
443
494
  ## How to test
@@ -457,7 +508,7 @@ response = MoesifRack::MoesifMiddleware.new(@app, @options).update_companies_bat
457
508
 
458
509
  ## Other integrations
459
510
 
460
- To view more more documentation on integration options, please visit [the Integration Options Documentation](https://www.moesif.com/docs/getting-started/integration-options/).
511
+ To view more documentation on integration options, please visit [the Integration Options Documentation](https://www.moesif.com/docs/getting-started/integration-options/).
461
512
 
462
513
  [ico-built-for]: https://img.shields.io/badge/built%20for-rack-blue.svg
463
514
  [ico-version]: https://img.shields.io/gem/v/moesif_rack.svg
@@ -118,4 +118,8 @@ class AppConfig
118
118
  return nil
119
119
  end
120
120
  end
121
+
122
+ def calculate_weight(sample_rate)
123
+ return sample_rate == 0 ? 1 : (100 / sample_rate).floor
124
+ end
121
125
  end
@@ -6,6 +6,8 @@ require_relative './client_ip.rb'
6
6
  require_relative './app_config.rb'
7
7
  require_relative './update_user.rb'
8
8
  require_relative './update_company.rb'
9
+ require 'zlib'
10
+ require 'stringio'
9
11
 
10
12
  module MoesifRack
11
13
 
@@ -34,6 +36,45 @@ module MoesifRack
34
36
  @config_dict = Hash.new
35
37
  @disable_transaction_id = options['disable_transaction_id'] || false
36
38
  @log_body = options.fetch('log_body', true)
39
+ @batch_size = options['batch_size'] || 25
40
+ @events_queue = Queue.new
41
+ @event_response_config_etag = nil
42
+
43
+ Thread::new do
44
+ loop do
45
+ begin
46
+ until @events_queue.empty? do
47
+ batch_events = []
48
+ until batch_events.size == @batch_size || @events_queue.empty? do
49
+ batch_events << @events_queue.pop
50
+ end
51
+ event_api_response = @api_controller.create_events_batch(batch_events)
52
+ @event_response_config_etag = event_api_response[:x_moesif_config_etag]
53
+ if @debug
54
+ puts("Events successfully sent to Moesif")
55
+ end
56
+ end
57
+
58
+ if @events_queue.empty?
59
+ if @debug
60
+ puts("No events to read from the queue")
61
+ end
62
+ end
63
+
64
+ # Sleep for 5 seconds
65
+ sleep 5
66
+ rescue MoesifApi::APIException => e
67
+ if e.response_code.between?(401, 403)
68
+ puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
69
+ end
70
+ if @debug
71
+ puts "Error sending event to Moesif, with status code: "
72
+ puts e.response_code
73
+ end
74
+ end
75
+ end
76
+ end
77
+
37
78
  begin
38
79
  if !@config.nil?
39
80
  @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
@@ -45,7 +86,8 @@ module MoesifRack
45
86
  end
46
87
  end
47
88
  @capture_outoing_requests = options['capture_outoing_requests']
48
- if @capture_outoing_requests
89
+ @capture_outgoing_requests = options['capture_outgoing_requests']
90
+ if @capture_outoing_requests || @capture_outgoing_requests
49
91
  if @debug
50
92
  puts 'Start Capturing outgoing requests'
51
93
  end
@@ -70,6 +112,39 @@ module MoesifRack
70
112
  CompanyHelper.new.update_companies_batch(@api_controller, @debug, company_profiles)
71
113
  end
72
114
 
115
+ def start_with_json(body)
116
+ body.start_with?('{') || body.start_with?('[')
117
+ end
118
+
119
+ def decompress_body(body)
120
+ Zlib::GzipReader.new(StringIO.new(body)).read
121
+ end
122
+
123
+ def transform_headers(headers)
124
+ Hash[headers.map { |k, v| [k.downcase, v]}]
125
+ end
126
+
127
+ def base64_encode_body(body)
128
+ return Base64.encode64(body), 'base64'
129
+ end
130
+
131
+ def parse_body(body, headers)
132
+ begin
133
+ if start_with_json(body)
134
+ parsed_body = JSON.parse(body)
135
+ transfer_encoding = 'json'
136
+ elsif headers.key?('content-encoding') && ((headers['content-encoding'].downcase).include? "gzip")
137
+ uncompressed_string = decompress_body(body)
138
+ parsed_body, transfer_encoding = base64_encode_body(uncompressed_string)
139
+ else
140
+ parsed_body, transfer_encoding = base64_encode_body(body)
141
+ end
142
+ rescue
143
+ parsed_body, transfer_encoding = base64_encode_body(body)
144
+ end
145
+ return parsed_body, transfer_encoding
146
+ end
147
+
73
148
  def call env
74
149
  start_time = Time.now.utc.iso8601
75
150
 
@@ -85,7 +160,7 @@ module MoesifRack
85
160
  complex_copy = env.dup
86
161
 
87
162
  req_headers = {}
88
- complex_copy.select {|k,v| k.start_with? 'HTTP_'}.each do |key, val|
163
+ complex_copy.select {|k,v| k.start_with?('HTTP_', 'CONTENT_') }.each do |key, val|
89
164
  new_key = key.sub(/^HTTP_/, '')
90
165
  new_key = new_key.sub('_', '-')
91
166
  req_headers[new_key] = val
@@ -98,12 +173,7 @@ module MoesifRack
98
173
 
99
174
  if @log_body
100
175
  if req_body_string && req_body_string.length != 0
101
- begin
102
- req_body = JSON.parse(req_body_string)
103
- rescue
104
- req_body = Base64.encode64(req_body_string)
105
- req_body_transfer_encoding = 'base64'
106
- end
176
+ req_body, req_body_transfer_encoding = parse_body(req_body_string, transform_headers(req_headers))
107
177
  end
108
178
  end
109
179
 
@@ -115,12 +185,7 @@ module MoesifRack
115
185
 
116
186
  if @log_body
117
187
  if rsp_body_string && rsp_body_string.length != 0
118
- begin
119
- rsp_body = JSON.parse(rsp_body_string)
120
- rescue
121
- rsp_body = Base64.encode64(rsp_body_string)
122
- rsp_body_transfer_encoding = 'base64'
123
- end
188
+ rsp_body, rsp_body_transfer_encoding = parse_body(rsp_body_string, transform_headers(rsp_headers))
124
189
  end
125
190
  end
126
191
 
@@ -177,6 +242,7 @@ module MoesifRack
177
242
  event_model = MoesifApi::EventModel.new()
178
243
  event_model.request = event_req
179
244
  event_model.response = event_rsp
245
+ event_model.direction = "Incoming"
180
246
 
181
247
  if @identify_user
182
248
  if @debug
@@ -231,10 +297,14 @@ module MoesifRack
231
297
  end
232
298
 
233
299
  if @sampling_percentage > @random_percentage
234
- event_api_response = @api_controller.create_event(event_model)
235
- event_response_config_etag = event_api_response[:x_moesif_config_etag]
300
+ event_model.weight = @app_config.calculate_weight(@sampling_percentage)
301
+ # Add Event to the queue
302
+ @events_queue << event_model
303
+ if @debug
304
+ puts("Event added to the queue ")
305
+ end
236
306
 
237
- if !event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != event_response_config_etag && Time.now.utc > @last_updated_time + 300
307
+ if !@event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != @event_response_config_etag && Time.now.utc > @last_updated_time + 300
238
308
  begin
239
309
  @config = @app_config.get_config(@api_controller, @debug)
240
310
  @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
@@ -245,21 +315,15 @@ module MoesifRack
245
315
  end
246
316
  end
247
317
  end
248
- if @debug
249
- puts("Event successfully sent to Moesif")
250
- end
251
318
  else
252
319
  if @debug
253
320
  puts("Skipped Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s)
254
321
  end
255
322
  end
256
- rescue MoesifApi::APIException => e
257
- if e.response_code.between?(401, 403)
258
- puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
259
- end
323
+ rescue => exception
260
324
  if @debug
261
- puts "Error sending event to Moesif, with status code: "
262
- puts e.response_code
325
+ puts "Error adding event to the queue "
326
+ puts exception.to_s
263
327
  end
264
328
  end
265
329
 
@@ -3,6 +3,7 @@ require 'rack'
3
3
  require 'moesif_api'
4
4
  require 'json'
5
5
  require 'base64'
6
+ require_relative '../../lib/moesif_rack/app_config.rb'
6
7
 
7
8
  module MoesifCaptureOutgoing
8
9
 
@@ -23,6 +24,22 @@ module MoesifCaptureOutgoing
23
24
  @skip_outgoing = options['skip_outgoing']
24
25
  @mask_data_outgoing = options['mask_data_outgoing']
25
26
  @log_body_outgoing = options.fetch('log_body_outgoing', true)
27
+ @app_config = AppConfig.new
28
+ @config = @app_config.get_config(@api_controller, @debug)
29
+ @config_etag = nil
30
+ @sampling_percentage = 100
31
+ @last_updated_time = Time.now.utc
32
+ @config_dict = Hash.new
33
+ begin
34
+ if !@config.nil?
35
+ @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
36
+ end
37
+ rescue => exception
38
+ if @debug
39
+ puts 'Error while parsing application configuration on initialization'
40
+ puts exception.to_s
41
+ end
42
+ end
26
43
  end
27
44
 
28
45
  def call (url, request, request_time, response, response_time)
@@ -102,6 +119,7 @@ module MoesifCaptureOutgoing
102
119
  event_model = MoesifApi::EventModel.new()
103
120
  event_model.request = event_req
104
121
  event_model.response = event_rsp
122
+ event_model.direction = "Outgoing"
105
123
 
106
124
  # Metadata for Outgoing Request
107
125
  if @get_metadata_outgoing
@@ -156,11 +174,45 @@ module MoesifCaptureOutgoing
156
174
 
157
175
  # Send Event to Moesif
158
176
  begin
159
- if @debug
160
- puts 'Sending Outgoing Request Data to Moesif'
161
- puts event_model.to_json
177
+ @random_percentage = Random.rand(0.00..100.00)
178
+ begin
179
+ @sampling_percentage = @app_config.get_sampling_percentage(@config, event_model.user_id, event_model.company_id, @debug)
180
+ rescue => exception
181
+ if @debug
182
+ puts 'Error while getting sampling percentage, assuming default behavior'
183
+ puts exception.to_s
184
+ end
185
+ @sampling_percentage = 100
186
+ end
187
+
188
+ if @sampling_percentage > @random_percentage
189
+ event_model.weight = @app_config.calculate_weight(@sampling_percentage)
190
+ if @debug
191
+ puts 'Sending Outgoing Request Data to Moesif'
192
+ puts event_model.to_json
193
+ end
194
+ event_api_response = @api_controller.create_event(event_model)
195
+ event_response_config_etag = event_api_response[:x_moesif_config_etag]
196
+
197
+ if !event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != event_response_config_etag && Time.now.utc > @last_updated_time + 300
198
+ begin
199
+ @config = @app_config.get_config(@api_controller, @debug)
200
+ @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
201
+ rescue => exception
202
+ if @debug
203
+ puts 'Error while updating the application configuration'
204
+ puts exception.to_s
205
+ end
206
+ end
207
+ end
208
+ if @debug
209
+ puts("Event successfully sent to Moesif")
210
+ end
211
+ else
212
+ if @debug
213
+ puts("Skipped outgoing Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s)
214
+ end
162
215
  end
163
- @api_controller.create_event(event_model)
164
216
  rescue MoesifApi::APIException => e
165
217
  if e.response_code.between?(401, 403)
166
218
  puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
@@ -10,7 +10,7 @@ class MoesifRackTest < Test::Unit::TestCase
10
10
  @options = { 'application_id' => 'Your Moesif Application Id',
11
11
  'debug' => true,
12
12
  'disable_transaction_id' => true,
13
- 'capture_outoing_requests' => true,
13
+ 'capture_outgoing_requests' => true,
14
14
  'get_metadata' => Proc.new {|request, response|
15
15
  {
16
16
  'foo' => 'abc',
@@ -108,6 +108,8 @@ class MoesifRackTest < Test::Unit::TestCase
108
108
 
109
109
  def test_log_event
110
110
  response = @moesif_rack_app.call(Rack::MockRequest.env_for("https://acmeinc.com/items/42752/reviews"))
111
+ # Sleep to allow queue to flush for testing purpose
112
+ sleep 5
111
113
  assert_equal response, @app.call(nil)
112
114
  end
113
115
 
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: 1.3.8
4
+ version: 1.4.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: 2019-11-18 00:00:00.000000000 Z
12
+ date: 2020-05-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 1.2.9
34
+ version: 1.2.12
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 1.2.9
41
+ version: 1.2.12
42
42
  description: Collection/Data Ingestion SDK for Rack (also Rails) Middleware / RoR
43
43
  email: xing@moesif.com
44
44
  executables: []
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  requirements: []
79
- rubygems_version: 3.0.1
79
+ rubygems_version: 3.0.4
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: moesif_rack