diff --git a/app/controllers/api_controller.rb b/app/controllers/api_controller.rb
index a7764cbc9..23178b5f3 100644
--- a/app/controllers/api_controller.rb
+++ b/app/controllers/api_controller.rb
@@ -2,6 +2,24 @@ class ApiController < ApplicationController
skip_before_action :set_current_user, only: [:index]
def index
- render json: { version: Chatwoot.config[:version], timestamp: Time.now.utc.to_formatted_s(:db) }
+ render json: { version: Chatwoot.config[:version],
+ timestamp: Time.now.utc.to_formatted_s(:db),
+ queue_services: redis_status,
+ data_services: postgres_status }
+ end
+
+ private
+
+ def redis_status
+ r = Redis.new(Redis::Config.app)
+ return 'ok' if r.ping
+ rescue Redis::CannotConnectError
+ 'failing'
+ end
+
+ def postgres_status
+ ActiveRecord::Base.connection.active? ? 'ok' : 'failing'
+ rescue ActiveRecord::ConnectionNotEstablished
+ 'failing'
end
end
diff --git a/app/controllers/super_admin/instance_statuses_controller.rb b/app/controllers/super_admin/instance_statuses_controller.rb
new file mode 100644
index 000000000..5a99582b6
--- /dev/null
+++ b/app/controllers/super_admin/instance_statuses_controller.rb
@@ -0,0 +1,44 @@
+class SuperAdmin::InstanceStatusesController < SuperAdmin::ApplicationController
+ def show
+ @metrics = {}
+ chatwoot_version
+ sha
+ postgres_status
+ redis_metrics
+ end
+
+ def chatwoot_version
+ @metrics['Chatwoot version'] = Chatwoot.config[:version]
+ end
+
+ def sha
+ sha = `git rev-parse HEAD`
+ @metrics['Git SHA'] = sha.presence || 'n/a'
+ end
+
+ def postgres_status
+ @metrics['Postgres alive'] = if ActiveRecord::Base.connection.active?
+ 'true'
+ else
+ 'false'
+ end
+ end
+
+ def redis_metrics
+ r = Redis.new(Redis::Config.app)
+ if r.ping == 'PONG'
+ redis_server = r.info
+ @metrics['Redis alive'] = 'false'
+ @metrics['Redis version'] = redis_server['redis_version']
+ @metrics['Redis number of connected clients'] = redis_server['connected_clients']
+ @metrics["Redis 'maxclients' setting"] = redis_server['maxclients']
+ @metrics['Redis memory used'] = redis_server['used_memory_human']
+ @metrics['Redis memory peak'] = redis_server['used_memory_peak_human']
+ @metrics['Redis total memory available'] = redis_server['total_system_memory_human']
+ @metrics["Redis 'maxmemory' setting"] = redis_server['maxmemory']
+ @metrics["Redis 'maxmemory_policy' setting"] = redis_server['maxmemory_policy']
+ end
+ rescue Redis::CannotConnectError
+ @metrics['Redis alive'] = false
+ end
+end
diff --git a/app/views/super_admin/application/_navigation.html.erb b/app/views/super_admin/application/_navigation.html.erb
index 73e7c29af..e09ebb277 100644
--- a/app/views/super_admin/application/_navigation.html.erb
+++ b/app/views/super_admin/application/_navigation.html.erb
@@ -40,7 +40,7 @@ as defined by the routes in the `admin/` namespace
<% Administrate::Namespace.new(namespace).resources.each do |resource| %>
- <% next if ["account_users", "dashboard", "devise/sessions", "app_configs" ].include? resource.resource %>
+ <% next if ["account_users", "dashboard", "devise/sessions", "app_configs", "instance_statuses" ].include? resource.resource %>
<%= link_to(
@@ -50,6 +50,11 @@ as defined by the routes in the `admin/` namespace
<% end %>
+
+
+ <%= link_to "Instance Health", super_admin_instance_status_url %>
+
+
<%= link_to "Sidekiq", sidekiq_web_url, { target: "_blank" } %>
diff --git a/app/views/super_admin/instance_statuses/show.html.erb b/app/views/super_admin/instance_statuses/show.html.erb
new file mode 100644
index 000000000..d0d23f2a1
--- /dev/null
+++ b/app/views/super_admin/instance_statuses/show.html.erb
@@ -0,0 +1,23 @@
+<% content_for(:title) do %>
+ Instance Health
+<% end %>
+
+
+ <%= content_for(:title) %>
+
+
+
+
+
+ | Metric |
+ Value |
+
+ <% @metrics.each do |key,value| %>
+
+ | <%= key %> |
+ <%= value %> |
+
+ <% end %>
+
+
+
diff --git a/config/routes.rb b/config/routes.rb
index 13cb9cedc..bb7bc8c35 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -374,6 +374,7 @@ Rails.application.routes.draw do
resources :installation_configs, only: [:index, :new, :create, :show, :edit, :update]
resources :agent_bots, only: [:index, :new, :create, :show, :edit, :update]
resources :platform_apps, only: [:index, :new, :create, :show, :edit, :update]
+ resource :instance_status, only: [:show]
# resources that doesn't appear in primary navigation in super admin
resources :account_users, only: [:new, :create, :destroy]
diff --git a/spec/controllers/api_controller_spec.rb b/spec/controllers/api_controller_spec.rb
index b2948e28a..dc8d2ee66 100644
--- a/spec/controllers/api_controller_spec.rb
+++ b/spec/controllers/api_controller_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe 'API Base', type: :request do
get '/api/'
expect(response).to have_http_status(:success)
expect(response.body).to include(Chatwoot.config[:version])
+ expect(response.body).to include('queue_services')
+ expect(response.body).to include('data_services')
end
end
end
diff --git a/spec/controllers/super_admin/instance_statuses_controller_spec.rb b/spec/controllers/super_admin/instance_statuses_controller_spec.rb
new file mode 100644
index 000000000..b2b1237f9
--- /dev/null
+++ b/spec/controllers/super_admin/instance_statuses_controller_spec.rb
@@ -0,0 +1,25 @@
+require 'rails_helper'
+
+RSpec.describe 'Super Admin Instance health', type: :request do
+ let(:super_admin) { create(:super_admin) }
+
+ describe 'GET /super_admin/instance_status' do
+ context 'when it is an unauthenticated super admin' do
+ it 'returns unauthorized' do
+ get '/super_admin/instance_status'
+ expect(response).to have_http_status(:redirect)
+ end
+ end
+
+ context 'when it is an authenticated super admin' do
+ it 'shows the instance_status page' do
+ sign_in(super_admin, scope: :super_admin)
+ get '/super_admin/instance_status'
+ expect(response).to have_http_status(:success)
+ expect(response.body).to include('Chatwoot version')
+ sha = `git rev-parse HEAD`
+ expect(response.body).to include(sha)
+ end
+ end
+ end
+end