zuora_connect 1.6.05 → 1.6.06

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
  SHA1:
3
- metadata.gz: 453d594fb07a0bff60f8e49caaecaf6946b9cae9
4
- data.tar.gz: d748b6246b8978f0c11540034061ee38ea9aca75
3
+ metadata.gz: 3aab6b6790b92249ea03f26bf79222ec77720566
4
+ data.tar.gz: 5f09e4567ab8a4bdac1defe735a5b43809295dd9
5
5
  SHA512:
6
- metadata.gz: 1a760b5accc67e3b0053e30e7f70f3661804de2f4742a04615e63b548710ce9bda1505843549523b26371f16d8241fa50a538ddc9bd5d0caac2e2afa1e5d0038
7
- data.tar.gz: 2f0cac559a7556f6eab011d8983bbbfd54ea3af321b31f7431099a211c8473480edd99e6db45ab8a3e7152a66fdad60121b9bc99ab9186248b4cb881f2892542
6
+ metadata.gz: 9b20a0da49a4ee3ff62950fb04419a5d3a98fe1d381ed9b9bcc04c7564c8e9d053db136740a82ff74ad950ce47e094aa63b66739dc35ba1a7d4924c95ab4541b
7
+ data.tar.gz: fe902be31ee9eb458cc92204cc4addb4ea50a973973247b6a1d44fb1b670a0d0dc35b1644ac5ff8248741b1926dd589e8d17372b1199975530fb98ddbc65a2b9
@@ -13,17 +13,25 @@ module ZuoraConnect
13
13
  def drop
14
14
  instance_id = @appinstance.id
15
15
  if session["#{instance_id}::destroy"] && ZuoraConnect::AppInstance.where(:id => instance_id).size != 0
16
- ZuoraConnect::AppInstance.destroy(instance_id)
17
- msg = Apartment::Tenant.drop(instance_id)
18
- respond_to do |format|
19
- message = Hash.new
20
- message = {"error" => {:message => msg.error_message}} if msg.error_message != ""
21
- message["message"] = msg.result_status == 1 ? "success" : "error"
22
- format.json {render :json => message}
16
+ if @appinstance.drop_instance
17
+ ZuoraConnect::AppInstance.destroy(instance_id)
18
+ msg = Apartment::Tenant.drop(instance_id)
19
+
20
+ respond_to do |format|
21
+ if msg.error_message.present?
22
+ format.json {render json: {"message" => msg.error_message}, status: :bad_request }
23
+ else
24
+ format.json {render json: {}, status: :ok}
25
+ end
26
+ end
27
+ else
28
+ respond_to do |format|
29
+ format.json {render json: {"message" => @appinstance.drop_message}, status: :bad_request}
30
+ end
23
31
  end
24
32
  else
25
33
  respond_to do |format|
26
- format.json {render :json => { "message" => "Unauthorized"}}
34
+ format.json { render json: { "message" => "Unauthorized"}, status: :unauthorized }
27
35
  end
28
36
  end
29
37
  end
@@ -4,8 +4,8 @@ module ZuoraConnect
4
4
  default_scope {select(ZuoraConnect::AppInstance.column_names.delete_if {|x| ["catalog_mapping", "catalog"].include?(x) }) }
5
5
  after_initialize :init
6
6
  self.table_name = "zuora_connect_app_instances"
7
- attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version
8
-
7
+ attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message
8
+ @@telegraf_host = nil
9
9
  REFRESH_TIMEOUT = 2.minute #Used to determine how long to wait on current refresh call before executing another
10
10
  INSTANCE_REFRESH_WINDOW = 30.minutes #Used to set how how long till app starts attempting to refresh cached task connect data
11
11
  INSTANCE_REDIS_CACHE_PERIOD = 60.minutes #Used to determine how long to cached task data will live for
@@ -25,12 +25,31 @@ module ZuoraConnect
25
25
  self.apartment_switch(nil, true)
26
26
  end
27
27
 
28
+ def self.write_metric(series: 'Unknown', tags: {}, values: {})
29
+ begin
30
+ if @@telegraf_host.blank?
31
+ Rails.logger.debug('Need new connection') if ZuoraConnect.configuration.telegraf_debug
32
+ uri = URI.parse(ZuoraConnect.configuration.telegraf_endpoint)
33
+ @@telegraf_host = UDPSocket.new.tap do |socket|
34
+ socket.connect uri.host, uri.port
35
+ end
36
+ end
37
+ @@telegraf_host.write InfluxDB::PointValue.new({series: series, tags: tags, values: values}).dump
38
+ rescue => ex
39
+ @@telegraf_host = nil
40
+ Rails.logger.tagged("Telegraf") do
41
+ logger.warn('Failed to write')
42
+ logger.warn(ex.class)
43
+ logger.warn(ex.message)
44
+ end
45
+ end
46
+ end
28
47
 
29
48
  # Methods for writing Telegraf metrics
30
49
 
31
50
  # Returns the process type if any
32
51
  def self.get_process_type
33
- p_type = nil
52
+ p_type = 'Unknown'
34
53
  if ENV['HOSTNAME'] && ENV['DEIS_APP']
35
54
  temp = ENV['HOSTNAME'].split(ENV['DEIS_APP'])[1]
36
55
  temp = temp.split(/(-[0-9a-zA-Z]{5})$/)[0] # remove the 5 char hash
@@ -40,57 +59,31 @@ module ZuoraConnect
40
59
  end
41
60
 
42
61
  # Write to telegraf
43
- def self.write_to_telegraf(endpoint_name: nil, method_name: nil, status_code: nil, response_time: nil, db_runtime: nil, view_runtime: nil, content_type: nil, direction: nil, error_type: nil, app_instance: nil, function_name: nil)
44
-
45
- # To avoid writing metrics from rspec tests
46
- if ENV['DEIS_APP']
47
- # Getting the process type
48
- p_type = ZuoraConnect::AppInstanceBase.get_process_type
49
-
50
- if direction == "inbound" && ZuoraConnect.configuration.enable_inbound_metrics_flag
51
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
52
-
53
- # Separately handling 200 and non 200 as influx does not accept nil as a value
54
- if db_runtime && view_runtime
55
- # 200 requests
56
- begin
57
- ZuoraConnect.configuration.telegraf_client.write(ZuoraConnect.configuration.influxdb_series_name_inbound,
58
- tags: {"app_name": "#{ZuoraConnect.configuration.app_name}", "controller": endpoint_name.split("#")[0] , "action": endpoint_name.split("#")[1] , "content-type": content_type, method: method_name, status: status_code, process_type: p_type, "app_instance": app_instance},
59
- values: {response_time: response_time, db_time: db_runtime, view_time: view_runtime})
60
- rescue => e
61
- raise e
62
- end
63
- else
64
- # non 200 requests
65
- begin
66
- ZuoraConnect.configuration.telegraf_client.write(ZuoraConnect.configuration.influxdb_series_name_inbound,
67
- tags: {"app_name": "#{ZuoraConnect.configuration.app_name}", "controller": endpoint_name.split("#")[0] , "action": endpoint_name.split("#")[1], "content-type": content_type, method: method_name, status: status_code, process_type: p_type, "app_instance": app_instance},
68
- values: {response_time: response_time})
69
- rescue=> e
70
- raise e
62
+ def self.write_to_telegraf(direction: nil, tags: {}, values: {})
63
+ Rails.logger.tagged("Telegraf") do
64
+ time = Benchmark.measure do |bench|
65
+ # To avoid writing metrics from rspec tests
66
+ if ENV['DEIS_APP'] || true
67
+ # Getting the process type
68
+ p_type = self.get_process_type
69
+ app_instance = Thread.current[:appinstance].present? ? Thread.current[:appinstance].id : 0
70
+ tags = tags.merge({ app_name: ZuoraConnect.configuration.app_name, process_type: p_type, app_instance: app_instance})
71
+
72
+ if direction == :inbound && ZuoraConnect.configuration.enable_inbound_metrics_flag
73
+ series = ZuoraConnect.configuration.influxdb_series_name_inbound
74
+ self.write_metric(series: series, tags: tags, values: values)
75
+ elsif direction == :outbound && ZuoraConnect.configuration.enable_outbound_metrics_flag
76
+ series = ZuoraConnect.configuration.influxdb_series_name_outbound
77
+ self.write_metric(series: series, tags: tags, values: values)
71
78
  end
72
- end
73
79
 
74
- elsif direction == "outbound" && ZuoraConnect.configuration.enable_outbound_metrics_flag
75
- # if there is an error
76
- if error_type
77
- begin
78
- ZuoraConnect.configuration.telegraf_client.write(ZuoraConnect.configuration.influxdb_series_name_outbound,
79
- tags: {"app_name": "#{ZuoraConnect.configuration.app_name}", endpoint: endpoint_name, status: status_code, process_type: p_type, "app_instance": app_instance, "function_name": function_name, method: method_name, "error_type": error_type},
80
- values: {response_time: response_time})
81
- rescue => e
82
- raise e
83
- end
84
- else
85
- begin
86
- ZuoraConnect.configuration.telegraf_client.write(ZuoraConnect.configuration.influxdb_series_name_outbound,
87
- tags: {"app_name": "#{ZuoraConnect.configuration.app_name}", endpoint: endpoint_name, status: status_code, process_type: p_type, "app_instance": app_instance, "function_name": function_name, method: method_name},
88
- values: {response_time: response_time})
89
- rescue => e
90
- raise e
91
- end
92
80
  end
93
81
  end
82
+ if ZuoraConnect.configuration.telegraf_debug
83
+ Rails.logger.debug(tags.to_s)
84
+ Rails.logger.debug(values.to_s)
85
+ Rails.logger.debug("Writing #{direction.capitalize}: #{time.real.round(4)}")
86
+ end
94
87
  end
95
88
  end
96
89
 
@@ -223,7 +216,6 @@ module ZuoraConnect
223
216
 
224
217
  def refresh(session = nil)
225
218
  refresh_count ||= 0
226
- error_type = ""
227
219
  start = Time.now
228
220
  response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}.json",:body => {:access_token => self.access_token})
229
221
  response_time = Time.now - start
@@ -243,7 +235,6 @@ module ZuoraConnect
243
235
  Rails.logger.info("[#{self.id}] REFRESH TASK - #{ex.class} Retrying(#{refresh_count})")
244
236
  retry
245
237
  else
246
- error_type = "#{ex.class}"
247
238
  Rails.logger.fatal("[#{self.id}] REFRESH TASK - #{ex.class} Failed #{refresh_count}x")
248
239
  raise
249
240
  end
@@ -255,16 +246,9 @@ module ZuoraConnect
255
246
  end
256
247
  retry
257
248
  else
258
- error_type = "#{ex.class}"
259
249
  Rails.logger.fatal("[#{self.id}] REFRESH TASK - Failed #{refresh_count}x")
260
250
  raise
261
251
  end
262
- ensure
263
- # Writing to telegraf
264
- status_code = response.code if response
265
- endpoint_name = URI(ZuoraConnect.configuration.url).host
266
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
267
- ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET", "app_instance": app_instance)
268
252
  end
269
253
 
270
254
  #### START Task Mathods ####
@@ -304,28 +288,13 @@ module ZuoraConnect
304
288
  end
305
289
 
306
290
  def updateOption(optionId, value)
307
- begin
308
- start_time = Time.now
309
- response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/application_options/#{optionId}/edit?value=#{value}",:body => {:access_token => self.username})
310
- rescue => e
311
- error_type = "#{e.class}"
312
- ensure
313
- end_time = Time.now
314
- response_time = end_time - start_time
315
- status_code = response.code if response
316
- endpoint_name = URI(ZuoraConnect.configuration.url).host
317
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
318
- ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "GET", "app_instance": app_instance)
319
- return response
320
- end
291
+ response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/application_options/#{optionId}/edit?value=#{value}",:body => {:access_token => self.username})
321
292
  end
322
293
 
323
294
  #This can update an existing login, add a new login, change to another existing login
324
295
  #EXAMPLE: {"name": "ftp_login_14","username": "ftplogin7","tenant_type": "Custom","password": "test2","url": "www.ftp.com","custom_data": { "path": "/var/usr/test"}}
325
296
  def update_logins(options)
326
297
  update_login_count ||= 0
327
- start_time = Time.now
328
- error_type = ""
329
298
  response = HTTParty.post(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}/logins",:body => {:access_token => self.username}.merge(options))
330
299
  parsed_json = JSON.parse(response.body)
331
300
  if response.code == 200
@@ -344,7 +313,6 @@ module ZuoraConnect
344
313
  if (update_login_count += 1) < 3
345
314
  retry
346
315
  else
347
- error_type = "#{ex.class}"
348
316
  raise
349
317
  end
350
318
  rescue ZuoraConnect::Exceptions::ConnectCommunicationError => ex
@@ -354,16 +322,8 @@ module ZuoraConnect
354
322
  end
355
323
  retry
356
324
  else
357
- error_type = "#{ex.class}"
358
325
  raise
359
326
  end
360
- ensure
361
- end_time = Time.now
362
- response_time = end_time - start_time
363
- status_code = response.code if response
364
- endpoint_name = URI(ZuoraConnect.configuration.url).host
365
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
366
- ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST", "app_instance": app_instance)
367
327
  end
368
328
  #### END Task Mathods ####
369
329
 
@@ -382,7 +342,6 @@ module ZuoraConnect
382
342
 
383
343
  def refresh_oauth
384
344
  refresh_oauth_count ||= 0
385
- error_type = ""
386
345
  start = Time.now
387
346
  params = {
388
347
  :grant_type => "refresh_token",
@@ -409,7 +368,6 @@ module ZuoraConnect
409
368
  Rails.logger.info("[#{self.id}] REFRESH OAUTH - #{ex.class} Retrying(#{refresh_oauth_count})")
410
369
  retry
411
370
  else
412
- error_type = "#{ex.class}"
413
371
  Rails.logger.fatal("[#{self.id}] REFRESH OAUTH - #{ex.class} Failed #{refresh_oauth_count}x")
414
372
  raise
415
373
  end
@@ -424,15 +382,9 @@ module ZuoraConnect
424
382
  Rails.logger.info("[#{self.id}] REFRESH OAUTH - Failed Retrying(#{refresh_oauth_count})")
425
383
  retry
426
384
  else
427
- error_type = "#{ex.class}"
428
385
  Rails.logger.fatal("[#{self.id}] REFRESH OAUTH - Failed #{refresh_oauth_count}x")
429
386
  raise
430
387
  end
431
- ensure
432
- status_code = response.code if response
433
- endpoint_name = URI(ZuoraConnect.configuration.url).host
434
- Thread.current[:appinstance].present? ? app_instance = Thread.current[:appinstance].id : app_instance = 0
435
- ZuoraConnect::AppInstanceBase.write_to_telegraf("response_time": response_time, "status_code": status_code, "endpoint_name": endpoint_name, "direction": "outbound", "error_type": error_type, "function_name": "#{self.class}##{__method__}", "method_name": "POST", "app_instance": app_instance)
436
388
  end
437
389
  #### END Connect OAUTH methods ####
438
390
 
@@ -479,7 +431,7 @@ module ZuoraConnect
479
431
  if defined?(Redis.current)
480
432
  #Task data must be present and the last refresh cannot be old. We dont want to overwite new cache data with old
481
433
  if self.task_data.present? && (self.last_refresh.to_i > INSTANCE_REFRESH_WINDOW.ago.to_i)
482
- Rails.logger.info("[#{self.id}] Caching AppInstance")
434
+ Rails.logger.debug("[#{self.id}] Caching AppInstance")
483
435
  Redis.current.setex("AppInstance:#{self.id}", INSTANCE_REDIS_CACHE_PERIOD.to_i, encrypt_data(data: self.save_data))
484
436
  end
485
437
  Redis.current.del("Deleted:#{self.id}")
@@ -846,6 +798,12 @@ module ZuoraConnect
846
798
  return true
847
799
  end
848
800
 
801
+ #Method for overiding droping of an app instance
802
+ def drop_instance
803
+ self.drop_message = 'Ok to drop'
804
+ return true
805
+ end
806
+
849
807
  def reload_attributes(selected_attributes)
850
808
  raise "Attibutes must be array" if selected_attributes.class != Array
851
809
  value_attributes = self.class.unscoped.where(:id=>id).select(selected_attributes).first.attributes
@@ -4,15 +4,15 @@ module ZuoraConnect
4
4
  def initialize (fields)
5
5
  @clients = {}
6
6
  if fields["tenant_type"] == "Zuora" && fields["entities"] && fields["entities"].size > 0
7
- @clients["Default"] = ::ZuoraAPI::Login.new(fields.map{|k,v| [k.to_sym, v]}.to_h)
7
+ @clients["Default"] = ::ZuoraAPI::Basic.new(fields.map{|k,v| [k.to_sym, v]}.to_h)
8
8
  @default_entity = fields["entities"][0]["id"] if fields["entities"].size == 1
9
9
  fields["entities"].each do |entity|
10
10
  login_fields = fields.map{|k,v| [k.to_sym, v]}.to_h
11
11
  login_fields[:entity_id] = entity["id"]
12
- @clients[entity["id"]] = ::ZuoraAPI::Login.new(login_fields)
12
+ @clients[entity["id"]] = ::ZuoraAPI::Basic.new(login_fields)
13
13
  end
14
14
  elsif fields["tenant_type"] == "Zuora"
15
- @clients["Default"] = ::ZuoraAPI::Login.new(fields.map{|k,v| [k.to_sym, v]}.to_h)
15
+ @clients["Default"] = ::ZuoraAPI::Basic.new(fields.map{|k,v| [k.to_sym, v]}.to_h)
16
16
  end
17
17
 
18
18
  self.attr_builder("available_entities",@clients.keys) if fields["tenant_type"] == "Zuora"
@@ -0,0 +1,32 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter < AbstractAdapter
4
+ private
5
+ def load_additional_types(type_map, oids = nil)
6
+ initializer = OID::TypeMapInitializer.new(type_map)
7
+ if supports_ranges?
8
+ query = <<-SQL
9
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
10
+ FROM pg_type as t
11
+ LEFT JOIN pg_range as r ON oid = rngtypid
12
+ SQL
13
+ else
14
+ query = <<-SQL
15
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
16
+ FROM pg_type as t
17
+ SQL
18
+ end
19
+
20
+ if oids
21
+ query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
22
+ else
23
+ query += initializer.query_conditions_for_initial_load(type_map)
24
+ end
25
+
26
+ execute_and_clear(query, "SCHEMA", []) do |records|
27
+ initializer.run(records)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,79 @@
1
+ module InfluxDB
2
+ # Convert data point to string using Line protocol
3
+ class PointValue
4
+ attr_reader :series, :values, :tags, :timestamp
5
+
6
+ def initialize(data)
7
+ @series = escape data[:series], :measurement
8
+ @values = escape_values data[:values]
9
+ @tags = escape_tags data[:tags]
10
+ @timestamp = data[:timestamp]
11
+ end
12
+
13
+ def dump
14
+ dump = @series.dup
15
+ dump << ",#{@tags}" if @tags
16
+ dump << " #{@values}"
17
+ dump << " #{@timestamp}" if @timestamp
18
+ dump
19
+ end
20
+
21
+ private
22
+
23
+ ESCAPES = {
24
+ measurement: [' '.freeze, ','.freeze],
25
+ tag_key: ['='.freeze, ' '.freeze, ','.freeze],
26
+ tag_value: ['='.freeze, ' '.freeze, ','.freeze],
27
+ field_key: ['='.freeze, ' '.freeze, ','.freeze, '"'.freeze],
28
+ field_value: ["\\".freeze, '"'.freeze],
29
+ }.freeze
30
+
31
+ private_constant :ESCAPES
32
+
33
+ def escape(str, type)
34
+ # rubocop:disable Layout/AlignParameters
35
+ str = str.encode "UTF-8".freeze, "UTF-8".freeze,
36
+ invalid: :replace,
37
+ undef: :replace,
38
+ replace: "".freeze
39
+ # rubocop:enable Layout/AlignParameters
40
+
41
+ ESCAPES[type].each do |ch|
42
+ str = str.gsub(ch) { "\\#{ch}" }
43
+ end
44
+ str
45
+ end
46
+
47
+ def escape_values(values)
48
+ return if values.nil?
49
+ values.map do |k, v|
50
+ key = escape(k.to_s, :field_key)
51
+ val = escape_value(v)
52
+ "#{key}=#{val}"
53
+ end.join(",".freeze)
54
+ end
55
+
56
+ def escape_value(value)
57
+ if value.is_a?(String)
58
+ '"'.freeze + escape(value, :field_value) + '"'.freeze
59
+ elsif value.is_a?(Integer)
60
+ "#{value}i"
61
+ else
62
+ value.to_s
63
+ end
64
+ end
65
+
66
+ def escape_tags(tags)
67
+ return if tags.nil?
68
+
69
+ tags = tags.map do |k, v|
70
+ key = escape(k.to_s, :tag_key)
71
+ val = escape(v.to_s, :tag_value)
72
+
73
+ "#{key}=#{val}" unless key == "".freeze || val == "".freeze
74
+ end.compact
75
+
76
+ tags.join(",") unless tags.empty?
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,218 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'set'
4
+
5
+ # Usage:
6
+ #
7
+ # require 'http_logger'
8
+ #
9
+ # == Setup logger
10
+ #
11
+ # HttpLogger.logger = Logger.new('/tmp/all.log')
12
+ # HttpLogger.log_headers = true
13
+ #
14
+ # == Do request
15
+ #
16
+ # res = Net::HTTP.start(url.host, url.port) { |http|
17
+ # http.request(req)
18
+ # }
19
+ # ...
20
+ #
21
+ # == View the log
22
+ #
23
+ # cat /tmp/all.log
24
+ class HttpLogger
25
+ class << self
26
+ attr_accessor :collapse_body_limit
27
+ attr_accessor :log_headers
28
+ attr_accessor :log_request_body
29
+ attr_accessor :log_response_body
30
+ attr_accessor :logger
31
+ attr_accessor :colorize
32
+ attr_accessor :ignore
33
+ attr_accessor :level
34
+ end
35
+
36
+ self.log_headers = false
37
+ self.log_request_body = true
38
+ self.log_response_body = true
39
+ self.colorize = true
40
+ self.collapse_body_limit = 5000
41
+ self.ignore = []
42
+ self.level = :debug
43
+
44
+ def self.perform(*args, &block)
45
+ instance.perform(*args, &block)
46
+ end
47
+
48
+ def self.instance
49
+ @instance ||= HttpLogger.new
50
+ end
51
+
52
+ def self.deprecate_config(option)
53
+ warn "Net::HTTP.#{option} is deprecated. Use HttpLogger.#{option} instead."
54
+ end
55
+
56
+ def perform(http, request, request_body)
57
+ start_time = Time.now
58
+ tags = {}
59
+ response = yield
60
+ rescue => ex
61
+ tags = tags.merge({error_type: ex.class})
62
+ raise
63
+ ensure
64
+ values = {response_time: ((Time.now - start_time)*1000).round(2)}
65
+ if require_logging?(http, request)
66
+ tags = tags.merge({endpoint: http.address, method: request.method})
67
+ log_request_url(http, request, start_time)
68
+ log_request_body(request)
69
+ log_request_headers(request)
70
+ if defined?(response) && response
71
+ tags = tags.merge({status: response.code.to_i})
72
+ log_response_code(response)
73
+ log_response_headers(response)
74
+ log_response_body(response.body)
75
+ end
76
+ ZuoraConnect::AppInstance.write_to_telegraf(direction: :outbound, tags: tags, values: values)
77
+ end
78
+ end
79
+
80
+ protected
81
+
82
+ def log_request_url(http, request, start_time)
83
+ ofset = Time.now - start_time
84
+ log("HTTP #{request.method} (%0.2fms)" % (ofset * 1000), request_url(http, request))
85
+ end
86
+
87
+ def request_url(http, request)
88
+ URI.decode("http#{"s" if http.use_ssl?}://#{http.address}:#{http.port}#{request.path}")
89
+ end
90
+
91
+ def log_request_headers(request)
92
+ if self.class.log_headers
93
+ request.each_capitalized { |k,v| log("HTTP request header", "#{k}: #{v}") }
94
+ end
95
+ end
96
+
97
+ HTTP_METHODS_WITH_BODY = Set.new(%w(POST PUT GET PATCH))
98
+
99
+ def log_request_body(request)
100
+ if self.class.log_request_body
101
+ if HTTP_METHODS_WITH_BODY.include?(request.method)
102
+ if (body = request.body) && !body.empty?
103
+ log("Request body", truncate_body(body))
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ def log_response_code(response)
110
+ log("Response status", "#{response.class} (#{response.code})")
111
+ end
112
+
113
+ def log_response_headers(response)
114
+ if self.class.log_headers
115
+ response.each_capitalized { |k,v| log("HTTP response header", "#{k}: #{v}") }
116
+ end
117
+ end
118
+
119
+ def log_response_body(body)
120
+ if self.class.log_response_body
121
+ if body.is_a?(Net::ReadAdapter)
122
+ log("Response body", "<impossible to log>")
123
+ else
124
+ if body && !body.empty?
125
+ log("Response body", truncate_body(body))
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ def require_logging?(http, request)
132
+ self.logger && !ignored?(http, request) && (http.started? || fakeweb?(http, request))
133
+ end
134
+
135
+ def ignored?(http, request)
136
+ url = request_url(http, request)
137
+ self.class.ignore.any? do |pattern|
138
+ url =~ pattern
139
+ end
140
+ end
141
+
142
+ def fakeweb?(http, request)
143
+ return false unless defined?(::FakeWeb)
144
+ uri = ::FakeWeb::Utility.request_uri_as_string(http, request)
145
+ method = request.method.downcase.to_sym
146
+ ::FakeWeb.registered_uri?(method, uri)
147
+ end
148
+
149
+ def truncate_body(body)
150
+ if collapse_body_limit && collapse_body_limit > 0 && body && body.size >= collapse_body_limit
151
+ body_piece_size = collapse_body_limit / 2
152
+ body[0..body_piece_size] +
153
+ "\n\n<some data truncated>\n\n" +
154
+ body[(body.size - body_piece_size)..body.size]
155
+ else
156
+ body
157
+ end
158
+ end
159
+
160
+ def log(message, dump)
161
+ self.logger.send(self.class.level, format_log_entry(message, dump)) if Rails.env.to_sym == :development
162
+ end
163
+
164
+ def format_log_entry(message, dump = nil)
165
+ if self.class.colorize
166
+ message_color, dump_color = "4;32;1", "0;1"
167
+ log_entry = " \e[#{message_color}m#{message}\e[0m "
168
+ log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
169
+ log_entry
170
+ else
171
+ "%s %s" % [message, dump]
172
+ end
173
+ end
174
+
175
+ def logger
176
+ self.class.logger
177
+ end
178
+
179
+ def collapse_body_limit
180
+ self.class.collapse_body_limit
181
+ end
182
+ end
183
+
184
+ class Net::HTTP
185
+
186
+ def self.log_headers=(value)
187
+ HttpLogger.deprecate_config("log_headers")
188
+ HttpLogger.log_headers = value
189
+ end
190
+
191
+ def self.colorize=(value)
192
+ HttpLogger.deprecate_config("colorize")
193
+ HttpLogger.colorize = value
194
+ end
195
+
196
+ def self.logger=(value)
197
+ HttpLogger.deprecate_config("logger")
198
+ HttpLogger.logger = value
199
+ end
200
+
201
+
202
+ alias_method :request_without_logging, :request
203
+
204
+ def request(request, body = nil, &block)
205
+ HttpLogger.perform(self, request, body) do
206
+ request_without_logging(request, body, &block)
207
+ end
208
+ end
209
+ end
210
+
211
+ if defined?(Rails)
212
+ if defined?(ActiveSupport) && ActiveSupport.respond_to?(:on_load)
213
+ # Rails3
214
+ ActiveSupport.on_load(:after_initialize) do
215
+ HttpLogger.logger = Rails.logger unless HttpLogger.logger
216
+ end
217
+ end
218
+ end
@@ -6,38 +6,37 @@ module Middleware
6
6
 
7
7
  # This method is triggered when a non error page is loaded (not 404)
8
8
  def call(name, started, finished, unique_id, payload)
9
-
10
9
  if ZuoraConnect.configuration.enable_inbound_metrics_flag == true
11
-
12
10
  # If the url contains any css or JavaScript files then do not collect metrics for them
13
- block_words = ["css", "assets", "jpg", "png", "jpeg", "ico"]
14
- if block_words.any? { |word| payload[:path].include?(word) }
15
- return nil
16
- end
11
+ return nil if ["css", "assets", "jpg", "png", "jpeg", "ico"].any? { |word| payload[:path].include?(word) }
17
12
 
18
13
  # Getting the endpoint and the content_type
19
14
  content_hash = {:html => "text/html", :js => "application/javascript", :json => "application/json"}
20
- content_hash.key?(payload[:format]) ? content_type = content_hash[payload[:format]] : content_type = payload[:format]
21
- request_path = "#{payload[:controller]}##{payload[:action]}"
22
- response_time = finished-started
15
+ content_type = content_hash.key?(payload[:format]) ? content_hash[payload[:format]] : payload[:format]
23
16
 
24
17
  # payloads with 500 requests do not have status as it is not set by the controller
25
18
  # https://github.com/rails/rails/issues/33335
26
- status_code = payload[:status] ? payload[:status] : payload[:exception_object].present? ? 500 : ""
19
+ #status_code = payload[:status] ? payload[:status] : payload[:exception_object].present? ? 500 : ""
20
+ if payload[:exception].present?
21
+ status_code, exception = [500, payload[:exception].first]
22
+ else
23
+ status_code, exception = [payload[:status], nil]
24
+ end
27
25
 
28
- # Write to telegraf
29
- ZuoraConnect::AppInstanceBase.write_to_telegraf("endpoint_name": request_path, "method_name": payload[:method], "status_code": status_code, "response_time": response_time, "db_runtime": payload[:db_runtime].to_f, "view_runtime": payload[:view_runtime], "content_type": content_type, "direction": "inbound")
26
+ tags = {method: payload[:method], status: status_code, error_type: exception, content_type: content_type, controller: payload[:controller], action: payload[:action]}.compact
30
27
 
28
+ values = {view_time: payload[:view_runtime], db_time: payload[:db_runtime], response_time: ((finished-started)*1000)}.compact
29
+ values = values.map{ |k,v| [k,v.round(2)]}.to_h
30
+
31
+ ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: :inbound, tags: tags, values: values)
31
32
  end
32
33
  end
33
34
  end
34
35
 
35
-
36
36
  class MetricsMiddleware
37
37
 
38
38
  require "zuora_connect/version"
39
39
  require "zuora_api/version"
40
- require "telegraf"
41
40
 
42
41
  def initialize(app)
43
42
  @app = app
@@ -46,15 +45,10 @@ module Middleware
46
45
  def call(env)
47
46
  start_time = Time.now
48
47
  @status, @headers, @response = @app.call(env)
49
- end_time = Time.now
48
+
50
49
  if ZuoraConnect.configuration.enable_inbound_metrics_flag == true
51
50
  # If the url contains any CSS or JavaScript files then do not collect metrics for them
52
- block_words = ["css", "assets", "jpg", "png", "jpeg", "ico"]
53
- if block_words.any? { |word| env['PATH_INFO'].include?(word) }
54
- return [@status, @headers, @response]
55
- end
56
-
57
- response_time = end_time - start_time
51
+ return [@status, @headers, @response] if ["css", "assets", "jpg", "png", "jpeg", "ico"].any? { |word| env['PATH_INFO'].include?(word) }
58
52
 
59
53
  if defined? Prometheus
60
54
  #Prometheus Stuff
@@ -86,28 +80,30 @@ module Middleware
86
80
 
87
81
  end
88
82
  end
89
- # Writing to telegraf: Handle 404 and 500 requests
90
- if @status == 404 || @status == 304
91
- # Getting the endpoint and content_type
92
- request_path = @status == 404 ? "ActionController#RoutingError" : env["action_controller.instance"].present? ? "#{env["action_controller.instance"].class}##{env["action_controller.instance"].action_name}" : ""
93
-
94
- # Uncomment following block of code for handling engine requests/requests without controller
95
- # else
96
- # # Handling requests which do not have controllers (engines)
97
- # if env["SCRIPT_NAME"].present?
98
- # controller_path = "#{env['SCRIPT_NAME'][1..-1]}"
99
- # controller_path = controller_path.sub("/", "::")
100
- # request_path = "#{controller_path}#UnknownAction"
101
- # end
102
-
103
- content_type = @headers['Content-Type'].split(';')[0] if @headers['Content-Type']
104
- ZuoraConnect::AppInstanceBase.write_to_telegraf("endpoint_name": request_path, "method_name": env['REQUEST_METHOD'], "status_code": @status, "response_time": response_time, "content_type": content_type, "direction": "inbound") if request_path.present?
83
+
84
+ # Uncomment following block of code for handling engine requests/requests without controller
85
+ # else
86
+ # # Handling requests which do not have controllers (engines)
87
+ if env["SCRIPT_NAME"].present?
88
+ controller_path = "#{env['SCRIPT_NAME'][1..-1]}"
89
+ controller_path = controller_path.sub("/", "::")
90
+ request_path = "#{controller_path}#UnknownAction"
91
+ else
92
+ # Writing to telegraf: Handle 404
93
+ if [404].include?(@status)
94
+ content_type = @headers['Content-Type'].split(';')[0] if @headers['Content-Type']
95
+
96
+ tags = {status: @status, content_type: content_type}
97
+
98
+ tags = tags.merge({controller: 'ActionController', action: 'RoutingError' })
99
+
100
+ values = {response_time: ((Time.now - start_time)*1000).round(2) }
101
+
102
+ ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: :inbound, tags: tags, values: values)
103
+ end
105
104
  end
106
105
  end
107
106
  [@status, @headers, @response]
108
-
109
107
  end
110
-
111
108
  end
112
-
113
109
  end
@@ -1,6 +1,13 @@
1
1
  module ZuoraConnect
2
2
  class Configuration
3
- attr_accessor :oauth_client_id, :oauth_client_secret, :oauth_client_redirect_uri,:use_s3, :default_locale,:dev_mode_appinstance ,:dev_mode_admin, :dev_mode_user, :dev_mode_pass, :default_time_zone,:delayed_job,:url, :private_key, :dev_mode_logins,:dev_mode_mode, :dev_mode_options, :mode, :timeout,:dev_mode_secret_access_key,:dev_mode_access_key_id,:aws_region, :s3_bucket_name, :s3_folder_name, :additional_apartment_models, :telegraf_endpoint, :enable_inbound_metrics_flag, :enable_outbound_metrics_flag, :telegraf_client, :custom_prometheus_update_block, :app_name, :influxdb_series_name_inbound, :influxdb_series_name_outbound
3
+
4
+ attr_accessor :default_locale, :default_time_zone, :url, :mode, :delayed_job,:private_key, :additional_apartment_models
5
+
6
+ attr_accessor :telegraf_endpoint, :telegraf_debug, :enable_inbound_metrics_flag, :enable_outbound_metrics_flag, :custom_prometheus_update_block, :app_name, :influxdb_series_name_inbound, :influxdb_series_name_outbound
7
+
8
+ attr_accessor :oauth_client_id, :oauth_client_secret, :oauth_client_redirect_uri
9
+
10
+ attr_accessor :dev_mode_logins, :dev_mode_options, :dev_mode_mode, :dev_mode_appinstance, :dev_mode_user, :dev_mode_pass, :dev_mode_admin, :dev_mode_secret_access_key,:dev_mode_access_key_id,:aws_region, :s3_bucket_name, :s3_folder_name
4
11
 
5
12
  def initialize
6
13
  @default_locale = :en
@@ -8,19 +15,20 @@ module ZuoraConnect
8
15
  @url = "https://connect.zuora.com"
9
16
  @mode = "Production"
10
17
  @delayed_job = false
11
- @use_s3 = false
12
18
  @private_key = ENV["CONNECT_KEY"]
13
19
  @additional_apartment_models = []
20
+
21
+
22
+ # Setting the app name for telegraf write
14
23
  @telegraf_endpoint = 'udp://telegraf-app-metrics.monitoring.svc.cluster.local:8094'
24
+ @telegraf_debug = false
15
25
  @enable_inbound_metrics_flag = false
16
26
  @enable_outbound_metrics_flag = false
17
- @telegraf_client = Telegraf::Agent.new @telegraf_endpoint
18
-
19
- # Setting the app name for telegraf write
20
- @app_name = ENV['DEIS_APP'].present? ? "#{ENV['DEIS_APP']}" : "#{Rails.application.class.parent_name}"
21
27
  @influxdb_series_name_inbound = "request-inbound"
22
28
  @influxdb_series_name_outbound = "request-outbound"
23
29
 
30
+ @app_name = ENV['DEIS_APP'].present? ? "#{ENV['DEIS_APP']}" : "#{Rails.application.class.parent_name}"
31
+
24
32
  # OAuth Settings
25
33
  @oauth_client_id = ""
26
34
  @oauth_client_secret = ""
@@ -21,7 +21,7 @@ module ZuoraConnect
21
21
  check_instance
22
22
  end
23
23
  end
24
- Rails.logger.info("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
24
+ Rails.logger.debug("[#{@appinstance.blank? ? "N/A" : @appinstance.id}] Authenticate App API Request Completed In - #{(Time.now - start_time).round(2)}s")
25
25
  end
26
26
 
27
27
  def authenticate_connect_app_request
@@ -1,3 +1,3 @@
1
1
  module ZuoraConnect
2
- VERSION = "1.6.05"
2
+ VERSION = "1.6.06"
3
3
  end
data/lib/zuora_connect.rb CHANGED
@@ -7,7 +7,8 @@ require 'zuora_connect/railtie'
7
7
  require 'resque/additions'
8
8
  require 'resque/dynamic_queues'
9
9
  require 'resque/self_lookup'
10
-
10
+ require 'metrics/influx/point_value'
11
+ require 'metrics/net'
11
12
 
12
13
  module ZuoraConnect
13
14
  class << self
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zuora_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.05
4
+ version: 1.6.06
5
5
  platform: ruby
6
6
  authors:
7
7
  - Connect Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-24 00:00:00.000000000 Z
11
+ date: 2018-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: apartment
@@ -36,20 +36,20 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 1.5.0
39
+ version: 1.6.0
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 1.4.0
42
+ version: 1.6.0
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - "~>"
48
48
  - !ruby/object:Gem::Version
49
- version: 1.5.0
49
+ version: 1.6.0
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 1.4.0
52
+ version: 1.6.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: httparty
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -106,20 +106,6 @@ dependencies:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
- - !ruby/object:Gem::Dependency
110
- name: telegraf
111
- requirement: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: 0.4.0
116
- type: :runtime
117
- prerelease: false
118
- version_requirements: !ruby/object:Gem::Requirement
119
- requirements:
120
- - - "~>"
121
- - !ruby/object:Gem::Version
122
- version: 0.4.0
123
109
  - !ruby/object:Gem::Dependency
124
110
  name: railties
125
111
  requirement: !ruby/object:Gem::Requirement
@@ -252,6 +238,7 @@ files:
252
238
  - app/views/zuora_connect/static/session_error.html.erb
253
239
  - config/initializers/apartment.rb
254
240
  - config/initializers/object_method_hooks.rb
241
+ - config/initializers/postgresql_adapter.rb
255
242
  - config/initializers/prometheus.rb
256
243
  - config/initializers/redis.rb
257
244
  - config/initializers/resque.rb
@@ -267,6 +254,8 @@ files:
267
254
  - db/migrate/20110503003603_add_catalog_mappings_to_app_instance.rb
268
255
  - db/migrate/20110503003604_catalog_default.rb
269
256
  - db/migrate/20180301052853_add_catalog_attempted_at.rb
257
+ - lib/metrics/influx/point_value.rb
258
+ - lib/metrics/net.rb
270
259
  - lib/middleware/metrics_middleware.rb
271
260
  - lib/resque/additions.rb
272
261
  - lib/resque/dynamic_queues.rb