From f283e062c9ef79029fcd77cb08b076809a78eb53 Mon Sep 17 00:00:00 2001
From: Gregg Tanzillo <gtanzill@redhat.com>
Date: Mon, 24 Apr 2017 21:56:40 -0400
Subject: [PATCH] Merge pull request #13856 from
 jrafanie/set_database_application_name

Set database application name in workers and server
(cherry picked from commit f241df45cc9ef588bd4c9041249ec59264f117f9)
---
 app/models/miq_server.rb                       |  4 ++++
 app/models/miq_worker.rb                       | 15 +++++++++++++++
 app/models/miq_worker/runner.rb                | 16 ++++++++++++----
 lib/extensions/ar_application_name.rb          | 16 ++++++++++++++++
 lib/workers/evm_server.rb                      |  9 +++++++++
 spec/lib/workers/evm_server_spec.rb            |  2 ++
 spec/models/miq_schedule_worker/runner_spec.rb |  2 +-
 7 files changed, 59 insertions(+), 5 deletions(-)
 create mode 100644 lib/extensions/ar_application_name.rb

diff --git a/app/models/miq_server.rb b/app/models/miq_server.rb
index f04f93de489..01e32c6a53d 100644
--- a/app/models/miq_server.rb
+++ b/app/models/miq_server.rb
@@ -485,6 +485,10 @@ def who_am_i
     @who_am_i ||= "#{name} #{my_zone} #{self.class.name} #{id}"
   end
 
+  def database_application_name
+    "MIQ #{Process.pid} Server[#{compressed_id}], #{zone.name}[#{zone.compressed_id}]".truncate(64)
+  end
+
   def is_local?
     guid == MiqServer.my_guid
   end
diff --git a/app/models/miq_worker.rb b/app/models/miq_worker.rb
index 463065cf6d7..40ec6ccc2a0 100644
--- a/app/models/miq_worker.rb
+++ b/app/models/miq_worker.rb
@@ -472,6 +472,21 @@ def friendly_name
 
   delegate :normalized_type, :to => :class
 
+  def abbreviated_class_name
+    type.sub(/^ManageIQ::Providers::/, "")
+  end
+
+  def minimal_class_name
+    abbreviated_class_name
+      .sub(/Miq/, "")
+      .sub(/Worker/, "")
+  end
+
+  def database_application_name
+    zone = MiqServer.my_server.zone
+    "MIQ #{Process.pid} #{minimal_class_name}[#{compressed_id}], s[#{miq_server.compressed_id}], #{zone.name}[#{zone.compressed_id}]".truncate(64)
+  end
+
   def format_full_log_msg
     "Worker [#{self.class}] with ID: [#{id}], PID: [#{pid}], GUID: [#{guid}]"
   end
diff --git a/app/models/miq_worker/runner.rb b/app/models/miq_worker/runner.rb
index eeb597068b3..1b4a9c97e38 100644
--- a/app/models/miq_worker/runner.rb
+++ b/app/models/miq_worker/runner.rb
@@ -57,7 +57,6 @@ def initialize(cfg = {})
   def worker_initialization
     starting_worker_record
     set_process_title
-
     # Sync the config and roles early since heartbeats and logging require the configuration
     sync_active_roles
     sync_config
@@ -65,6 +64,11 @@ def worker_initialization
     set_connection_pool_size
   end
 
+  # More process specific stuff :-(
+  def set_database_application_name
+    ArApplicationName.name = @worker.database_application_name
+  end
+
   def set_connection_pool_size
     cur_size = ActiveRecord::Base.connection_pool.instance_variable_get(:@size)
     new_size = worker_settings[:connection_pool_size] || cur_size
@@ -142,6 +146,7 @@ def recover_from_temporary_failure
   end
 
   def prepare
+    set_database_application_name
     ObjectSpace.garbage_collect
     started_worker_record
     do_wait_for_worker_monitor if self.class.wait_for_worker_monitor?
@@ -469,12 +474,15 @@ def clean_broker_connection
     _log.info("#{log_prefix} Releasing any broker connections for pid: [#{Process.pid}], ERROR: #{err.message}")
   end
 
-  def set_process_title
-    type   = @worker.type.sub(/^ManageIQ::Providers::/, "")
+  def process_title
+    type   = @worker.abbreviated_class_name
     title  = "#{MiqWorker::PROCESS_TITLE_PREFIX} #{type} id: #{@worker.id}"
     title << ", queue: #{@worker.queue_name}" if @worker.queue_name
     title << ", uri: #{@worker.uri}" if @worker.uri
+    title
+  end
 
-    Process.setproctitle(title)
+  def set_process_title
+    Process.setproctitle(process_title)
   end
 end
diff --git a/lib/extensions/ar_application_name.rb b/lib/extensions/ar_application_name.rb
new file mode 100644
index 00000000000..bcfbd029669
--- /dev/null
+++ b/lib/extensions/ar_application_name.rb
@@ -0,0 +1,16 @@
+module ArApplicationName
+  # We need to set the PGAPPNAME env variable and force the 'pg' gem objects to be
+  # recreated with this env variable set. This is done by disconnecting all of the
+  # connections in the pool.  We do this because reconnect! on an instance of the
+  # AR adapter created prior to our change to PGAPPNAME will have old connection
+  # options, which will reset our application_name.
+  #
+  # Because we fork workers from the server, if we don't disconnect the pool,
+  # any call to reconnect! on a connection will cause the worker's connection
+  # to have the server's application_name.
+  def self.name=(name)
+    # TODO: this is postgresql specific
+    ENV['PGAPPNAME'] = name
+    ActiveRecord::Base.connection_pool.disconnect!
+  end
+end
diff --git a/lib/workers/evm_server.rb b/lib/workers/evm_server.rb
index 7d9dd45830d..4633573f8e7 100644
--- a/lib/workers/evm_server.rb
+++ b/lib/workers/evm_server.rb
@@ -62,6 +62,7 @@ def start
 
     PidFile.create(MiqServer.pidfile)
     set_process_title
+    set_database_application_name
     MiqServer.start
   rescue Interrupt => e
     process_hard_signal(e.message)
@@ -78,6 +79,14 @@ def set_process_title
     Process.setproctitle(SERVER_PROCESS_TITLE) if Process.respond_to?(:setproctitle)
   end
 
+  def set_database_application_name
+    ArApplicationName.name = database_application_name
+  end
+
+  def database_application_name
+    MiqServer.my_server.database_application_name
+  end
+
   def self.start(*args)
     # Parse the args into the global config variable
     cfg = {}
diff --git a/spec/lib/workers/evm_server_spec.rb b/spec/lib/workers/evm_server_spec.rb
index e97a579ca08..25b173fb542 100644
--- a/spec/lib/workers/evm_server_spec.rb
+++ b/spec/lib/workers/evm_server_spec.rb
@@ -6,6 +6,8 @@
 
     before do
       allow(MiqServer).to receive_messages(:running? => false)
+      allow(server).to receive(:set_database_application_name)
+      allow(server).to receive(:set_process_title)
       allow(PidFile).to receive(:create)
     end
 
diff --git a/spec/models/miq_schedule_worker/runner_spec.rb b/spec/models/miq_schedule_worker/runner_spec.rb
index 6f7295ae1d8..1d35c220e7e 100644
--- a/spec/models/miq_schedule_worker/runner_spec.rb
+++ b/spec/models/miq_schedule_worker/runner_spec.rb
@@ -26,7 +26,7 @@
         @worker1 = FactoryGirl.create(:miq_worker, :status => MiqWorker::STATUS_STOPPED)
         @dispatch1 = FactoryGirl.create(:miq_queue, {:zone => @zone1.name, :handler_type => @worker1.class.name, :handler_id => @worker1.id}.merge(@opts))
 
-        @zone2 = FactoryGirl.create(:zone, :name => 'zone2')
+        @zone2 = FactoryGirl.create(:zone)
         @worker2 = FactoryGirl.create(:miq_worker, :status => MiqWorker::STATUS_STOPPED)
 
         allow(MiqServer).to receive(:my_zone).and_return(@zone1.name)