zuora_connect 1.6.05 → 1.6.06

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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