Commit 642fc9cb authored by Stan Hu's avatar Stan Hu

Show Geo event log and cursor data in node status page

parent f0deea60
/* eslint-disable no-new*/
import './smart_interval';
import './lib/utils/datetime_utility';
const healthyClass = 'geo-node-healthy';
const unhealthyClass = 'geo-node-unhealthy';
......@@ -20,6 +21,8 @@ class GeoNodeStatus {
this.$repositoriesFailed = $('.js-repositories-failed', this.$status);
this.$lfsObjectsSynced = $('.js-lfs-objects-synced', this.$status);
this.$attachmentsSynced = $('.js-attachments-synced', this.$status);
this.$lastEventSeen = $('.js-last-event-seen', this.$status);
this.$lastCursorEvent = $('.js-last-cursor-event', this.$status);
this.$health = $('.js-health', this.$status);
this.endpoint = this.$el.data('status-url');
......@@ -50,6 +53,10 @@ class GeoNodeStatus {
this.$repositoriesFailed.html(status.repositories_failed_count);
this.$lfsObjectsSynced.html(`${status.lfs_objects_synced_count}/${status.lfs_objects_count} (${status.lfs_objects_synced_in_percentage})`);
this.$attachmentsSynced.html(`${status.attachments_synced_count}/${status.attachments_count} (${status.attachments_synced_in_percentage})`);
const eventDate = gl.utils.formatDate(new Date(status.last_event_date));
const cursorDate = gl.utils.formatDate(new Date(status.cursor_last_event_date));
this.$lastEventSeen.html(`${status.last_event_id} (${eventDate})`);
this.$lastCursorEvent.html(`${status.cursor_last_event_id} (${cursorDate})`);
if (status.health === 'Healthy') {
this.$health.html('');
} else {
......
......@@ -18,6 +18,10 @@ module Geo
class_name: 'Geo::RepositoriesChangedEvent',
foreign_key: :repositories_changed_event_id
def self.latest_event
order(id: :desc).first
end
def event
repository_updated_event ||
repository_deleted_event ||
......
......@@ -21,6 +21,42 @@ class GeoNodeStatus
def db_replication_lag=(value)
@db_replication_lag = value
end
def last_event_id
@last_event_id ||= latest_event&.id
end
def last_event_id=(value)
@last_event_id = value
end
def last_event_date
@last_event_date ||= Geo::EventLog.latest_event&.created_at
end
def last_event_date=(value)
@last_event_date = value
end
def cursor_last_event_id
@cursor_last_event_id ||= cursor_last_processed&.event_id
end
def cursor_last_event_id=(value)
@cursor_last_event_id = value
end
def cursor_last_event_date
event_id = cursor_last_event_id
return unless event_id
@cursor_last_event_date ||= Geo::EventLog.find_by(id: event_id)&.created_at
end
def cursor_last_event_date=(value)
@cursor_last_event_date = value
end
def repositories_count
@repositories_count ||= repositories.count
......@@ -126,4 +162,12 @@ class GeoNodeStatus
def repositories
@repositories ||= Gitlab::Geo.current_node.projects
end
def latest_event
Geo::EventLog.latest_event
end
def cursor_last_processed
Geo::EventLogState.last_processed
end
end
......@@ -28,4 +28,9 @@ class GeoNodeStatusEntity < Grape::Entity
expose :repositories_synced_in_percentage do |node|
number_to_percentage(node.repositories_synced_in_percentage, precision: 2)
end
expose :last_event_id
expose :last_event_date
expose :cursor_last_event_id
expose :cursor_last_event_date
end
......@@ -13,6 +13,10 @@ module Geo
lfs_objects_synced_count
attachments_count
attachments_synced_count
last_event_id
last_event_date
cursor_last_event_id
cursor_last_event_date
).freeze
def call(geo_node)
......
......@@ -65,6 +65,13 @@
%span.help-block
Attachments synced:
%strong.node-info.js-attachments-synced
%p
%span.help-block
Last event ID seen from primary:
%strong.node-info.js-last-event-seen
%span.help-block
Last event ID processed by cursor:
%strong.node-info.js-last-cursor-event
%p
.js-health
......
---
title: Show Geo event log and cursor data in node status page
merge_request:
author:
type: changed
......@@ -957,6 +957,10 @@ module API
expose :lfs_objects_synced_count
expose :attachments_count
expose :attachments_synced_count
expose :last_event_id
expose :last_event_date
expose :cursor_last_event_id
expose :cursor_last_event_date
end
class PersonalAccessToken < Grape::Entity
......
......@@ -267,7 +267,11 @@ describe Admin::GeoNodesController, :postgresql do
lfs_objects_synced_count: 123,
repositories_count: 10,
repositories_synced_count: 5,
repositories_failed_count: 0
repositories_failed_count: 0,
last_event_id: 2,
last_event_date: Time.now.iso8601,
cursor_last_event_id: 1,
cursor_last_event_date: Time.now.iso8601
)
end
......
......@@ -11,7 +11,11 @@
"db_replication_lag",
"repositories_count",
"repositories_failed_count",
"repositories_synced_count"
"repositories_synced_count",
"last_event_id",
"last_event_date",
"cursor_last_event_id",
"cursor_last_event_date"
],
"properties" : {
"id": { "type": "integer" },
......@@ -27,7 +31,11 @@
"repositories_count": { "type": "integer" },
"repositories_failed_count": { "type": "integer" },
"repositories_synced_count": { "type": "integer" },
"repositories_synced_in_percentage": { "type": "string" }
"repositories_synced_in_percentage": { "type": "string" },
"last_event_id": { "type": ["integer", "null"] },
"last_event_date": { "type": ["string", "null"] },
"cursor_last_event_id": { "type": ["integer", "null"] },
"cursor_last_event_date": { "type": ["string", "null"] }
},
"additionalProperties": false
}
......@@ -170,6 +170,34 @@ describe GeoNodeStatus do
end
end
describe '#last_event_id and #last_event_date' do
it 'returns nil when no events are available' do
expect(subject.last_event_id).to be_nil
expect(subject.last_event_date).to be_nil
end
it 'returns the latest event' do
created_at = Date.new(2017, 10, 22)
event = create(:geo_event_log, created_at: created_at)
expect(subject.last_event_id).to eq(event.id)
expect(subject.last_event_date).to eq(created_at)
end
end
describe '#cursor_last_event_id and #cursor_last_event_date' do
it 'returns nil when no events are available' do
expect(subject.cursor_last_event_id).to be_nil
expect(subject.cursor_last_event_date).to be_nil
end
it 'returns the latest event ID' do
event = create(:geo_event_log_state)
expect(subject.cursor_last_event_id).to eq(event.event_id)
end
end
context 'when no values are available' do
it 'returns 0 for each attribute' do
allow(Gitlab::Geo::HealthCheck).to receive(:db_replication_lag).and_return(nil)
......@@ -180,6 +208,10 @@ describe GeoNodeStatus do
subject.repositories_count = nil
subject.repositories_synced_count = nil
subject.repositories_failed_count = nil
subject.last_event_id = nil
subject.last_event_date = nil
subject.cursor_last_event_id = nil
subject.cursor_last_event_date = nil
expect(subject.db_replication_lag).to be_nil
expect(subject.repositories_count).to be_zero
......@@ -192,6 +224,10 @@ describe GeoNodeStatus do
expect(subject.attachments_count).to be_zero
expect(subject.attachments_synced_count).to be_zero
expect(subject.attachments_synced_in_percentage).to be_zero
expect(subject.last_event_id).to be_nil
expect(subject.last_event_date).to be_nil
expect(subject.cursor_last_event_id).to be_nil
expect(subject.cursor_last_event_date).to be_nil
end
end
end
......@@ -32,7 +32,11 @@ describe Geo::NodeStatusService do
lfs_objects_count: 100,
lfs_objects_synced_count: 50,
attachments_count: 30,
attachments_synced_count: 30 }
attachments_synced_count: 30,
last_event_id: 2,
last_event_date: Time.now,
cursor_last_event_id: 1,
cursor_last_event_date: Time.now }
request = double(success?: true, parsed_response: data.stringify_keys, code: 200)
allow(described_class).to receive(:get).and_return(request)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment