zuora_connect 2.0.60t → 3.0.0.pre.a
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/zuora_connect/static_controller.rb +3 -7
- data/app/models/zuora_connect/app_instance_base.rb +80 -132
- data/config/initializers/prometheus.rb +13 -13
- data/config/initializers/redis.rb +4 -4
- data/config/initializers/resque.rb +6 -6
- data/config/initializers/unicorn.rb +2 -2
- data/config/routes.rb +0 -1
- data/lib/metrics/net.rb +7 -7
- data/lib/middleware/metrics_middleware.rb +10 -10
- data/lib/zuora_connect.rb +3 -63
- data/lib/zuora_connect/controllers/helpers.rb +2 -6
- data/lib/zuora_connect/engine.rb +2 -1
- data/lib/zuora_connect/railtie.rb +0 -63
- data/lib/zuora_connect/version.rb +1 -1
- metadata +16 -5
- data/app/models/zuora_connect/telegraf.rb +0 -97
- data/lib/logging/connect_formatter.rb +0 -44
- data/lib/metrics/influx/point_value.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e63c10c8405375ad7cb2c28073c6181ed055266fb8d61e3ac5725e8f5b8ca8d5
|
4
|
+
data.tar.gz: c5124fe3590fd14c0acdad0cfe6e567997195eaa728245f620bfff5bbda285fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1beb3e3c0531b3035051711670de269814122c20269086ffd31257b02dc4e6ff8c515ac812abc436360ebc9f1506e3ae8e15e859d6098913e08f2dfed67e1284
|
7
|
+
data.tar.gz: bff9fca90e302be4fe97b3cac4ac54bb8dc6c841ad6762939f9b0b2c6c7e66417bb108105d6d8372965ae9090d813c97cff8a4a4a6b513665beed63c9229f0e4
|
@@ -1,16 +1,12 @@
|
|
1
1
|
module ZuoraConnect
|
2
2
|
class StaticController < ApplicationController
|
3
|
-
before_action :authenticate_connect_app_request, :except => [:
|
4
|
-
before_action :clear_connect_app_session, :only => [:
|
5
|
-
after_action :persist_connect_app_session, :except => [:
|
3
|
+
before_action :authenticate_connect_app_request, :except => [:health, :initialize_app, :provision, :instance_user]
|
4
|
+
before_action :clear_connect_app_session, :only => [:health, :initialize_app, :provision, :instance_user]
|
5
|
+
after_action :persist_connect_app_session, :except => [:health, :initialize_app, :provision, :instance_user]
|
6
6
|
|
7
7
|
skip_before_action :verify_authenticity_token, :only => [:initialize_app, :provision]
|
8
8
|
http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user]
|
9
9
|
|
10
|
-
def metrics
|
11
|
-
type = params[:type].present? ? params[:type] : "versions"
|
12
|
-
render json: ZuoraConnect::AppInstance.get_metrics(type).to_json, status: 200
|
13
|
-
end
|
14
10
|
|
15
11
|
def health
|
16
12
|
if params[:error].present?
|
@@ -12,7 +12,6 @@ module ZuoraConnect
|
|
12
12
|
|
13
13
|
self.table_name = "zuora_connect_app_instances"
|
14
14
|
attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message, :new_session_message, :connect_user, :logitems, :user_timezone
|
15
|
-
@@telegraf_host = nil
|
16
15
|
REFRESH_TIMEOUT = 2.minute #Used to determine how long to wait on current refresh call before executing another
|
17
16
|
INSTANCE_REFRESH_WINDOW = 1.hours #Used to set how how long till app starts attempting to refresh cached task connect data
|
18
17
|
INSTANCE_REDIS_CACHE_PERIOD = 24.hours #Used to determine how long to cached task data will live for
|
@@ -25,6 +24,8 @@ module ZuoraConnect
|
|
25
24
|
CATALOG_LOOKUP_CACHE_TIME_KEY = 'CatalogCachedAt'
|
26
25
|
CATALOG_LOOKUP_TTL = 60.seconds
|
27
26
|
CATALOG_LOOKUP_CACHE_RESULT_KEY = 'CatalogCache'
|
27
|
+
TIMEZONE_LOG_RATE_LIMIT_KEY = 'TimezoneLoggedAt'
|
28
|
+
TIMEZONE_LOG_PERIOD = 4.hours
|
28
29
|
IGNORED_LOCALS = ['fr', 'ja', 'es', 'zh', 'de']
|
29
30
|
INTERNAL_HOSTS = []
|
30
31
|
LOGIN_TENANT_DESTINATION = 'target_login'
|
@@ -33,7 +34,7 @@ module ZuoraConnect
|
|
33
34
|
Aws::Errors::MissingCredentialsError,
|
34
35
|
Aws::S3::Errors::AccessDenied,
|
35
36
|
Aws::SES::Errors::AccessDenied,
|
36
|
-
Aws::KMS::Errors::AccessDeniedException
|
37
|
+
Aws::KMS::Errors::AccessDeniedException
|
37
38
|
].freeze
|
38
39
|
AWS_AUTH_ERRORS_MSG = "AWS Auth Errors".freeze
|
39
40
|
|
@@ -245,48 +246,7 @@ module ZuoraConnect
|
|
245
246
|
ZuoraConnect.logger.error(ex) if !IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
246
247
|
end
|
247
248
|
|
248
|
-
|
249
|
-
sql = <<-eos
|
250
|
-
SELECT zuora_users.zuora_identity_response
|
251
|
-
FROM "#{self.id}".zuora_users
|
252
|
-
ORDER BY zuora_users.updated_at DESC
|
253
|
-
LIMIT 1;
|
254
|
-
eos
|
255
|
-
user = ActiveRecord::Base.connection.execute(sql).to_a.first
|
256
|
-
|
257
|
-
if user.present?
|
258
|
-
zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}'))
|
259
|
-
self.user_timezone = zuora_identity_response.values.first&.dig('timeZone')
|
260
|
-
end
|
261
|
-
rescue => ex
|
262
|
-
Rails.logger.error('Failed to get users while setting app instance timezone', ex)
|
263
|
-
end
|
264
|
-
|
265
|
-
if self.user_timezone.present?
|
266
|
-
# connect instance which has a custom timezone
|
267
|
-
if !self.auto_deployed? && (
|
268
|
-
ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset !=
|
269
|
-
ActiveSupport::TimeZone[self.user_timezone]&.utc_offset
|
270
|
-
)
|
271
|
-
if self.environment == 'Production'
|
272
|
-
ZuoraConnect.logger.error(
|
273
|
-
"Instance and user timezones are different. User has '#{self.user_timezone}' and " \
|
274
|
-
"instance has '#{self.task_data.dig('user_settings', 'timezone')}'",
|
275
|
-
app_instance_id: self.id
|
276
|
-
)
|
277
|
-
end
|
278
|
-
self.user_timezone = nil
|
279
|
-
Time.zone = self.timezone
|
280
|
-
else
|
281
|
-
begin
|
282
|
-
Time.zone = self.user_timezone
|
283
|
-
rescue ArgumentError
|
284
|
-
Time.zone = self.timezone
|
285
|
-
end
|
286
|
-
end
|
287
|
-
else
|
288
|
-
Time.zone = self.timezone
|
289
|
-
end
|
249
|
+
self.set_timezone
|
290
250
|
|
291
251
|
if self.task_data.present?
|
292
252
|
tenants = self.task_data.fetch('tenant_ids', [])
|
@@ -302,7 +262,7 @@ module ZuoraConnect
|
|
302
262
|
end
|
303
263
|
|
304
264
|
params = {
|
305
|
-
name: self.task_data.dig('name'),
|
265
|
+
name: self.task_data.dig('name'),
|
306
266
|
zuora_entity_ids: (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).map{|e| e['id']}.uniq,
|
307
267
|
zuora_tenant_ids: tenants.map(&:to_s).uniq,
|
308
268
|
organizations: organizations
|
@@ -311,7 +271,7 @@ module ZuoraConnect
|
|
311
271
|
client = self.send(LOGIN_TENANT_DESTINATION).client
|
312
272
|
if defined?(client.rest_domain)
|
313
273
|
ZuoraConnect::RequestIdMiddleware.zuora_rest_domain = client.rest_domain
|
314
|
-
params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
|
274
|
+
params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
|
315
275
|
end
|
316
276
|
end
|
317
277
|
params = params.reject{|k,v| !self.attributes.keys.member?(k.to_s) || self[k] == v}
|
@@ -319,16 +279,80 @@ module ZuoraConnect
|
|
319
279
|
end
|
320
280
|
end
|
321
281
|
|
282
|
+
def set_timezone(timezone: self.timezone, type: :default)
|
283
|
+
if timezone.blank?
|
284
|
+
timezone = self.timezone
|
285
|
+
end
|
286
|
+
|
287
|
+
if type == :default
|
288
|
+
Time.zone = timezone
|
289
|
+
elsif type == :user
|
290
|
+
begin
|
291
|
+
sql = <<-eos
|
292
|
+
SELECT zuora_users.zuora_identity_response
|
293
|
+
FROM "#{self.id}".zuora_users
|
294
|
+
ORDER BY zuora_users.updated_at DESC
|
295
|
+
LIMIT 1;
|
296
|
+
eos
|
297
|
+
user = ActiveRecord::Base.connection.execute(sql).to_a.first
|
298
|
+
|
299
|
+
if user.present?
|
300
|
+
zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}'))
|
301
|
+
self.user_timezone = zuora_identity_response.values.first&.dig('timeZone')
|
302
|
+
else
|
303
|
+
if (Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
|
304
|
+
Rails.logger.error('Cannot find any user to set the timezone', app_instance_id: self.id)
|
305
|
+
Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
rescue => ex
|
309
|
+
Rails.logger.error('There is an error while getting timezone users', ex)
|
310
|
+
end
|
311
|
+
|
312
|
+
if self.user_timezone.present?
|
313
|
+
# connect instance which has a custom timezone
|
314
|
+
if !self.auto_deployed? && (
|
315
|
+
ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset !=
|
316
|
+
ActiveSupport::TimeZone[self.user_timezone]&.utc_offset
|
317
|
+
)
|
318
|
+
if self.environment == 'Production' &&
|
319
|
+
(Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
|
320
|
+
ZuoraConnect.logger.error(
|
321
|
+
"Instance and user timezones are different. User has '#{self.user_timezone}' and " \
|
322
|
+
"instance has '#{self.task_data.dig('user_settings', 'timezone')}'",
|
323
|
+
app_instance_id: self.id
|
324
|
+
)
|
325
|
+
Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
|
326
|
+
end
|
327
|
+
self.user_timezone = nil
|
328
|
+
Time.zone = timezone
|
329
|
+
else
|
330
|
+
begin
|
331
|
+
Time.zone = self.user_timezone
|
332
|
+
rescue ArgumentError
|
333
|
+
Rails.logger.error('Malformed user timezone', app_instance_id: self.id)
|
334
|
+
Time.zone = timezone
|
335
|
+
end
|
336
|
+
end
|
337
|
+
else
|
338
|
+
Time.zone = timezone
|
339
|
+
end
|
340
|
+
end
|
341
|
+
rescue => e
|
342
|
+
Rails.logger.error('Malformed timezone used', e, app_instance_id: self.id)
|
343
|
+
Time.zone = self.timezone
|
344
|
+
end
|
345
|
+
|
322
346
|
def auto_deployed?
|
323
347
|
self.id >= 25000000
|
324
348
|
end
|
325
349
|
|
326
|
-
def refresh(session: {})
|
350
|
+
def refresh(session: {})
|
327
351
|
refresh_count ||= 0
|
328
352
|
skip_connect ||= false
|
329
353
|
begin
|
330
354
|
#Check how app was deployed
|
331
|
-
if self.id < 25000000 && !skip_connect
|
355
|
+
if self.id < 25000000 && !skip_connect
|
332
356
|
self.check_oauth_state
|
333
357
|
response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}.json",:body => {:access_token => self.access_token})
|
334
358
|
|
@@ -339,7 +363,7 @@ module ZuoraConnect
|
|
339
363
|
raise ZuoraConnect::Exceptions::ConnectCommunicationError.new("JSON parse error", response.body, response.code)
|
340
364
|
end
|
341
365
|
|
342
|
-
self.build_task(task_data: parsed_json, session: session)
|
366
|
+
self.build_task(task_data: parsed_json, session: session)
|
343
367
|
if self.kms_key.present? && self.kms_key.match(/^arn:aws:.*/)
|
344
368
|
begin
|
345
369
|
self.zuora_logins = self.strip_cache_data(object: parsed_json.dup, keys: ['applications', 'tokens', 'user_settings'])
|
@@ -349,7 +373,7 @@ module ZuoraConnect
|
|
349
373
|
rescue => ex
|
350
374
|
Rails.logger.error(AWS_AUTH_ERRORS_MSG, ex)
|
351
375
|
end
|
352
|
-
end
|
376
|
+
end
|
353
377
|
else
|
354
378
|
raise ZuoraConnect::Exceptions::ConnectCommunicationError.new("Error Communicating with Connect", response.body, response.code)
|
355
379
|
end
|
@@ -455,82 +479,6 @@ module ZuoraConnect
|
|
455
479
|
end
|
456
480
|
Thread.current[:appinstance] = self
|
457
481
|
end
|
458
|
-
|
459
|
-
def self.write_to_telegraf(*args)
|
460
|
-
if ZuoraConnect.configuration.enable_metrics && !defined?(Prometheus)
|
461
|
-
@@telegraf_host = ZuoraConnect::Telegraf.new() if @@telegraf_host == nil
|
462
|
-
unicorn_stats = self.unicorn_listener_stats() if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
463
|
-
@@telegraf_host.write(direction: 'Raindrops', tags: {}, values: unicorn_stats) unless unicorn_stats.blank?
|
464
|
-
return @@telegraf_host.write(*args)
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
def self.unicorn_listener_stats ()
|
469
|
-
stats_hash = {}
|
470
|
-
stats_hash["total_active"] = 0
|
471
|
-
stats_hash["total_queued"] = 0
|
472
|
-
|
473
|
-
begin
|
474
|
-
tmp = Unicorn.listener_names
|
475
|
-
unix = tmp.grep(%r{\A/})
|
476
|
-
tcp = tmp.grep(/\A.+:\d+\z/)
|
477
|
-
tcp = nil if tcp.empty?
|
478
|
-
unix = nil if unix.empty?
|
479
|
-
|
480
|
-
|
481
|
-
Raindrops::Linux.tcp_listener_stats(tcp).each do |addr,stats|
|
482
|
-
stats_hash["active_#{addr}"] = stats.active
|
483
|
-
stats_hash["queued_#{addr}"] = stats.queued
|
484
|
-
stats_hash["total_active"] = stats.active + stats_hash["total_active"]
|
485
|
-
stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
|
486
|
-
end if tcp
|
487
|
-
|
488
|
-
Raindrops::Linux.unix_listener_stats(unix).each do |addr,stats|
|
489
|
-
stats_hash["active_#{addr}"] = stats.active
|
490
|
-
stats_hash["queued_#{addr}"] = stats.queued
|
491
|
-
stats_hash["total_active"] = stats.active + stats_hash["total_active"]
|
492
|
-
stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
|
493
|
-
end if unix
|
494
|
-
rescue IOError => ex
|
495
|
-
rescue => ex
|
496
|
-
ZuoraConnect.logger.error(ex)
|
497
|
-
end
|
498
|
-
return stats_hash
|
499
|
-
end
|
500
|
-
|
501
|
-
def self.get_metrics(type)
|
502
|
-
@data = {}
|
503
|
-
|
504
|
-
if type == "versions"
|
505
|
-
@data = {
|
506
|
-
app_name: ZuoraConnect::Telegraf.app_name,
|
507
|
-
url: "dummy",
|
508
|
-
Version_Gem: ZuoraConnect::VERSION,
|
509
|
-
Version_Zuora: ZuoraAPI::VERSION ,
|
510
|
-
Version_Ruby: RUBY_VERSION,
|
511
|
-
Version_Rails: Rails.version,
|
512
|
-
hold: 1
|
513
|
-
}
|
514
|
-
elsif type == "stats"
|
515
|
-
begin
|
516
|
-
Resque.redis.ping
|
517
|
-
@resque = Resque.info
|
518
|
-
@data = {
|
519
|
-
app_name: ZuoraConnect::Telegraf.app_name,
|
520
|
-
url: "dummy",
|
521
|
-
Resque:{
|
522
|
-
Jobs_Finished: @resque[:processed] ,
|
523
|
-
Jobs_Failed: @resque[:failed],
|
524
|
-
Jobs_Pending: @resque[:pending],
|
525
|
-
Workers_Active: @resque[:working],
|
526
|
-
Workers_Total: @resque[:workers]
|
527
|
-
}
|
528
|
-
}
|
529
|
-
rescue
|
530
|
-
end
|
531
|
-
end
|
532
|
-
return @data
|
533
|
-
end
|
534
482
|
#### END Task Methods ####
|
535
483
|
|
536
484
|
#### START Task Methods ####
|
@@ -573,7 +521,7 @@ module ZuoraConnect
|
|
573
521
|
end
|
574
522
|
rescue ZuoraConnect::Exceptions::MissMatch => ex
|
575
523
|
raise
|
576
|
-
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
524
|
+
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
577
525
|
raise
|
578
526
|
rescue => ex
|
579
527
|
ZuoraConnect.logger.error("Build Task Error", ex)
|
@@ -629,10 +577,10 @@ module ZuoraConnect
|
|
629
577
|
self.refresh if !defined?(self.target_login)
|
630
578
|
|
631
579
|
response = HTTParty.get("#{ZuoraConnect.configuration.url}/api/#{self.api_version}/tenants/search?hostname=#{self.target_login.client.hostname}&node_id=#{self.zuora_entity_ids.first}")
|
632
|
-
|
580
|
+
|
633
581
|
if response.success?
|
634
582
|
parsed_json = JSON.parse(response.body)
|
635
|
-
|
583
|
+
|
636
584
|
#Set Org
|
637
585
|
if self.id >= 25000000 && parsed_json['organization'].present?
|
638
586
|
login_cache = self.zuora_logins
|
@@ -654,7 +602,7 @@ module ZuoraConnect
|
|
654
602
|
end
|
655
603
|
end
|
656
604
|
self.save(:validate => false)
|
657
|
-
|
605
|
+
|
658
606
|
return parsed_json
|
659
607
|
end
|
660
608
|
rescue *(ZuoraAPI::Login::CONNECTION_EXCEPTIONS + ZuoraAPI::Login::CONNECTION_READ_EXCEPTIONS) => ex
|
@@ -708,7 +656,7 @@ module ZuoraConnect
|
|
708
656
|
end
|
709
657
|
|
710
658
|
def refresh_oauth
|
711
|
-
refresh_oauth_count ||= 0
|
659
|
+
refresh_oauth_count ||= 0
|
712
660
|
response = HTTParty.post("#{ZuoraConnect.configuration.url}/oauth/token", body: {
|
713
661
|
:grant_type => "refresh_token",
|
714
662
|
:redirect_uri => ZuoraConnect.configuration.oauth_client_redirect_uri,
|
@@ -1344,7 +1292,7 @@ module ZuoraConnect
|
|
1344
1292
|
|
1345
1293
|
def self.without_sticking
|
1346
1294
|
if self.connection.respond_to?(:without_sticking)
|
1347
|
-
self.connection.without_sticking do
|
1295
|
+
self.connection.without_sticking do
|
1348
1296
|
yield
|
1349
1297
|
end
|
1350
1298
|
else
|
@@ -49,10 +49,10 @@ if defined? Prometheus
|
|
49
49
|
prometheus = Prometheus::Client.registry
|
50
50
|
|
51
51
|
# Create your metrics.
|
52
|
-
ZUORA_VERSION = prometheus.gauge(:zuora_version, docstring: 'The current Zuora Gem version.', labels: %i(version name), preset_labels: { version: ZuoraAPI::VERSION, name:
|
53
|
-
CONNECT_VERSION = prometheus.gauge(:gem_version, docstring: 'The current Connect Gem version.', labels: %i(version name), preset_labels: { version: ZuoraConnect::VERSION, name:
|
54
|
-
RAILS_VERSION = prometheus.gauge(:rails_version, docstring: 'The current Rails version.', labels: %i(version name), preset_labels: { version: Rails.version, name:
|
55
|
-
RUBY_V = prometheus.gauge(:ruby_version, docstring: 'The current Ruby version.', labels: %i(version name), preset_labels: { version: RUBY_VERSION, name:
|
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)
|
56
56
|
|
57
57
|
ZUORA_VERSION.set(0)
|
58
58
|
CONNECT_VERSION.set(0)
|
@@ -61,12 +61,12 @@ if defined? Prometheus
|
|
61
61
|
|
62
62
|
# Do they have resque jobs?
|
63
63
|
if defined? Resque.redis
|
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:
|
65
|
-
JOBS_FINISHED = prometheus.gauge(:jobs_finished, docstring: 'Done resque jobs', labels: %i(type name), preset_labels: {type:'resque', name:
|
66
|
-
WORKERS_TOTAL = prometheus.gauge(:workers_total, docstring: 'Total resque workers', labels: %i(type name), preset_labels: {type:'resque', name:
|
67
|
-
WORKERS_ACTIVE = prometheus.gauge(:workers_active, docstring: 'Active resque workers', labels: %i(type name), preset_labels: {type:'resque', name:
|
68
|
-
JOBS_FAILED = prometheus.gauge(:jobs_failed, docstring: 'Failed resque jobs', labels: %i(type name), preset_labels: {type:'resque', name:
|
69
|
-
JOBS_PENDING = prometheus.gauge(:jobs_pending, docstring: 'Pending resque jobs', labels: %i(type name), preset_labels: {type:'resque', name:
|
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)
|
70
70
|
end
|
71
71
|
|
72
72
|
if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
@@ -74,17 +74,17 @@ if defined? Prometheus
|
|
74
74
|
:unicorn_kills,
|
75
75
|
docstring: 'Unicorn Kills',
|
76
76
|
labels: %i(type name),
|
77
|
-
preset_labels: {type:'Unicorn-Killer', name:
|
77
|
+
preset_labels: {type:'Unicorn-Killer', name: ZuoraObservability::Env.app_name},
|
78
78
|
store_settings: sum_aggregation
|
79
79
|
)
|
80
80
|
|
81
|
-
|
81
|
+
ZuoraObservability::Metrics.unicorn_listener.each do |key, _|
|
82
82
|
gauge_name = "unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_')
|
83
83
|
gauge = prometheus.gauge(
|
84
84
|
gauge_name.to_sym,
|
85
85
|
docstring: 'Unicorn Stats',
|
86
86
|
labels: %i(type name),
|
87
|
-
preset_labels: { type: 'unicorn', name:
|
87
|
+
preset_labels: { type: 'unicorn', name: ZuoraObservability::Env.app_name },
|
88
88
|
store_settings: most_recent_aggregation
|
89
89
|
)
|
90
90
|
Prometheus.const_set(
|
@@ -12,21 +12,21 @@ class RedisFlash
|
|
12
12
|
end
|
13
13
|
|
14
14
|
if defined?(Redis.current)
|
15
|
-
Redis.current = Redis.new(:id => "#{
|
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 => "#{
|
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 => "#{
|
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
|
@@ -36,13 +36,13 @@ Resque.module_eval do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
if defined?(Resque.logger)
|
39
|
-
Resque.logger =
|
40
|
-
Resque::Scheduler.logger =
|
39
|
+
Resque.logger = ZuoraObservability::Logger.custom_logger(name: "Resque", type: 'Monologger', level: MonoLogger::INFO)
|
40
|
+
Resque::Scheduler.logger = ZuoraObservability::Logger.custom_logger(name: "ResqueScheduler") if defined?(Resque::Scheduler)
|
41
41
|
end
|
42
42
|
if defined?(Delayed::Worker.logger)
|
43
|
-
Delayed::Worker.logger =
|
43
|
+
Delayed::Worker.logger = ZuoraObservability::Logger.custom_logger(name: "DelayedJob", type: 'Monologger', level: MonoLogger::INFO)
|
44
44
|
end
|
45
45
|
|
46
|
-
Makara::Logging::Logger.logger =
|
47
|
-
ElasticAPM.agent.config.logger =
|
48
|
-
ActionMailer::Base.logger =
|
46
|
+
Makara::Logging::Logger.logger = ZuoraObservability::Logger.custom_logger(name: "Makara") if defined?(Makara)
|
47
|
+
ElasticAPM.agent.config.logger = ZuoraObservability::Logger.custom_logger(name: "ElasticAPM", level: MonoLogger::WARN) if defined?(ElasticAPM) && ElasticAPM.running?
|
48
|
+
ActionMailer::Base.logger = ZuoraObservability::Logger.custom_logger(name: "ActionMailer", type: 'Monologger') if defined?(ActionMailer)
|
@@ -6,7 +6,7 @@ if defined?(Unicorn::WorkerKiller)
|
|
6
6
|
if defined?(Prometheus)
|
7
7
|
Prometheus::UNICORN_KILLS.set(1)
|
8
8
|
else
|
9
|
-
|
9
|
+
ZuoraObservability::Metrics.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -34,4 +34,4 @@ if defined?(Unicorn::HttpServer) && defined?(Prometheus)
|
|
34
34
|
class Unicorn::Worker
|
35
35
|
prepend WorkerExtensions
|
36
36
|
end
|
37
|
-
end
|
37
|
+
end
|
data/config/routes.rb
CHANGED
data/lib/metrics/net.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -17,7 +17,7 @@ module ZuoraConnect
|
|
17
17
|
# payloads with 500 requests do not have status as it is not set by the controller
|
18
18
|
# https://github.com/rails/rails/issues/33335
|
19
19
|
#status_code = payload[:status] ? payload[:status] : payload[:exception_object].present? ? 500 : ""
|
20
|
-
if payload[:exception].present?
|
20
|
+
if payload[:exception].present?
|
21
21
|
status_code, exception = [500, payload[:exception].first]
|
22
22
|
else
|
23
23
|
status_code, exception = [payload[:status], nil]
|
@@ -28,7 +28,7 @@ module ZuoraConnect
|
|
28
28
|
values = {view_time: payload[:view_runtime], db_time: payload[:db_runtime], response_time: ((finished-started)*1000)}.compact
|
29
29
|
values = values.map{ |k,v| [k,v.round(2)]}.to_h
|
30
30
|
|
31
|
-
|
31
|
+
ZuoraObservability::Metrics.write_to_telegraf(direction: :inbound, tags: tags, values: values)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -42,7 +42,7 @@ module ZuoraConnect
|
|
42
42
|
end
|
43
43
|
|
44
44
|
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"]
|
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"]
|
46
46
|
if !ActionDispatch::Request::HTTP_METHODS.include?(env["REQUEST_METHOD"].upcase)
|
47
47
|
[405, {"Content-Type" => "text/plain"}, ["Method Not Allowed"]]
|
48
48
|
else
|
@@ -66,14 +66,14 @@ module ZuoraConnect
|
|
66
66
|
|
67
67
|
if defined?(Prometheus) && env['PATH_INFO'] == '/connect/internal/metrics'
|
68
68
|
# Prometheus Stuff
|
69
|
-
metrics =
|
69
|
+
metrics = ZuoraObservability::Metrics.resque
|
70
70
|
redis_up = metrics.present? && metrics.dig(:Resque, :Workers_Total).present? ? 1 : 0
|
71
71
|
Prometheus::REDIS_CONNECTION.set(redis_up)
|
72
72
|
|
73
73
|
process_prometheus_metric(metrics: metrics)
|
74
74
|
|
75
75
|
if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
76
|
-
|
76
|
+
ZuoraObservability::Metrics.unicorn_listener.each do |key, value|
|
77
77
|
gauge = Prometheus.const_get("unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_').upcase)
|
78
78
|
gauge.set(value) if gauge.present?
|
79
79
|
end
|
@@ -84,13 +84,13 @@ module ZuoraConnect
|
|
84
84
|
start_time = Time.now
|
85
85
|
begin
|
86
86
|
@status, @headers, @response = @app.call(env)
|
87
|
-
ensure
|
88
|
-
|
87
|
+
ensure
|
88
|
+
|
89
89
|
# If the url contains any CSS or JavaScript files then do not collect metrics for them
|
90
90
|
if ["css", "assets", "jpg", "png", "jpeg", "ico"].any? { |word| env['PATH_INFO'].include?(word) } || /.*\.js$/.match(env['PATH_INFO'])
|
91
91
|
tags = {status: @status, controller: 'ActionController', action: 'Assets', app_instance: 0}
|
92
92
|
values = {response_time: ((Time.now - start_time)*1000).round(2) }
|
93
|
-
|
93
|
+
ZuoraObservability::Metrics.write_to_telegraf(direction: 'request-inbound-assets', tags: tags, values: values)
|
94
94
|
end
|
95
95
|
|
96
96
|
# Uncomment following block of code for handling engine requests/requests without controller
|
@@ -112,7 +112,7 @@ module ZuoraConnect
|
|
112
112
|
|
113
113
|
values = {response_time: ((Time.now - start_time)*1000).round(2) }
|
114
114
|
|
115
|
-
|
115
|
+
ZuoraObservability::Metrics.write_to_telegraf(direction: :inbound, tags: tags, values: values)
|
116
116
|
end
|
117
117
|
end
|
118
118
|
Thread.current[:inbound_metric] = nil
|
@@ -140,7 +140,7 @@ module ZuoraConnect
|
|
140
140
|
gauge_name.to_sym,
|
141
141
|
docstring: "#{key} metric",
|
142
142
|
labels: %i(type name),
|
143
|
-
preset_labels: { type: type, name:
|
143
|
+
preset_labels: { type: type, name: ZuoraObservability::Env.app_name },
|
144
144
|
store_settings: most_recent_aggregation
|
145
145
|
)
|
146
146
|
gauge.set(value)
|
data/lib/zuora_connect.rb
CHANGED
@@ -9,12 +9,11 @@ require 'resque/silence_done'
|
|
9
9
|
require 'resque/self_lookup'
|
10
10
|
require 'resque/plugins/custom_logger'
|
11
11
|
require 'resque/plugins/app_instance_job'
|
12
|
-
require 'logging/connect_formatter'
|
13
|
-
require 'metrics/influx/point_value'
|
14
12
|
require 'metrics/net'
|
15
13
|
require 'mono_logger'
|
16
14
|
require 'zuora_connect/zuora_audit'
|
17
15
|
require 'active_record'
|
16
|
+
require 'zuora_observability'
|
18
17
|
::ActiveRecord::Base.send :include, ZuoraConnect::ZuoraAudit
|
19
18
|
|
20
19
|
module ZuoraConnect
|
@@ -29,68 +28,9 @@ module ZuoraConnect
|
|
29
28
|
when 'test'
|
30
29
|
Rails.logger
|
31
30
|
else
|
32
|
-
@logger ||= custom_logger(name: "Connect", level: Rails.logger.level)
|
31
|
+
@logger ||= ZuoraObservability::Logger.custom_logger(name: "Connect", level: Rails.logger.level)
|
33
32
|
end
|
34
33
|
end
|
35
|
-
|
36
|
-
def custom_logger(name: "", level: Rails.logger.present? ? Rails.logger.level : MonoLogger::INFO, type: :ougai)
|
37
|
-
#puts name + ' - ' + {Logger::WARN => 'Logger::WARN', Logger::ERROR => 'Logger::ERROR', Logger::DEBUG => 'Logger::DEBUG', Logger::INFO => 'Logger::INFO' }[level] + ' - '
|
38
|
-
if type == :ougai
|
39
|
-
require 'ougai'
|
40
|
-
require "ougai/formatters/customizable"
|
41
|
-
#logger = Ougai::Logger.new(MonoLogger.new(STDOUT))
|
42
|
-
logger = Ougai::Logger.new(STDOUT)
|
43
|
-
logger.level = level
|
44
|
-
if ZuoraConnect.configuration.json_logging
|
45
|
-
logger.formatter = Ougai::Formatters::ConnectFormatter.new(name)
|
46
|
-
logger.before_log = lambda do |data|
|
47
|
-
data[:trace_id] = ZuoraConnect::RequestIdMiddleware.request_id if ZuoraConnect::RequestIdMiddleware.request_id.present?
|
48
|
-
data[:zuora_trace_id] = ZuoraConnect::RequestIdMiddleware.zuora_request_id if ZuoraConnect::RequestIdMiddleware.zuora_request_id.present?
|
49
|
-
#data[:traces] = {amazon_id: data[:trace_id], zuora_id: data[:zuora_trace_id]}
|
50
|
-
end
|
51
|
-
else
|
52
|
-
logger.formatter = Ougai::Formatters::Customizable.new(
|
53
|
-
format_err: proc do |data|
|
54
|
-
next nil unless data.key?(:err)
|
55
|
-
err = data.delete(:err)
|
56
|
-
" #{err[:name]} (#{err[:message]})\n #{err[:stack]}"
|
57
|
-
end,
|
58
|
-
format_data: proc do |data|
|
59
|
-
data.delete(:app_instance_id); data.delete(:tenant_ids); data.delete(:organization); data.delete(:environment)
|
60
|
-
format('%s %s: %s', 'DATA'.ljust(6), Time.now.strftime('%FT%T.%6NZ'), "#{data.to_json}") if data.present?
|
61
|
-
end,
|
62
|
-
format_msg: proc do |severity, datetime, _progname, data|
|
63
|
-
msg = data.delete(:msg)
|
64
|
-
format('%s %s: %s', severity.ljust(6), datetime, msg)
|
65
|
-
end
|
66
|
-
)
|
67
|
-
logger.formatter.datetime_format = '%FT%T.%6NZ'
|
68
|
-
end
|
69
|
-
else
|
70
|
-
logger = MonoLogger.new(STDOUT)
|
71
|
-
logger.level = level
|
72
|
-
logger.formatter = proc do |serverity, datetime, progname, msg|
|
73
|
-
begin
|
74
|
-
msg = JSON.parse(msg)
|
75
|
-
rescue JSON::ParserError => ex
|
76
|
-
end
|
77
|
-
if ZuoraConnect.configuration.json_logging
|
78
|
-
require 'json'
|
79
|
-
store = {
|
80
|
-
name: name,
|
81
|
-
level: serverity,
|
82
|
-
timestamp: datetime.strftime('%FT%T.%6NZ'),
|
83
|
-
pid: Process.pid,
|
84
|
-
message: name == "ActionMailer" ? msg.strip : msg
|
85
|
-
}
|
86
|
-
JSON.dump(store) + "\n"
|
87
|
-
else
|
88
|
-
format('%s %s: %s', serverity.ljust(6), datetime, msg) + "\n"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
return logger
|
93
|
-
end
|
94
34
|
end
|
95
35
|
|
96
36
|
module Controllers
|
@@ -147,7 +87,7 @@ module ZuoraConnect
|
|
147
87
|
verify_server_cert: false,
|
148
88
|
log_level: Logger::INFO,
|
149
89
|
service_name: ENV['DEIS_APP'].present? ? ENV['DEIS_APP'] : Rails.application.class.parent_name,
|
150
|
-
logger:
|
90
|
+
logger: ZuoraObservability::Logger.custom_logger(name: "ElasticAPM", level: MonoLogger::WARN)
|
151
91
|
})
|
152
92
|
defaults.merge!({disable_send: true}) if defined?(Rails::Console)
|
153
93
|
|
@@ -138,12 +138,8 @@ module ZuoraConnect
|
|
138
138
|
end
|
139
139
|
ZuoraConnect.logger.error(ex) if !ZuoraConnect::AppInstance::IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
140
140
|
end
|
141
|
-
|
142
|
-
|
143
|
-
Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
|
144
|
-
end
|
145
|
-
rescue
|
146
|
-
ZuoraConnect.logger.error(ex)
|
141
|
+
if @appinstance.user_timezone.blank?
|
142
|
+
@appinstance.set_timezone(timezone: session["#{@appinstance.id}::user::timezone"], type: :default)
|
147
143
|
end
|
148
144
|
end
|
149
145
|
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
data/lib/zuora_connect/engine.rb
CHANGED
@@ -10,9 +10,10 @@ module ZuoraConnect
|
|
10
10
|
|
11
11
|
initializer "connect", before: :load_config_initializers do |app|
|
12
12
|
Rails.application.routes.prepend do
|
13
|
+
get '/connect/internal/data' => 'zuora_observability/metrics#metrics'
|
13
14
|
mount ZuoraConnect::Engine, at: "/connect"
|
14
15
|
match '/api/connect/health', via: :all, to: 'zuora_connect/static#health'
|
15
|
-
match '/api/connect/internal/data', via: :all, to: '
|
16
|
+
match '/api/connect/internal/data', via: :all, to: 'zuora_observability/metrics#metrics'
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
@@ -46,68 +46,5 @@ module ZuoraConnect
|
|
46
46
|
|
47
47
|
# hook to process_action
|
48
48
|
ActiveSupport::Notifications.subscribe('process_action.action_controller', ZuoraConnect::PageRequest.new)
|
49
|
-
|
50
|
-
initializer(:rails_stdout_logging, before: :initialize_logger) do
|
51
|
-
require 'lograge'
|
52
|
-
|
53
|
-
Rails.configuration.logger = ZuoraConnect.custom_logger(name: "Rails")
|
54
|
-
if !Rails.env.test? && !Rails.env.development?
|
55
|
-
Rails.configuration.lograge.enabled = true
|
56
|
-
Rails.configuration.colorize_logging = false
|
57
|
-
end
|
58
|
-
|
59
|
-
if Rails.configuration.lograge.enabled
|
60
|
-
if Rails.configuration.logger.class.to_s == 'Ougai::Logger'
|
61
|
-
Rails.configuration.lograge.formatter = Class.new do |fmt|
|
62
|
-
def fmt.call(data)
|
63
|
-
{ msg: 'Rails Request', request: data }
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
#Rails.configuration.lograge.formatter = Lograge::Formatters::Json.new
|
68
|
-
Rails.configuration.lograge.custom_options = lambda do |event|
|
69
|
-
exceptions = %w(controller action format)
|
70
|
-
items = {
|
71
|
-
#time: event.time.strftime('%FT%T.%6N'),
|
72
|
-
params: event.payload[:params].as_json(except: exceptions).to_json.to_s
|
73
|
-
}
|
74
|
-
items.merge!({exception_object: event.payload[:exception_object]}) if event.payload[:exception_object].present?
|
75
|
-
items.merge!({exception: event.payload[:exception]}) if event.payload[:exception].present?
|
76
|
-
|
77
|
-
if event.payload[:headers].present?
|
78
|
-
# By convertion, headers usually do not have dots. Nginx even rejects headers with dots
|
79
|
-
# All Rails headers are namespaced, like 'rack.input'.
|
80
|
-
# Thus, we can obtain the client headers by rejecting dots
|
81
|
-
request_headers =
|
82
|
-
event.payload[:headers].env.
|
83
|
-
reject { |key| key.to_s.include?('.') || REQUEST_HEADERS_TO_IGNORE.include?(key.to_s) }
|
84
|
-
begin
|
85
|
-
if request_headers["HTTP_AUTHORIZATION"].present?
|
86
|
-
if request_headers["HTTP_AUTHORIZATION"].include?("Basic")
|
87
|
-
user_password = request_headers["HTTP_AUTHORIZATION"].split("Basic").last.strip
|
88
|
-
user, password = Base64.decode64(user_password).split(":")
|
89
|
-
request_headers["HTTP_AUTHORIZATION"] = "Basic #{user}:ValueFiltered"
|
90
|
-
elsif
|
91
|
-
request_headers["HTTP_AUTHORIZATION"] = "ValueFiltered"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
request_headers["HTTP_API_TOKEN"] = "ValueFiltered" if request_headers["HTTP_API_TOKEN"].present?
|
95
|
-
rescue
|
96
|
-
request_headers.delete("HTTP_API_TOKEN")
|
97
|
-
request_headers.delete("HTTP_AUTHORIZATION")
|
98
|
-
end
|
99
|
-
items.merge!({ headers: request_headers.to_s })
|
100
|
-
end
|
101
|
-
|
102
|
-
if Thread.current[:appinstance].present?
|
103
|
-
items.merge!({connect_user: Thread.current[:appinstance].connect_user, new_session: Thread.current[:appinstance].new_session_message})
|
104
|
-
if Thread.current[:appinstance].logitems.present? && Thread.current[:appinstance].logitems.class == Hash
|
105
|
-
items.merge!(Thread.current[:appinstance].logitems)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
return items
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
49
|
end
|
113
50
|
end
|
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:
|
4
|
+
version: 3.0.0.pre.a
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Connect Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: apartment
|
@@ -182,6 +182,20 @@ dependencies:
|
|
182
182
|
- - ">="
|
183
183
|
- !ruby/object:Gem::Version
|
184
184
|
version: '0'
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
name: zuora_observability
|
187
|
+
requirement: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
type: :runtime
|
193
|
+
prerelease: false
|
194
|
+
version_requirements: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
185
199
|
- !ruby/object:Gem::Dependency
|
186
200
|
name: rspec
|
187
201
|
requirement: !ruby/object:Gem::Requirement
|
@@ -318,7 +332,6 @@ files:
|
|
318
332
|
- app/models/zuora_connect/app_instance.rb
|
319
333
|
- app/models/zuora_connect/app_instance_base.rb
|
320
334
|
- app/models/zuora_connect/login.rb
|
321
|
-
- app/models/zuora_connect/telegraf.rb
|
322
335
|
- app/models/zuora_connect/zuora_user.rb
|
323
336
|
- app/views/layouts/zuora_connect/application.html.erb
|
324
337
|
- app/views/sql/refresh_aggregate_table.txt
|
@@ -353,8 +366,6 @@ files:
|
|
353
366
|
- db/migrate/20190520232222_add_unique_index.rb
|
354
367
|
- db/migrate/20190520232223_add_provisioning_fields.rb
|
355
368
|
- db/migrate/20190520232224_add_environment_fields.rb
|
356
|
-
- lib/logging/connect_formatter.rb
|
357
|
-
- lib/metrics/influx/point_value.rb
|
358
369
|
- lib/metrics/net.rb
|
359
370
|
- lib/middleware/bad_multipart_form_data_sanitizer.rb
|
360
371
|
- lib/middleware/json_parse_errors.rb
|
@@ -1,97 +0,0 @@
|
|
1
|
-
module ZuoraConnect
|
2
|
-
class Telegraf
|
3
|
-
attr_accessor :host
|
4
|
-
|
5
|
-
OUTBOUND_METRICS = true
|
6
|
-
OUTBOUND_METRICS_NAME = "request-outbound"
|
7
|
-
INBOUND_METRICS = true
|
8
|
-
INBOUND_METRICS_NAME = "request-inbound"
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
self.connect
|
12
|
-
end
|
13
|
-
|
14
|
-
def connect
|
15
|
-
ZuoraConnect.logger.debug(self.format_metric_log('Telegraf','Need new connection')) if ZuoraConnect.configuration.telegraf_debug
|
16
|
-
uri = URI.parse(ZuoraConnect.configuration.telegraf_endpoint)
|
17
|
-
self.host = UDPSocket.new.tap do |socket|
|
18
|
-
socket.connect uri.host, uri.port
|
19
|
-
end
|
20
|
-
rescue => ex
|
21
|
-
self.host = nil
|
22
|
-
ZuoraConnect.logger.warn(self.format_metric_log('Telegraf', "Failed to connect: #{ex.class}")) if Rails.env.to_s != 'production'
|
23
|
-
end
|
24
|
-
|
25
|
-
def write(direction: 'Unknown', tags: {}, values: {})
|
26
|
-
time = Benchmark.measure do |bench|
|
27
|
-
# To avoid writing metrics from rspec tests
|
28
|
-
if Rails.env.to_sym != :test
|
29
|
-
app_instance = Thread.current[:appinstance].present? ? Thread.current[:appinstance].id : 0
|
30
|
-
tags = { app_name: self.class.app_name, process_type: self.class.process_type, app_instance: app_instance, pod_name: self.class.pod_name}.merge(tags)
|
31
|
-
|
32
|
-
if direction == :inbound
|
33
|
-
if INBOUND_METRICS && !Thread.current[:inbound_metric].to_bool
|
34
|
-
self.write_udp(series: INBOUND_METRICS_NAME, tags: tags, values: values)
|
35
|
-
Thread.current[:inbound_metric] = true
|
36
|
-
else
|
37
|
-
return
|
38
|
-
end
|
39
|
-
elsif direction == :outbound
|
40
|
-
self.write_udp(series: OUTBOUND_METRICS_NAME, tags: tags, values: values) if OUTBOUND_METRICS
|
41
|
-
else
|
42
|
-
self.write_udp(series: direction, tags: tags, values: values)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
if ZuoraConnect.configuration.telegraf_debug
|
47
|
-
ZuoraConnect.logger.debug(self.format_metric_log('Telegraf', tags.to_s))
|
48
|
-
ZuoraConnect.logger.debug(self.format_metric_log('Telegraf', values.to_s))
|
49
|
-
ZuoraConnect.logger.debug(self.format_metric_log('Telegraf', "Writing '#{direction.capitalize}': #{time.real.round(5)} ms"))
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
def write_udp(series: '', tags: {}, values: {})
|
55
|
-
return if !values.present?
|
56
|
-
self.host.write InfluxDB::PointValue.new({series: series, tags: tags, values: values}).dump
|
57
|
-
rescue => ex
|
58
|
-
self.connect
|
59
|
-
ZuoraConnect.logger.warn(self.format_metric_log('Telegraf',"Failed to write udp: #{ex.class}")) if Rails.env.to_s != 'production'
|
60
|
-
end
|
61
|
-
|
62
|
-
def format_metric_log(message, dump = nil)
|
63
|
-
message_color, dump_color = "1;91", "0;1"
|
64
|
-
log_entry = " \e[#{message_color}m#{message}\e[0m "
|
65
|
-
log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
|
66
|
-
if Rails.env == :development
|
67
|
-
log_entry
|
68
|
-
else
|
69
|
-
[message, dump].compact.join(' - ')
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def self.app_name
|
74
|
-
return ENV['DEIS_APP'].present? ? ENV['DEIS_APP'] : Rails.application.class.parent_name
|
75
|
-
end
|
76
|
-
|
77
|
-
def self.pod_name
|
78
|
-
return ENV['HOSTNAME'].present? ? ENV['HOSTNAME'] : Socket.gethostname
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.full_process_name(process_name: nil, function: nil)
|
82
|
-
keys = [self.pod_name, process_name.present? ? process_name : self.process_type, Process.pid, function]
|
83
|
-
return keys.compact.join('][').prepend('[').concat(']')
|
84
|
-
end
|
85
|
-
|
86
|
-
# Returns the process type if any
|
87
|
-
def self.process_type(default: 'Unknown')
|
88
|
-
p_type = default
|
89
|
-
if ENV['HOSTNAME'] && ENV['DEIS_APP']
|
90
|
-
temp = ENV['HOSTNAME'].split(ENV['DEIS_APP'])[1]
|
91
|
-
temp = temp.split(/(-[0-9a-zA-Z]{5})$/)[0] # remove the 5 char hash
|
92
|
-
p_type = temp[1, temp.rindex("-")-1]
|
93
|
-
end
|
94
|
-
return p_type
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'ougai/formatters/base'
|
2
|
-
require 'ougai/formatters/for_json'
|
3
|
-
|
4
|
-
module Ougai
|
5
|
-
module Formatters
|
6
|
-
# A JSON formatter compatible with node-bunyan
|
7
|
-
class ConnectFormatter < Base
|
8
|
-
include ForJson
|
9
|
-
|
10
|
-
# Intialize a formatter
|
11
|
-
# @param [String] app_name application name (execution program name if nil)
|
12
|
-
# @param [String] hostname hostname (hostname if nil)
|
13
|
-
# @param [Hash] opts the initial values of attributes
|
14
|
-
# @option opts [String] :trace_indent (2) the value of trace_indent attribute
|
15
|
-
# @option opts [String] :trace_max_lines (100) the value of trace_max_lines attribute
|
16
|
-
# @option opts [String] :serialize_backtrace (true) the value of serialize_backtrace attribute
|
17
|
-
# @option opts [String] :jsonize (true) the value of jsonize attribute
|
18
|
-
# @option opts [String] :with_newline (true) the value of with_newline attribute
|
19
|
-
def initialize(app_name = nil, hostname = nil, opts = {})
|
20
|
-
aname, hname, opts = Base.parse_new_params([app_name, hostname, opts])
|
21
|
-
super(aname, hname, opts)
|
22
|
-
init_opts_for_json(opts)
|
23
|
-
end
|
24
|
-
|
25
|
-
def _call(severity, time, progname, data)
|
26
|
-
data.merge!({message: data.delete(:msg)})
|
27
|
-
if data[:timestamp].present?
|
28
|
-
time = data[:timestamp]
|
29
|
-
data.delete(:timestamp)
|
30
|
-
end
|
31
|
-
dump({
|
32
|
-
name: progname || @app_name,
|
33
|
-
pid: $$,
|
34
|
-
level: severity,
|
35
|
-
timestamp: time.utc.strftime('%FT%T.%6NZ'),
|
36
|
-
}.merge(data))
|
37
|
-
end
|
38
|
-
|
39
|
-
def convert_time(data)
|
40
|
-
#data[:timestamp] = format_datetime(data[:time])
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,79 +0,0 @@
|
|
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
|