zuora_connect 2.1.1 → 3.0.0.pre.e

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,6 @@ module ZuoraConnect
2
2
  class ZuoraUser < ActiveRecord::Base
3
3
  self.table_name = "zuora_users"
4
4
  attr_accessor :session
5
-
5
+ cattr_accessor :current_user_id
6
6
  end
7
7
  end
@@ -1,9 +1,15 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  class PostgreSQLAdapter < AbstractAdapter
4
+
5
+ SCHEMA_ADDITIONAL_TYPES = 'SchemaAdditionalTypes'.freeze
6
+
4
7
  private
5
- def load_additional_types(type_map, oids = nil)
8
+ def load_additional_types_latest(oids = nil)
6
9
  initializer = OID::TypeMapInitializer.new(type_map)
10
+
11
+ return if loaded_from_cache?(initializer)
12
+
7
13
  if supports_ranges?
8
14
  query = <<-SQL
9
15
  SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
@@ -24,9 +30,73 @@ module ActiveRecord
24
30
  end
25
31
 
26
32
  execute_and_clear(query, "SCHEMA", []) do |records|
33
+ cache_additional_types(records)
27
34
  initializer.run(records)
28
35
  end
29
36
  end
37
+
38
+ def load_additional_types_deprecated(type_map, oids = nil)
39
+ initializer = OID::TypeMapInitializer.new(type_map)
40
+
41
+ return if loaded_from_cache?(initializer)
42
+
43
+ if supports_ranges?
44
+ query = <<-SQL
45
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
46
+ FROM pg_type as t
47
+ LEFT JOIN pg_range as r ON oid = rngtypid
48
+ SQL
49
+ else
50
+ query = <<-SQL
51
+ SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
52
+ FROM pg_type as t
53
+ SQL
54
+ end
55
+
56
+ if oids
57
+ query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
58
+ else
59
+ query += initializer.query_conditions_for_initial_load(type_map)
60
+ end
61
+
62
+ execute_and_clear(query, "SCHEMA", []) do |records|
63
+ cache_additional_types(records)
64
+ initializer.run(records)
65
+ end
66
+ end
67
+
68
+ def loaded_from_cache?(initializer)
69
+ if defined?(Redis.current)
70
+ begin
71
+ if Redis.current.exists(SCHEMA_ADDITIONAL_TYPES)
72
+ initializer.run(JSON.parse(Redis.current.get(SCHEMA_ADDITIONAL_TYPES)))
73
+ return true
74
+ end
75
+ rescue => ex
76
+ Rails.logger.warn('Exception occurred while loading additional types', ex)
77
+ end
78
+ end
79
+
80
+ false
81
+ end
82
+
83
+ def cache_additional_types(records)
84
+ if defined?(Redis.current)
85
+ begin
86
+ Redis.current.setex(SCHEMA_ADDITIONAL_TYPES, 1.hour.to_i, records.to_json)
87
+ rescue => ex
88
+ Rails.logger.warn('Exception occurred while caching additional types', ex)
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ rails_version = Rails.version.split('.').map { |x| x.to_i }
95
+ if (rails_version <=> [5, 2, 0]) >= 1
96
+ alias :load_additional_types :load_additional_types_latest
97
+ else
98
+ alias :load_additional_types :load_additional_types_deprecated
99
+ end
30
100
  end
31
101
  end
32
102
  end
@@ -3,38 +3,95 @@ if defined? Prometheus
3
3
  require "zuora_connect/version"
4
4
  require "zuora_api/version"
5
5
 
6
+ resque_path = "#{ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')}/*.prom"
7
+ prometheus_path = Rails.root.join("tmp/prometheus")
8
+
9
+ Dir[resque_path, "#{prometheus_path}/*.bin"].each do |file_path|
10
+ File.unlink(file_path)
11
+ end
12
+
13
+ require 'prometheus/client/data_stores/direct_file_store'
14
+ Prometheus::Client.config.data_store = Prometheus::Client::DataStores::DirectFileStore.new(
15
+ dir: prometheus_path
16
+ )
17
+
18
+ class ResqueExporter
19
+ require 'prometheus/client/formats/text'
20
+ require 'fileutils'
21
+
22
+ def initialize
23
+ @lock = Monitor.new
24
+ @registry = Prometheus::Client.registry
25
+ @path = ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')
26
+ FileUtils.mkdir_p(@path)
27
+ end
28
+
29
+ def export
30
+ filename = File.join(@path, 'resque_export.prom')
31
+ @lock.synchronize do
32
+ File.open(filename, 'w+') do |file|
33
+ file.write(Prometheus::Client::Formats::Text.marshal(@registry))
34
+ end
35
+ end
36
+ rescue
37
+ # Ignored
38
+ end
39
+ end
40
+
41
+ most_recent_aggregation = {}
42
+ sum_aggregation = {}
43
+ if defined?(Unicorn)
44
+ most_recent_aggregation[:aggregation] = :most_recent
45
+ sum_aggregation[:aggregation] = :sum
46
+ end
47
+
6
48
  # Create a default Prometheus registry for our metrics.
7
49
  prometheus = Prometheus::Client.registry
8
50
 
9
51
  # Create your metrics.
10
- ZUORA_VERSION = Prometheus::Client::Gauge.new(:zuora_version, 'The current Zuora Gem version.')
11
- CONNECT_VERSION = Prometheus::Client::Gauge.new(:gem_version, 'The current Connect Gem version.')
12
- RAILS_VERSION = Prometheus::Client::Gauge.new(:rails_version, 'The current Rails version.')
13
- RUBY_V = Prometheus::Client::Gauge.new(:ruby_version, 'The current Ruby version.')
52
+ ZUORA_VERSION = prometheus.gauge(:zuora_version, docstring: 'The current Zuora Gem version.', labels: %i(version name), preset_labels: { version: ZuoraAPI::VERSION, name: ZuoraObservability::Env.app_name }, store_settings: most_recent_aggregation)
53
+ CONNECT_VERSION = prometheus.gauge(:gem_version, docstring: 'The current Connect Gem version.', labels: %i(version name), preset_labels: { version: ZuoraConnect::VERSION, name: ZuoraObservability::Env.app_name }, store_settings: most_recent_aggregation)
54
+ RAILS_VERSION = prometheus.gauge(:rails_version, docstring: 'The current Rails version.', labels: %i(version name), preset_labels: { version: Rails.version, name: ZuoraObservability::Env.app_name }, store_settings: most_recent_aggregation)
55
+ RUBY_V = prometheus.gauge(:ruby_version, docstring: 'The current Ruby version.', labels: %i(version name), preset_labels: { version: RUBY_VERSION, name: ZuoraObservability::Env.app_name }, store_settings: most_recent_aggregation)
14
56
 
15
- # Register your metrics with the registry we previously created.
16
- prometheus.register(ZUORA_VERSION);ZUORA_VERSION.set({version: ZuoraAPI::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
17
- prometheus.register(CONNECT_VERSION);CONNECT_VERSION.set({version: ZuoraConnect::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
18
- prometheus.register(RAILS_VERSION);RAILS_VERSION.set({version: Rails.version, name: ZuoraConnect::Telegraf.app_name},0)
19
- prometheus.register(RUBY_V);RUBY_V.set({version: RUBY_VERSION, name: ZuoraConnect::Telegraf.app_name},0)
57
+ ZUORA_VERSION.set(0)
58
+ CONNECT_VERSION.set(0)
59
+ RAILS_VERSION.set(0)
60
+ RUBY_V.set(0)
20
61
 
21
62
  # Do they have resque jobs?
22
63
  if defined? Resque.redis
23
- REDIS_CONNECTION = Prometheus::Client::Gauge.new(:redis_connection, 'The status of the redis connection, 0 or 1')
24
- FINISHED_JOBS = Prometheus::Client::Gauge.new(:finished_jobs, 'Done resque jobs')
25
- WORKERS = Prometheus::Client::Gauge.new(:workers, 'Total resque workers')
26
- ACTIVE_WORKERS = Prometheus::Client::Gauge.new(:active_workers, 'Active resque workers')
27
- FAILED_JOBS = Prometheus::Client::Gauge.new(:failed_jobs, 'Failed resque jobs')
28
- PENDING_JOBS = Prometheus::Client::Gauge.new(:pending_jobs, 'Pending resque jobs')
29
-
30
- prometheus.register(REDIS_CONNECTION)
31
- prometheus.register(FINISHED_JOBS)
32
- prometheus.register(ACTIVE_WORKERS)
33
- prometheus.register(WORKERS)
34
- prometheus.register(FAILED_JOBS)
35
- prometheus.register(PENDING_JOBS)
36
-
64
+ REDIS_CONNECTION = prometheus.gauge(:redis_connection, docstring: 'The status of the redis connection, 0 or 1', labels: %i(connection name), preset_labels: {connection:'redis', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
65
+ JOBS_FINISHED = prometheus.gauge(:jobs_finished, docstring: 'Done resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
66
+ WORKERS_TOTAL = prometheus.gauge(:workers_total, docstring: 'Total resque workers', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
67
+ WORKERS_ACTIVE = prometheus.gauge(:workers_active, docstring: 'Active resque workers', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
68
+ JOBS_FAILED = prometheus.gauge(:jobs_failed, docstring: 'Failed resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
69
+ JOBS_PENDING = prometheus.gauge(:jobs_pending, docstring: 'Pending resque jobs', labels: %i(type name), preset_labels: {type:'resque', name: ZuoraObservability::Env.app_name}, store_settings: most_recent_aggregation)
37
70
  end
38
71
 
72
+ if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
73
+ UNICORN_KILLS = prometheus.gauge(
74
+ :unicorn_kills,
75
+ docstring: 'Unicorn Kills',
76
+ labels: %i(type name),
77
+ preset_labels: {type:'Unicorn-Killer', name: ZuoraObservability::Env.app_name},
78
+ store_settings: sum_aggregation
79
+ )
80
+
81
+ ZuoraObservability::Metrics.unicorn_listener.each do |key, _|
82
+ gauge_name = "unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_')
83
+ gauge = prometheus.gauge(
84
+ gauge_name.to_sym,
85
+ docstring: 'Unicorn Stats',
86
+ labels: %i(type name),
87
+ preset_labels: { type: 'unicorn', name: ZuoraObservability::Env.app_name },
88
+ store_settings: most_recent_aggregation
89
+ )
90
+ Prometheus.const_set(
91
+ gauge_name.upcase,
92
+ gauge
93
+ )
94
+ end
95
+ end
39
96
  end
40
97
  end
@@ -12,21 +12,21 @@ class RedisFlash
12
12
  end
13
13
 
14
14
  if defined?(Redis.current)
15
- Redis.current = Redis.new(:id => "#{ZuoraConnect::Telegraf.full_process_name(process_name: 'Redis')}", :url => redis_url, :timeout => 6, :reconnect_attempts => 2)
15
+ Redis.current = Redis.new(:id => "#{ZuoraObservability::Env.full_process_name(process_name: 'Redis')}", :url => redis_url, :timeout => 6, :reconnect_attempts => 2)
16
16
  browser_urls['Redis'] = { "url" => redis_url }
17
17
  if defined?(Resque.redis)
18
18
  if resque_url != redis_url
19
- Resque.redis = Redis.new(:id => "#{ZuoraConnect::Telegraf.full_process_name(process_name: 'Resque')}", :url => resque_url, :timeout => 6, :reconnect_attempts => 2)
19
+ Resque.redis = Redis.new(:id => "#{ZuoraObservability::Env.full_process_name(process_name: 'Resque')}", :url => resque_url, :timeout => 6, :reconnect_attempts => 2)
20
20
  browser_urls['Resque'] = { "url" => resque_url }
21
21
  else
22
22
  Resque.redis = Redis.current
23
23
  end
24
24
  end
25
25
  if defined?(flash_url.present?)
26
- RedisFlash.current = Redis.new(:id => "#{ZuoraConnect::Telegraf.full_process_name(process_name: 'Flash')}", :url => flash_url, :timeout => 6, :reconnect_attempts => 2)
26
+ RedisFlash.current = Redis.new(:id => "#{ZuoraObservability::Env.full_process_name(process_name: 'Flash')}", :url => flash_url, :timeout => 6, :reconnect_attempts => 2)
27
27
  browser_urls['Flash'] = { "url" => flash_url }
28
28
  end
29
29
  end
30
30
  if defined?(RedisBrowser)
31
31
  RedisBrowser.configure("connections" => browser_urls)
32
- end
32
+ end
@@ -5,6 +5,20 @@ if defined?(Resque::Worker)
5
5
  Resque::Job.send(:include, Resque::SelfLookup)
6
6
  end
7
7
 
8
+ if defined?(Resque::Job) && defined?(Prometheus)
9
+ module ResquePrometheusExtensions
10
+ EXPORTER = Prometheus::ResqueExporter.new
11
+ def perform
12
+ super
13
+ EXPORTER.export
14
+ end
15
+ end
16
+
17
+ class Resque::Job
18
+ prepend ResquePrometheusExtensions
19
+ end
20
+ end
21
+
8
22
  Resque.module_eval do
9
23
  # Returns a hash, mapping queue names to queue sizes
10
24
  def queue_sizes
@@ -20,15 +34,3 @@ Resque.module_eval do
20
34
  Hash[queue_names.zip(sizes)]
21
35
  end
22
36
  end
23
-
24
- if defined?(Resque.logger)
25
- Resque.logger = ZuoraConnect.custom_logger(name: "Resque", type: 'Monologger', level: MonoLogger::INFO)
26
- Resque::Scheduler.logger = ZuoraConnect.custom_logger(name: "ResqueScheduler") if defined?(Resque::Scheduler)
27
- end
28
- if defined?(Delayed::Worker.logger)
29
- Delayed::Worker.logger = ZuoraConnect.custom_logger(name: "DelayedJob", type: 'Monologger', level: MonoLogger::INFO)
30
- end
31
-
32
- Makara::Logging::Logger.logger = ZuoraConnect.custom_logger(name: "Makara") if defined?(Makara)
33
- ElasticAPM.agent.config.logger = ZuoraConnect.custom_logger(name: "ElasticAPM", level: MonoLogger::WARN) if defined?(ElasticAPM) && ElasticAPM.running?
34
- ActionMailer::Base.logger = ZuoraConnect.custom_logger(name: "ActionMailer", type: 'Monologger') if defined?(ActionMailer)
@@ -3,7 +3,35 @@ if defined?(Unicorn::WorkerKiller)
3
3
  self.singleton_class.send(:alias_method, :kill_self_old, :kill_self)
4
4
  def self.kill_self(logger, start_time)
5
5
  self.kill_self_old(logger, start_time)
6
- ZuoraConnect::AppInstance.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
6
+ if defined?(Prometheus)
7
+ Prometheus::UNICORN_KILLS.set(1)
8
+ else
9
+ ZuoraObservability::Metrics.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
10
+ end
7
11
  end
8
12
  end
9
- end
13
+ end
14
+
15
+ if defined?(Unicorn::HttpServer) && defined?(Prometheus)
16
+ module HttpServerExtensions
17
+ def kill_worker(signal, wpid)
18
+ Prometheus::UNICORN_KILLS.increment
19
+ super
20
+ end
21
+ end
22
+
23
+ module WorkerExtensions
24
+ def soft_kill(sig)
25
+ Prometheus::UNICORN_KILLS.increment
26
+ super
27
+ end
28
+ end
29
+
30
+ class Unicorn::HttpServer
31
+ prepend HttpServerExtensions
32
+ end
33
+
34
+ class Unicorn::Worker
35
+ prepend WorkerExtensions
36
+ end
37
+ end
@@ -1,8 +1,12 @@
1
1
  ZuoraConnect::Engine.routes.draw do
2
2
  get '/health' => 'static#health'
3
- get '/internal/data' => 'static#metrics'
4
3
  post '/initialize_app' => 'static#initialize_app'
5
4
 
5
+ if ENV['PROVISION_USER'].present? && ENV['PROVISION_SECRET'].present?
6
+ post '/provision' => 'static#provision'
7
+ get '/instance/:id/user' => 'static#instance_user'
8
+ end
9
+
6
10
  namespace :api do
7
11
  namespace :v1 do
8
12
  resources :app_instance, :only => [:index], defaults: {format: :json} do
@@ -68,12 +68,12 @@ class HttpLogger
68
68
  log_request_body(request)
69
69
  log_request_headers(request)
70
70
  if defined?(response) && response
71
- tags = tags.merge({status: response.code.to_i})
71
+ tags = tags.merge({status: response.code.to_i})
72
72
  log_response_code(response)
73
73
  log_response_headers(response)
74
74
  log_response_body(response.body)
75
75
  end
76
- ZuoraConnect::AppInstance.write_to_telegraf(direction: :outbound, tags: tags, values: values)
76
+ ZuoraObservability::Metrics.write_to_telegraf(direction: :outbound, tags: tags, values: values)
77
77
  end
78
78
  end
79
79
 
@@ -95,7 +95,7 @@ class HttpLogger
95
95
  end
96
96
 
97
97
  HTTP_METHODS_WITH_BODY = Set.new(%w(POST PUT GET PATCH))
98
-
98
+
99
99
  def log_request_body(request)
100
100
  if self.class.log_request_body
101
101
  if HTTP_METHODS_WITH_BODY.include?(request.method)
@@ -149,8 +149,8 @@ class HttpLogger
149
149
  def truncate_body(body)
150
150
  if collapse_body_limit && collapse_body_limit > 0 && body && body.size >= collapse_body_limit
151
151
  body_piece_size = collapse_body_limit / 2
152
- body[0..body_piece_size] +
153
- "\n\n<some data truncated>\n\n" +
152
+ body[0..body_piece_size] +
153
+ "\n\n<some data truncated>\n\n" +
154
154
  body[(body.size - body_piece_size)..body.size]
155
155
  else
156
156
  body
@@ -203,7 +203,7 @@ class Net::HTTP
203
203
 
204
204
  def request(request, body = nil, &block)
205
205
  HttpLogger.perform(self, request, body) do
206
- request_without_logging(request, body, &block)
206
+ request_without_logging(request, body, &block)
207
207
  end
208
208
  end
209
209
  end
@@ -215,4 +215,4 @@ if defined?(Rails)
215
215
  HttpLogger.logger = ZuoraConnect.logger unless HttpLogger.logger
216
216
  end
217
217
  end
218
- end
218
+ end
@@ -7,7 +7,7 @@ module ZuoraConnect
7
7
  def call(env)
8
8
  begin
9
9
  @app.call(env)
10
- rescue ActionDispatch::ParamsParser::ParseError => error
10
+ rescue DynamicRailsError => error
11
11
  if env['HTTP_ACCEPT'] =~ /application\/json/ || env['CONTENT_TYPE'] =~ /application\/json/
12
12
  return [
13
13
  400, { "Content-Type" => "application/json" },
@@ -18,5 +18,16 @@ module ZuoraConnect
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ # Note(hartley): remove once the minimum supported version of Rails is 5.2
23
+ class DynamicRailsError < StandardError
24
+ def self.===(exception)
25
+ if Rails.version >= "5.2"
26
+ exception.is_a?(ActionDispatch::Http::Parameters::ParseError)
27
+ else
28
+ exception.is_a?(ActionDispatch::ParamsParser::ParseError)
29
+ end
30
+ end
31
+ end
21
32
  end
22
- end
33
+ end
@@ -1,37 +1,6 @@
1
1
  module ZuoraConnect
2
2
  require 'uri'
3
3
 
4
- # Object of this class is passed to the ActiveSupport::Notification hook
5
- class PageRequest
6
-
7
- # This method is triggered when a non error page is loaded (not 404)
8
- def call(name, started, finished, unique_id, payload)
9
- # If the url contains any css or JavaScript files then do not collect metrics for them
10
- return nil if ["css", "assets", "jpg", "png", "jpeg", "ico"].any? { |word| payload[:path].include?(word) }
11
-
12
- # Getting the endpoint and the content_type
13
- content_hash = {:html => "text/html", :js => "application/javascript", :json => "application/json", :csv => "text/csv"}
14
- content_type = content_hash.key?(payload[:format]) ? content_hash[payload[:format]] : payload[:format]
15
- content_type = content_type.to_s.gsub('text/javascript', 'application/javascript')
16
-
17
- # payloads with 500 requests do not have status as it is not set by the controller
18
- # https://github.com/rails/rails/issues/33335
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
25
-
26
- tags = {method: payload[:method], status: status_code, error_type: exception, content_type: content_type, controller: payload[:controller], action: payload[:action]}.compact
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)
32
- end
33
- end
34
-
35
4
  class MetricsMiddleware
36
5
 
37
6
  require "zuora_connect/version"
@@ -42,7 +11,7 @@ module ZuoraConnect
42
11
  end
43
12
 
44
13
  def call(env)
45
- @bad_headers = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST", "HTTP_X_FORWARDED_PORT", "HTTP_X_FORWARDED_PROTO", "HTTP_X_FORWARDED_SCHEME", "HTTP_X_FORWARDED_SSL"]
14
+ @bad_headers = ["HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_HOST", "HTTP_X_FORWARDED_PORT", "HTTP_X_FORWARDED_PROTO", "HTTP_X_FORWARDED_SCHEME", "HTTP_X_FORWARDED_SSL"]
46
15
  if !ActionDispatch::Request::HTTP_METHODS.include?(env["REQUEST_METHOD"].upcase)
47
16
  [405, {"Content-Type" => "text/plain"}, ["Method Not Allowed"]]
48
17
  else
@@ -64,47 +33,27 @@ module ZuoraConnect
64
33
  #Remove bad headers
65
34
  @bad_headers.each { |header| env.delete(header) }
66
35
 
67
- #Thread.current[:appinstance] = nil
68
- start_time = Time.now
69
- begin
70
- @status, @headers, @response = @app.call(env)
71
- ensure
72
-
73
- # If the url contains any CSS or JavaScript files then do not collect metrics for them
74
- if ["css", "assets", "jpg", "png", "jpeg", "ico"].any? { |word| env['PATH_INFO'].include?(word) } || /.*\.js$/.match(env['PATH_INFO'])
75
- tags = {status: @status, controller: 'ActionController', action: 'Assets', app_instance: 0}
76
- values = {response_time: ((Time.now - start_time)*1000).round(2) }
77
- ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: 'request-inbound-assets', tags: tags, values: values)
78
- end
79
-
80
- if defined? Prometheus
81
- #Prometheus Stuff
82
- if env['PATH_INFO'] == '/connect/internal/metrics'
83
-
84
- #Do something before each scrape
85
- if defined? Resque.redis
86
- begin
87
-
88
- Resque.redis.ping
89
-
90
- Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},1)
91
- Prometheus::FINISHED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:processed])
92
- Prometheus::PENDING_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:pending])
93
- Prometheus::ACTIVE_WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:working])
94
- Prometheus::WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:workers])
95
- Prometheus::FAILED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:failed])
36
+ if defined?(Prometheus) && env['PATH_INFO'] == '/connect/internal/metrics'
37
+ # Prometheus Stuff
38
+ metrics = ZuoraObservability::Metrics.resque
39
+ redis_up = metrics.present? && metrics.dig(:Resque, :Workers_Total).present? ? 1 : 0
40
+ Prometheus::REDIS_CONNECTION.set(redis_up)
96
41
 
97
- rescue Redis::CannotConnectError
98
- Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},0)
99
- end
100
-
101
- if ZuoraConnect.configuration.custom_prometheus_update_block != nil
102
- ZuoraConnect.configuration.custom_prometheus_update_block.call()
103
- end
104
- end
42
+ process_prometheus_metric(metrics: metrics)
105
43
 
44
+ if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
45
+ ZuoraObservability::Metrics.unicorn_listener.each do |key, value|
46
+ gauge = Prometheus.const_get("unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_').upcase)
47
+ gauge.set(value) if gauge.present?
106
48
  end
107
49
  end
50
+ end
51
+
52
+ #Thread.current[:appinstance] = nil
53
+ start_time = Time.now
54
+ begin
55
+ @status, @headers, @response = @app.call(env)
56
+ ensure
108
57
 
109
58
  # Uncomment following block of code for handling engine requests/requests without controller
110
59
  # else
@@ -119,13 +68,13 @@ module ZuoraConnect
119
68
  content_type = @headers['Content-Type'].split(';')[0] if @headers['Content-Type']
120
69
  content_type = content_type.gsub('text/javascript', 'application/javascript')
121
70
  tags = {status: @status, content_type: content_type}
122
-
71
+
123
72
  tags = tags.merge({controller: 'ActionController'})
124
73
  tags = tags.merge({action: 'RoutingError' }) if @status == 404
125
-
74
+
126
75
  values = {response_time: ((Time.now - start_time)*1000).round(2) }
127
76
 
128
- ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: :inbound, tags: tags, values: values)
77
+ ZuoraObservability::Metrics.write_to_telegraf(direction: :inbound, tags: tags, values: values)
129
78
  end
130
79
  end
131
80
  Thread.current[:inbound_metric] = nil
@@ -133,5 +82,32 @@ module ZuoraConnect
133
82
  [@status, @headers, @response]
134
83
  end
135
84
  end
85
+
86
+ def process_prometheus_metric(type: 'none', metrics: {})
87
+ return if metrics.blank?
88
+
89
+ prometheus = Prometheus::Client.registry
90
+ most_recent_aggregation = {}
91
+ if Prometheus::Client.config.data_store.is_a?(Prometheus::Client::DataStores::DirectFileStore)
92
+ most_recent_aggregation[:aggregation] = :most_recent
93
+ end
94
+ metrics.each do |key, value|
95
+ next if %w[app_name url].include?(key.to_s)
96
+
97
+ if value.is_a?(Hash)
98
+ process_prometheus_metric(type: key.to_s, metrics: value)
99
+ else
100
+ gauge_name = key.to_s.downcase.gsub(/[^a-z0-9_]/, '_')
101
+ gauge = prometheus.get(gauge_name.to_sym) || prometheus.gauge(
102
+ gauge_name.to_sym,
103
+ docstring: "#{key} metric",
104
+ labels: %i(type name),
105
+ preset_labels: { type: type, name: ZuoraObservability::Env.app_name },
106
+ store_settings: most_recent_aggregation
107
+ )
108
+ gauge.set(value)
109
+ end
110
+ end
111
+ end
136
112
  end
137
113
  end