moesif_rack 1.4.0 → 1.4.5

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: 818bfecddcafd4b2b71a662e762cb5468b4bf54c7fc5397fb0812ad4274b82ac
4
- data.tar.gz: 96385b853df74e5a7ca95d669244fc8e744079fcfd6d109c1c7855663bd61ea8
3
+ metadata.gz: 2366969ea63a6f2aeeb37498dc5bbfad99d4ea43753085237af1326689050cc4
4
+ data.tar.gz: 2ac98efe04dc86f79db515805ed5f45e7beff707c87c82e42fc7adc2eacbc883
5
5
  SHA512:
6
- metadata.gz: eb421c6472805827b2f7c23442c3047ba36c34172ef9af86d2c1266e3867c5aea201cb1900b9e11c16f6915773273a366d75e2b81a0bd02676f147f432de2988
7
- data.tar.gz: 557bea2a4a9e8c223bde8d2242d47c23ff69adf591ee2f55101b74f9910e788ec584aaf7b5e61942f485a2aa43bd423b6a4196094586424c217de0ded3fe36b9
6
+ metadata.gz: f18420e49b9dbd3f6d8a1cba791a4c235a06d3568e8ed47d5be9059e93b09acdd6a71a7a7382f500daafe1d5d1b6dd3c3eb87b7d99612db042a41a3a881eb65c
7
+ data.tar.gz: a1a3174c9e701e6ccd809ee0ea113878ca53b0ed8194ca612ba5491f0aaa9aa2761e3b586b3acaf23f6317244700111026e6ae9ce84f212a87dd4a25bdda7619
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019 Moesif, Inc
1
+ Copyright (c) 2020 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
@@ -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.4.0'
25
+ gem 'moesif_rack'
26
26
 
27
27
  ```
28
28
 
@@ -334,7 +334,7 @@ This method is a convenient helper that calls the Moesif API lib.
334
334
  For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-a-user).
335
335
 
336
336
  ```ruby
337
- metadata => {
337
+ metadata = {
338
338
  :email => 'john@acmeinc.com',
339
339
  :first_name => 'John',
340
340
  :last_name => 'Doe',
@@ -348,7 +348,7 @@ metadata => {
348
348
 
349
349
  # Campaign object is optional, but useful if you want to track ROI of acquisition channels
350
350
  # See https://www.moesif.com/docs/api#users for campaign schema
351
- campaign = CampaignModel.new()
351
+ campaign = MoesifApi::CampaignModel.new()
352
352
  campaign.utm_source = "google"
353
353
  campaign.utm_medium = "cpc"
354
354
  campaign.utm_campaign = "adwords"
@@ -357,7 +357,7 @@ campaign.utm_content = "landing"
357
357
 
358
358
  # Only user_id is required.
359
359
  # metadata can be any custom object
360
- user = UserModel.new()
360
+ user = MoesifApi::UserModel.new()
361
361
  user.user_id = "12345"
362
362
  user.company_id = "67890" # If set, associate user with a company object
363
363
  user.campaign = campaign
@@ -375,7 +375,7 @@ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby
375
375
  ```ruby
376
376
  users = []
377
377
 
378
- metadata => {
378
+ metadata = {
379
379
  :email => 'john@acmeinc.com',
380
380
  :first_name => 'John',
381
381
  :last_name => 'Doe',
@@ -389,7 +389,7 @@ metadata => {
389
389
 
390
390
  # Campaign object is optional, but useful if you want to track ROI of acquisition channels
391
391
  # See https://www.moesif.com/docs/api#users for campaign schema
392
- campaign = CampaignModel.new()
392
+ campaign = MoesifApi::CampaignModel.new()
393
393
  campaign.utm_source = "google"
394
394
  campaign.utm_medium = "cpc"
395
395
  campaign.utm_campaign = "adwords"
@@ -398,7 +398,7 @@ campaign.utm_content = "landing"
398
398
 
399
399
  # Only user_id is required.
400
400
  # metadata can be any custom object
401
- user = UserModel.new()
401
+ user = MoesifApi::UserModel.new()
402
402
  user.user_id = "12345"
403
403
  user.company_id = "67890" # If set, associate user with a company object
404
404
  user.campaign = campaign
@@ -419,7 +419,7 @@ This method is a convenient helper that calls the Moesif API lib.
419
419
  For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby#update-a-company).
420
420
 
421
421
  ```ruby
422
- metadata => {
422
+ metadata = {
423
423
  :org_name => 'Acme, Inc',
424
424
  :plan_name => 'Free',
425
425
  :deal_stage => 'Lead',
@@ -432,7 +432,7 @@ metadata => {
432
432
 
433
433
  # Campaign object is optional, but useful if you want to track ROI of acquisition channels
434
434
  # See https://www.moesif.com/docs/api#update-a-company for campaign schema
435
- campaign = CampaignModel.new()
435
+ campaign = MoesifApi::CampaignModel.new()
436
436
  campaign.utm_source = "google"
437
437
  campaign.utm_medium = "cpc"
438
438
  campaign.utm_campaign = "adwords"
@@ -441,7 +441,7 @@ campaign.utm_content = "landing"
441
441
 
442
442
  # Only company_id is required.
443
443
  # metadata can be any custom object
444
- company = CompanyModel.new()
444
+ company = MoesifApi::CompanyModel.new()
445
445
  company.company_id = "67890"
446
446
  company.company_domain = "acmeinc.com" # If domain is set, Moesif will enrich your profiles with publicly available info
447
447
  company.campaign = campaign
@@ -459,7 +459,7 @@ For details, visit the [Ruby API Reference](https://www.moesif.com/docs/api?ruby
459
459
  ```ruby
460
460
  companies = []
461
461
 
462
- metadata => {
462
+ metadata = {
463
463
  :org_name => 'Acme, Inc',
464
464
  :plan_name => 'Free',
465
465
  :deal_stage => 'Lead',
@@ -472,7 +472,7 @@ metadata => {
472
472
 
473
473
  # Campaign object is optional, but useful if you want to track ROI of acquisition channels
474
474
  # See https://www.moesif.com/docs/api#update-a-company for campaign schema
475
- campaign = CampaignModel.new()
475
+ campaign = MoesifApi::CampaignModel.new()
476
476
  campaign.utm_source = "google"
477
477
  campaign.utm_medium = "cpc"
478
478
  campaign.utm_campaign = "adwords"
@@ -481,7 +481,7 @@ campaign.utm_content = "landing"
481
481
 
482
482
  # Only company_id is required.
483
483
  # metadata can be any custom object
484
- company = CompanyModel.new()
484
+ company = MoesifApi::CompanyModel.new()
485
485
  company.company_id = "67890"
486
486
  company.company_domain = "acmeinc.com" # If domain is set, Moesif will enrich your profiles with publicly available info
487
487
  company.campaign = campaign
@@ -500,11 +500,11 @@ response = MoesifRack::MoesifMiddleware.new(@app, @options).update_companies_bat
500
500
  5. Invoke 'ruby test/moesif_rack_test.rb'
501
501
  6. Invoke 'ruby -I test test/moesif_rack_test.rb -n test_capture_outgoing' to test capturing outgoing API calls from your app to third parties like Stripe, Github or to your own dependencies.
502
502
 
503
- ## Example Code
503
+ ## Example Projects
504
504
 
505
- [Moesif Rack Example with Rails](https://github.com/Moesif/moesif-rails-example) is an example of Moesif Rack applied to a Rails application.
506
-
507
- [Moesif Rack Example](https://github.com/Moesif/moesif-rack-example) is an example of Moesif Rack applied to a Rack application.
505
+ - [Moesif Rails 5 Example](https://github.com/Moesif/moesif-rails5-example) is an example of Moesif with a Ruby on Rails 5 application.
506
+ - [Moesif Rails 4 Example](https://github.com/Moesif/moesif-rails4-example) is an example of Moesif with a Ruby on Rails 4 application.
507
+ - [Moesif Rack Example](https://github.com/Moesif/moesif-rack-example) is an example of Moesif applied to a Rack application.
508
508
 
509
509
  ## Other integrations
510
510
 
@@ -3,66 +3,71 @@ require 'json'
3
3
  require 'time'
4
4
  require 'zlib'
5
5
  require 'stringio'
6
+ require_relative './helpers.rb'
6
7
 
7
8
  class AppConfig
8
9
 
9
- def get_config(api_controller, debug)
10
+ def initialize debug
11
+ @debug = debug
12
+ @helpers = Helpers.new(debug)
13
+ end
14
+
15
+ def get_config(api_controller)
10
16
  # Get Application Config
11
17
  begin
12
18
  config_api_response = api_controller.get_app_config()
19
+ @helpers.log_debug("new config downloaded")
20
+ @helpers.log_debug(config_api_response.to_s)
13
21
  return config_api_response
14
22
  rescue MoesifApi::APIException => e
15
23
  if e.response_code.between?(401, 403)
16
- puts 'Unauthorized access getting application configuration. Please check your Appplication Id.'
17
- end
18
- if debug
19
- puts 'Error getting application configuration, with status code:'
20
- puts e.response_code
24
+ @helpers.log_debug 'Unauthorized access getting application configuration. Please check your Appplication Id.'
21
25
  end
26
+ @helpers.log_debug 'Error getting application configuration, with status code:'
27
+ @helpers.log_debug e.response_code
28
+ rescue => e
29
+ @helpers.log_debug e.to_s
22
30
  end
31
+ rescue
23
32
  end
24
33
 
25
- def parse_configuration(config_api_response, debug)
34
+ def parse_configuration(config_api_response)
26
35
  # Parse configuration object and return Etag, sample rate and last updated time
27
36
  begin
28
37
  # Rails return gzipped compressed response body, so decompressing it and getting JSON response body
29
- response_body = decompress_gzip_body(config_api_response, debug)
38
+ response_body = decompress_gzip_body(config_api_response)
39
+ @helpers.log_debug(response_body.to_s)
30
40
 
31
41
  # Check if response body is not nil
32
42
  if !response_body.nil? then
33
43
  # Return Etag, sample rate and last updated time
34
- return config_api_response.headers[:x_moesif_config_etag], response_body.fetch("sample_rate", 100), Time.now.utc
44
+ return response_body, config_api_response.headers[:x_moesif_config_etag], Time.now.utc
35
45
  else
36
- if debug
37
- puts 'Response body is nil, assuming default behavior'
38
- end
46
+ @helpers.log_debug 'Response body is nil, assuming default behavior'
39
47
  # Response body is nil, so assuming default behavior
40
48
  return nil, 100, Time.now.utc
41
49
  end
42
50
  rescue => exception
43
- if debug
44
- puts 'Error while parsing the configuration object, assuming default behavior'
45
- puts exception.to_s
46
- end
51
+ @helpers.log_debug 'Error while parsing the configuration object, assuming default behavior'
52
+ @helpers.log_debug exception.to_s
47
53
  # Assuming default behavior
48
54
  return nil, 100, Time.now.utc
49
55
  end
50
56
  end
51
57
 
52
- def get_sampling_percentage(config_api_response, user_id, company_id, debug)
58
+ def get_sampling_percentage(config_api_response, user_id, company_id)
53
59
  # Get sampling percentage
54
60
  begin
55
- # Rails return gzipped compressed response body, so decompressing it and getting JSON response body
56
- response_body = decompress_gzip_body(config_api_response, debug)
57
-
58
61
  # Check if response body is not nil
59
- if !response_body.nil? then
60
-
62
+ if !config_api_response.nil? then
63
+ @helpers.log_debug("Getting sample rate for user #{user_id} company #{company_id}")
64
+ @helpers.log_debug(config_api_response.to_s)
65
+
61
66
  # Get user sample rate object
62
- user_sample_rate = response_body.fetch('user_sample_rate', nil)
67
+ user_sample_rate = config_api_response.fetch('user_sample_rate', nil)
63
68
 
64
69
  # Get company sample rate object
65
- company_sample_rate = response_body.fetch('company_sample_rate', nil)
70
+ company_sample_rate = config_api_response.fetch('company_sample_rate', nil)
66
71
 
67
72
  # Get sample rate for the user if exist
68
73
  if !user_id.nil? && !user_sample_rate.nil? && user_sample_rate.key?(user_id)
@@ -75,22 +80,18 @@ class AppConfig
75
80
  end
76
81
 
77
82
  # Return sample rate
78
- return response_body.fetch('sample_rate', 100)
83
+ return config_api_response.fetch('sample_rate', 100)
79
84
  else
80
- if debug
81
- puts 'Assuming default behavior as response body is nil - '
82
- end
85
+ @helpers.log_debug 'Assuming default behavior as response body is nil - '
83
86
  return 100
84
87
  end
85
88
  rescue => exception
86
- if debug
87
- puts 'Error while geting sampling percentage, assuming default behavior'
88
- end
89
+ @helpers.log_debug 'Error while geting sampling percentage, assuming default behavior'
89
90
  return 100
90
91
  end
91
92
  end
92
93
 
93
- def decompress_gzip_body(config_api_response, debug)
94
+ def decompress_gzip_body(config_api_response)
94
95
  # Decompress gzip response body
95
96
  begin
96
97
  # Check if the content-encoding header exist and is of type zip
@@ -105,16 +106,12 @@ class AppConfig
105
106
  # Return the parsed body
106
107
  return JSON.parse( uncompressed_string )
107
108
  else
108
- if debug
109
- puts 'Content Encoding is of type other than gzip, returning nil'
110
- end
109
+ @helpers.log_debug 'Content Encoding is of type other than gzip, returning nil'
111
110
  return nil
112
111
  end
113
112
  rescue => exception
114
- if debug
115
- puts 'Error while decompressing the response body'
116
- puts exception.to_s
117
- end
113
+ @helpers.log_debug 'Error while decompressing the response body'
114
+ @helpers.log_debug exception.to_s
118
115
  return nil
119
116
  end
120
117
  end
@@ -1,8 +1,8 @@
1
1
 
2
2
  def is_ip?(value)
3
+ ipv4 = /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
4
+ ipv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
3
5
  if
4
- ipv4 = /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/
5
- ipv6 = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/
6
6
  # We use !! to convert the return value to a boolean
7
7
  !!(value =~ ipv4 or value=~ ipv6)
8
8
  end
@@ -0,0 +1,14 @@
1
+ require 'time'
2
+
3
+ class Helpers
4
+
5
+ def initialize debug
6
+ @debug = debug
7
+ end
8
+
9
+ def log_debug(message)
10
+ if @debug
11
+ puts("#{Time.now.to_s} [Moesif Middleware] PID #{Process.pid} TID #{Thread.current.object_id} #{message}")
12
+ end
13
+ end
14
+ end
@@ -6,6 +6,9 @@ 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_relative './helpers.rb'
10
+ require 'zlib'
11
+ require 'stringio'
9
12
 
10
13
  module MoesifRack
11
14
 
@@ -26,30 +29,34 @@ module MoesifRack
26
29
  @mask_data = options['mask_data']
27
30
  @skip = options['skip']
28
31
  @debug = options['debug']
29
- @app_config = AppConfig.new
30
- @config = @app_config.get_config(@api_controller, @debug)
32
+ @app_config = AppConfig.new(@debug)
33
+ @helpers = Helpers.new(@debug)
34
+ @config = @app_config.get_config(@api_controller)
31
35
  @config_etag = nil
32
- @sampling_percentage = 100
33
- @last_updated_time = Time.now.utc
36
+ @last_config_download_time = Time.now.utc
37
+ @last_worker_run = Time.now.utc
34
38
  @config_dict = Hash.new
35
39
  @disable_transaction_id = options['disable_transaction_id'] || false
36
40
  @log_body = options.fetch('log_body', true)
41
+ @batch_size = options['batch_size'] || 25
42
+ @batch_max_time = options['batch_max_time'] || 2
43
+ @events_queue = Queue.new
44
+ @event_response_config_etag = nil
45
+ start_worker()
46
+
37
47
  begin
38
- if !@config.nil?
39
- @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
48
+ new_config = @app_config.get_config(@api_controller)
49
+ if !new_config.nil?
50
+ @config, @config_etag, @last_config_download_time = @app_config.parse_configuration(new_config)
40
51
  end
41
52
  rescue => exception
42
- if @debug
43
- puts 'Error while parsing application configuration on initialization'
44
- puts exception.to_s
45
- end
53
+ @helpers.log_debug 'Error while parsing application configuration on initialization'
54
+ @helpers.log_debug exception.to_s
46
55
  end
47
56
  @capture_outoing_requests = options['capture_outoing_requests']
48
57
  @capture_outgoing_requests = options['capture_outgoing_requests']
49
58
  if @capture_outoing_requests || @capture_outgoing_requests
50
- if @debug
51
- puts 'Start Capturing outgoing requests'
52
- end
59
+ @helpers.log_debug 'Start Capturing outgoing requests'
53
60
  require_relative '../../moesif_capture_outgoing/httplog.rb'
54
61
  MoesifCaptureOutgoing.start_capture_outgoing(options)
55
62
  end
@@ -71,12 +78,84 @@ module MoesifRack
71
78
  CompanyHelper.new.update_companies_batch(@api_controller, @debug, company_profiles)
72
79
  end
73
80
 
74
- def call env
75
- start_time = Time.now.utc.iso8601
81
+ def start_with_json(body)
82
+ body.start_with?('{') || body.start_with?('[')
83
+ end
84
+
85
+ def decompress_body(body)
86
+ Zlib::GzipReader.new(StringIO.new(body)).read
87
+ end
88
+
89
+ def transform_headers(headers)
90
+ Hash[headers.map { |k, v| [k.downcase, v]}]
91
+ end
92
+
93
+ def base64_encode_body(body)
94
+ return Base64.encode64(body), 'base64'
95
+ end
76
96
 
97
+ def @helpers.log_debug(message)
77
98
  if @debug
78
- puts 'inside moesif middleware'
99
+ puts("#{Time.now.to_s} [Moesif Middleware] PID #{Process.pid} TID #{Thread.current.object_id} #{message}")
100
+ end
101
+ end
102
+
103
+ def parse_body(body, headers)
104
+ begin
105
+ if start_with_json(body)
106
+ parsed_body = JSON.parse(body)
107
+ transfer_encoding = 'json'
108
+ elsif headers.key?('content-encoding') && ((headers['content-encoding'].downcase).include? "gzip")
109
+ uncompressed_string = decompress_body(body)
110
+ parsed_body, transfer_encoding = base64_encode_body(uncompressed_string)
111
+ else
112
+ parsed_body, transfer_encoding = base64_encode_body(body)
113
+ end
114
+ rescue
115
+ parsed_body, transfer_encoding = base64_encode_body(body)
116
+ end
117
+ return parsed_body, transfer_encoding
118
+ end
119
+
120
+ def start_worker
121
+ Thread::new do
122
+ @last_worker_run = Time.now.utc
123
+ loop do
124
+ begin
125
+ until @events_queue.empty? do
126
+ batch_events = []
127
+ until batch_events.size == @batch_size || @events_queue.empty? do
128
+ batch_events << @events_queue.pop
129
+ end
130
+ @helpers.log_debug("Sending #{batch_events.size.to_s} events to Moesif")
131
+ event_api_response = @api_controller.create_events_batch(batch_events)
132
+ @event_response_config_etag = event_api_response[:x_moesif_config_etag]
133
+ @helpers.log_debug(event_api_response.to_s)
134
+ @helpers.log_debug("Events successfully sent to Moesif")
135
+ end
136
+
137
+ if @events_queue.empty?
138
+ @helpers.log_debug("No events to read from the queue")
139
+ end
140
+
141
+ sleep @batch_max_time
142
+ rescue MoesifApi::APIException => e
143
+ if e.response_code.between?(401, 403)
144
+ puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
145
+ @helpers.log_debug(e.to_s)
146
+ end
147
+ @helpers.log_debug("Error sending event to Moesif, with status code #{e.response_code.to_s}")
148
+ rescue => e
149
+ @helpers.log_debug(e.to_s)
150
+ end
151
+ end
79
152
  end
153
+ end
154
+
155
+ def call env
156
+ start_time = Time.now.utc.iso8601
157
+
158
+ @helpers.log_debug('Calling Moesif middleware')
80
159
 
81
160
  status, headers, body = @app.call env
82
161
  end_time = Time.now.utc.iso8601
@@ -86,7 +165,7 @@ module MoesifRack
86
165
  complex_copy = env.dup
87
166
 
88
167
  req_headers = {}
89
- complex_copy.select {|k,v| k.start_with? 'HTTP_'}.each do |key, val|
168
+ complex_copy.select {|k,v| k.start_with?('HTTP_', 'CONTENT_') }.each do |key, val|
90
169
  new_key = key.sub(/^HTTP_/, '')
91
170
  new_key = new_key.sub('_', '-')
92
171
  req_headers[new_key] = val
@@ -99,12 +178,7 @@ module MoesifRack
99
178
 
100
179
  if @log_body
101
180
  if req_body_string && req_body_string.length != 0
102
- begin
103
- req_body = JSON.parse(req_body_string)
104
- rescue
105
- req_body = Base64.encode64(req_body_string)
106
- req_body_transfer_encoding = 'base64'
107
- end
181
+ req_body, req_body_transfer_encoding = parse_body(req_body_string, transform_headers(req_headers))
108
182
  end
109
183
  end
110
184
 
@@ -116,12 +190,7 @@ module MoesifRack
116
190
 
117
191
  if @log_body
118
192
  if rsp_body_string && rsp_body_string.length != 0
119
- begin
120
- rsp_body = JSON.parse(rsp_body_string)
121
- rescue
122
- rsp_body = Base64.encode64(rsp_body_string)
123
- rsp_body_transfer_encoding = 'base64'
124
- end
193
+ rsp_body, rsp_body_transfer_encoding = parse_body(rsp_body_string, transform_headers(rsp_headers))
125
194
  end
126
195
  end
127
196
 
@@ -181,89 +250,71 @@ module MoesifRack
181
250
  event_model.direction = "Incoming"
182
251
 
183
252
  if @identify_user
184
- if @debug
185
- puts "calling identify user proc"
186
- end
253
+ @helpers.log_debug "calling identify user proc"
187
254
  event_model.user_id = @identify_user.call(env, headers, body)
188
255
  end
189
256
 
190
257
  if @identify_company
191
- if @debug
192
- puts "calling identify company proc"
193
- end
258
+ @helpers.log_debug "calling identify company proc"
194
259
  event_model.company_id = @identify_company.call(env, headers, body)
195
260
  end
196
261
 
197
262
  if @get_metadata
198
- if @debug
199
- puts "calling get_metadata proc"
200
- end
263
+ @helpers.log_debug "calling get_metadata proc"
201
264
  event_model.metadata = @get_metadata.call(env, headers, body)
202
265
  end
203
266
 
204
267
  if @identify_session
205
- if @debug
206
- puts "calling identify session proc"
207
- end
268
+ @helpers.log_debug "calling identify session proc"
208
269
  event_model.session_token = @identify_session.call(env, headers, body)
209
270
  end
210
271
  if @mask_data
211
- if @debug
212
- puts "calling mask_data proc"
213
- end
272
+ @helpers.log_debug "calling mask_data proc"
214
273
  event_model = @mask_data.call(event_model)
215
274
  end
216
275
 
217
- if @debug
218
- puts "sending data to moesif"
219
- puts event_model.to_json
220
- end
276
+ @helpers.log_debug "sending data to moesif"
277
+ @helpers.log_debug event_model.to_json
221
278
  # Perform the API call through the SDK function
222
279
  begin
223
- @random_percentage = Random.rand(0.00..100.00)
280
+ random_percentage = Random.rand(0.00..100.00)
224
281
 
225
282
  begin
226
- @sampling_percentage = @app_config.get_sampling_percentage(@config, event_model.user_id, event_model.company_id, @debug)
283
+ sampling_percentage = @app_config.get_sampling_percentage(@config, event_model.user_id, event_model.company_id)
284
+ @helpers.log_debug "Using sample rate #{sampling_percentage}"
227
285
  rescue => exception
228
- if @debug
229
- puts 'Error while getting sampling percentage, assuming default behavior'
230
- puts exception.to_s
231
- end
232
- @sampling_percentage = 100
286
+ @helpers.log_debug 'Error while getting sampling percentage, assuming default behavior'
287
+ @helpers.log_debug exception.to_s
288
+ sampling_percentage = 100
233
289
  end
234
290
 
235
- if @sampling_percentage > @random_percentage
236
- event_model.weight = @app_config.calculate_weight(@sampling_percentage)
237
- event_api_response = @api_controller.create_event(event_model)
238
- event_response_config_etag = event_api_response[:x_moesif_config_etag]
291
+ if sampling_percentage > random_percentage
292
+ event_model.weight = @app_config.calculate_weight(sampling_percentage)
293
+ # Add Event to the queue
294
+ @events_queue << event_model
295
+ @helpers.log_debug("Event added to the queue ")
296
+ if Time.now.utc > (@last_config_download_time + 60)
297
+ start_worker()
298
+ end
239
299
 
240
- if !event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != event_response_config_etag && Time.now.utc > @last_updated_time + 300
300
+ if !@event_response_config_etag.nil? && !@config_etag.nil? && @config_etag != @event_response_config_etag && Time.now.utc > (@last_config_download_time + 300)
241
301
  begin
242
- @config = @app_config.get_config(@api_controller, @debug)
243
- @config_etag, @sampling_percentage, @last_updated_time = @app_config.parse_configuration(@config, @debug)
302
+ new_config = @app_config.get_config(@api_controller)
303
+ if !new_config.nil?
304
+ @config, @config_etag, @last_config_download_time = @app_config.parse_configuration(new_config)
305
+ end
306
+
244
307
  rescue => exception
245
- if @debug
246
- puts 'Error while updating the application configuration'
247
- puts exception.to_s
248
- end
308
+ @helpers.log_debug 'Error while updating the application configuration'
309
+ @helpers.log_debug exception.to_s
249
310
  end
250
311
  end
251
- if @debug
252
- puts("Event successfully sent to Moesif")
253
- end
254
312
  else
255
- if @debug
256
- puts("Skipped Event due to sampling percentage: " + @sampling_percentage.to_s + " and random percentage: " + @random_percentage.to_s)
257
- end
258
- end
259
- rescue MoesifApi::APIException => e
260
- if e.response_code.between?(401, 403)
261
- puts "Unathorized accesss sending event to Moesif. Please verify your Application Id."
262
- end
263
- if @debug
264
- puts "Error sending event to Moesif, with status code: "
265
- puts e.response_code
313
+ @helpers.log_debug("Skipped Event due to sampling percentage: " + sampling_percentage.to_s + " and random percentage: " + random_percentage .to_s)
266
314
  end
315
+ rescue => exception
316
+ @helpers.log_debug "Error adding event to the queue "
317
+ @helpers.log_debug exception.to_s
267
318
  end
268
319
 
269
320
  end
@@ -277,11 +328,7 @@ module MoesifRack
277
328
  end
278
329
 
279
330
  if !should_skip
280
- if @debug
281
- process_send.call
282
- else
283
- Thread.start(&process_send)
284
- end
331
+ process_send.call
285
332
  end
286
333
 
287
334
  [status, headers, body]
@@ -221,6 +221,10 @@ module MoesifCaptureOutgoing
221
221
  puts "Error sending event to Moesif, with status code: "
222
222
  puts e.response_code
223
223
  end
224
+ rescue => e
225
+ if debug
226
+ puts e.to_s
227
+ end
224
228
  end
225
229
  else
226
230
  if @debug
@@ -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,28 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moesif_rack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moesif, Inc
8
8
  - Xing Wang
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-12-18 00:00:00.000000000 Z
12
+ date: 2020-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: test-unit
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.1'
21
+ - - ">="
19
22
  - !ruby/object:Gem::Version
20
23
  version: 3.1.5
21
- type: :runtime
24
+ type: :development
22
25
  prerelease: false
23
26
  version_requirements: !ruby/object:Gem::Requirement
24
27
  requirements:
25
28
  - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '3.1'
31
+ - - ">="
26
32
  - !ruby/object:Gem::Version
27
33
  version: 3.1.5
28
34
  - !ruby/object:Gem::Dependency
@@ -31,15 +37,21 @@ dependencies:
31
37
  requirements:
32
38
  - - "~>"
33
39
  - !ruby/object:Gem::Version
34
- version: 1.2.11
40
+ version: '1.2'
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.12
35
44
  type: :runtime
36
45
  prerelease: false
37
46
  version_requirements: !ruby/object:Gem::Requirement
38
47
  requirements:
39
48
  - - "~>"
40
49
  - !ruby/object:Gem::Version
41
- version: 1.2.11
42
- description: Collection/Data Ingestion SDK for Rack (also Rails) Middleware / RoR
50
+ version: '1.2'
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.2.12
54
+ description: Rack/Rails middleware to log API calls to Moesif API analytics and monitoring
43
55
  email: xing@moesif.com
44
56
  executables: []
45
57
  extensions: []
@@ -50,6 +62,7 @@ files:
50
62
  - lib/moesif_rack.rb
51
63
  - lib/moesif_rack/app_config.rb
52
64
  - lib/moesif_rack/client_ip.rb
65
+ - lib/moesif_rack/helpers.rb
53
66
  - lib/moesif_rack/moesif_middleware.rb
54
67
  - lib/moesif_rack/update_company.rb
55
68
  - lib/moesif_rack/update_user.rb
@@ -60,8 +73,15 @@ files:
60
73
  homepage: https://moesif.com
61
74
  licenses:
62
75
  - Apache-2.0
63
- metadata: {}
64
- post_install_message:
76
+ metadata:
77
+ bug_tracker_uri: https://github.com/Moesif/moesif-rack/issues
78
+ changelog_uri: https://github.com/Moesif/moesif-rack/releases
79
+ documentation_uri: https://www.moesif.com/docs/server-integration/rack/
80
+ homepage_uri: https://www.moesif.com
81
+ mailing_list_uri: https://github.com/Moesif/moesif-rack
82
+ source_code_uri: https://github.com/Moesif/moesif-rack
83
+ wiki_uri: https://github.com/Moesif/moesif-rack
84
+ post_install_message:
65
85
  rdoc_options: []
66
86
  require_paths:
67
87
  - lib
@@ -76,9 +96,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
96
  - !ruby/object:Gem::Version
77
97
  version: '0'
78
98
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 2.7.7
81
- signing_key:
99
+ rubygems_version: 3.1.4
100
+ signing_key:
82
101
  specification_version: 4
83
102
  summary: moesif_rack
84
103
  test_files: []