Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-11781. Add last task status information to Recon UI #7472

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ private void createReconTaskStatusTable(Connection conn) {
.column("task_name", SQLDataType.VARCHAR(766).nullable(false))
.column("last_updated_timestamp", SQLDataType.BIGINT)
.column("last_updated_seq_number", SQLDataType.BIGINT)
.column("last_task_successful", SQLDataType.BIT)
.constraint(DSL.constraint("pk_task_name")
.primaryKey("task_name"))
.execute();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ private void register() {
String taskName = getTaskName();
if (!reconTaskStatusDao.existsById(taskName)) {
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(
taskName, 0L, 0L);
taskName, 0L, 0L, null);
reconTaskStatusDao.insert(reconTaskStatusRecord);
LOG.info("Registered {} task ", taskName);
}
Expand Down Expand Up @@ -89,7 +89,7 @@ public boolean isRunning() {

protected void recordSingleRunCompletion() {
reconTaskStatusDao.update(new ReconTaskStatus(getTaskName(),
System.currentTimeMillis(), 0L));
System.currentTimeMillis(), 0L, true));
}

protected boolean canRun() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public OzoneManagerServiceProviderImpl(
public void registerOMDBTasks() {
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(
OmSnapshotTaskName.OmDeltaRequest.name(),
System.currentTimeMillis(), getCurrentOMDBSequenceNumber());
System.currentTimeMillis(), getCurrentOMDBSequenceNumber(), null);
if (!reconTaskStatusDao.existsById(
OmSnapshotTaskName.OmDeltaRequest.name())) {
reconTaskStatusDao.insert(reconTaskStatusRecord);
Expand All @@ -240,7 +240,7 @@ public void registerOMDBTasks() {

reconTaskStatusRecord = new ReconTaskStatus(
OmSnapshotTaskName.OmSnapshotRequest.name(),
System.currentTimeMillis(), getCurrentOMDBSequenceNumber());
System.currentTimeMillis(), getCurrentOMDBSequenceNumber(), null);
if (!reconTaskStatusDao.existsById(
OmSnapshotTaskName.OmSnapshotRequest.name())) {
reconTaskStatusDao.insert(reconTaskStatusRecord);
Expand Down Expand Up @@ -571,45 +571,49 @@ public boolean syncDataFromOM() {
if (currentSequenceNumber <= 0) {
fullSnapshot = true;
} else {
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(
OmSnapshotTaskName.OmDeltaRequest.name(),
System.currentTimeMillis(), getCurrentOMDBSequenceNumber(), null);

try (OMDBUpdatesHandler omdbUpdatesHandler =
new OMDBUpdatesHandler(omMetadataManager)) {
LOG.info("Obtaining delta updates from Ozone Manager");
// Get updates from OM and apply to local Recon OM DB.
getAndApplyDeltaUpdatesFromOM(currentSequenceNumber,
omdbUpdatesHandler);
// Update timestamp of successful delta updates query.
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(
OmSnapshotTaskName.OmDeltaRequest.name(),
System.currentTimeMillis(), getCurrentOMDBSequenceNumber());
reconTaskStatusDao.update(reconTaskStatusRecord);

reconTaskStatusRecord.setLastUpdatedTimestamp(System.currentTimeMillis());
// Pass on DB update events to tasks that are listening.
reconTaskController.consumeOMEvents(new OMUpdateEventBatch(
omdbUpdatesHandler.getEvents()), omMetadataManager);
reconTaskStatusRecord.setLastTaskSuccessful(true);
} catch (InterruptedException intEx) {
reconTaskStatusRecord.setLastTaskSuccessful(false);
Thread.currentThread().interrupt();
} catch (Exception e) {
metrics.incrNumDeltaRequestsFailed();
LOG.warn("Unable to get and apply delta updates from OM.",
e.getMessage());
reconTaskStatusRecord.setLastTaskSuccessful(true);
fullSnapshot = true;
}
reconTaskStatusDao.update(reconTaskStatusRecord);
}

if (fullSnapshot) {
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(
OmSnapshotTaskName.OmSnapshotRequest.name(),
System.currentTimeMillis(),
getCurrentOMDBSequenceNumber(), null);

try {
metrics.incrNumSnapshotRequests();
LOG.info("Obtaining full snapshot from Ozone Manager");
// Update local Recon OM DB to new snapshot.
boolean success = updateReconOmDBWithNewSnapshot();
// Update timestamp of successful delta updates query.
if (success) {
ReconTaskStatus reconTaskStatusRecord =
new ReconTaskStatus(
OmSnapshotTaskName.OmSnapshotRequest.name(),
System.currentTimeMillis(),
getCurrentOMDBSequenceNumber());
reconTaskStatusDao.update(reconTaskStatusRecord);
reconTaskStatusRecord.setLastUpdatedTimestamp(System.currentTimeMillis());

// Reinitialize tasks that are listening.
LOG.info("Calling reprocess on Recon tasks.");
Expand All @@ -618,21 +622,26 @@ public boolean syncDataFromOM() {
// Update health status in ReconContext
reconContext.updateHealthStatus(new AtomicBoolean(true));
reconContext.getErrors().remove(ReconContext.ErrorCode.GET_OM_DB_SNAPSHOT_FAILED);
reconTaskStatusRecord.setLastTaskSuccessful(true);
} else {
metrics.incrNumSnapshotRequestsFailed();
// Update health status in ReconContext
reconContext.updateHealthStatus(new AtomicBoolean(false));
reconContext.updateErrors(ReconContext.ErrorCode.GET_OM_DB_SNAPSHOT_FAILED);
reconTaskStatusRecord.setLastTaskSuccessful(false);
}
} catch (InterruptedException intEx) {
reconTaskStatusRecord.setLastTaskSuccessful(false);
Thread.currentThread().interrupt();
} catch (Exception e) {
metrics.incrNumSnapshotRequestsFailed();
reconTaskStatusRecord.setLastTaskSuccessful(false);
LOG.error("Unable to update Recon's metadata with new OM DB. ", e);
// Update health status in ReconContext
reconContext.updateHealthStatus(new AtomicBoolean(false));
reconContext.updateErrors(ReconContext.ErrorCode.GET_OM_DB_SNAPSHOT_FAILED);
}
reconTaskStatusDao.update(reconTaskStatusRecord);
}
printOMDBMetaInfo();
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public void registerTask(ReconOmTask task) {
taskFailureCounter.put(taskName, new AtomicInteger(0));
// Create DB record for the task.
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(taskName,
0L, 0L);
0L, 0L, null);
if (!reconTaskStatusDao.existsById(taskName)) {
reconTaskStatusDao.insert(reconTaskStatusRecord);
}
Expand Down Expand Up @@ -179,15 +179,18 @@ public synchronized void reInitializeTasks(
executorService.invokeAll(tasks);
for (Future<Pair<String, Boolean>> f : results) {
String taskName = f.get().getLeft();
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(taskName,
System.currentTimeMillis(),
omMetadataManager.getLastSequenceNumberFromDB(), null);

if (!f.get().getRight()) {
LOG.info("Init failed for task {}.", taskName);
reconTaskStatusRecord.setLastTaskSuccessful(false);
} else {
//store the timestamp for the task
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(taskName,
System.currentTimeMillis(),
omMetadataManager.getLastSequenceNumberFromDB());
reconTaskStatusDao.update(reconTaskStatusRecord);
reconTaskStatusRecord.setLastTaskSuccessful(true);
}
reconTaskStatusDao.update(reconTaskStatusRecord);
}
} catch (ExecutionException e) {
LOG.error("Unexpected error : ", e);
Expand All @@ -199,11 +202,12 @@ public synchronized void reInitializeTasks(
* for that task.
* @param taskName taskname to be updated.
* @param lastSequenceNumber contains the new sequence number.
* @param lastTaskSuccessful contains if the last run of the task was successful
*/
private void storeLastCompletedTransaction(
String taskName, long lastSequenceNumber) {
String taskName, long lastSequenceNumber, boolean lastTaskSuccessful) {
ReconTaskStatus reconTaskStatusRecord = new ReconTaskStatus(taskName,
System.currentTimeMillis(), lastSequenceNumber);
System.currentTimeMillis(), lastSequenceNumber, lastTaskSuccessful);
reconTaskStatusDao.update(reconTaskStatusRecord);
}

Expand Down Expand Up @@ -251,9 +255,10 @@ private List<String> processTaskResults(List<Future<Pair<String, Boolean>>>
if (!f.get().getRight()) {
LOG.info("Failed task : {}", taskName);
failedTasks.add(f.get().getLeft());
storeLastCompletedTransaction(taskName, events.getLastSequenceNumber(), false);
} else {
taskFailureCounter.get(taskName).set(0);
storeLastCompletedTransaction(taskName, events.getLastSequenceNumber());
storeLastCompletedTransaction(taskName, events.getLastSequenceNumber(), true);
}
}
return failedTasks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1870,43 +1870,57 @@
"taskStatus": [
{
"taskName": "ContainerKeyMapperTask",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0
"lastUpdatedTimestamp": 1732273536690,
"lastUpdatedSeqNumber": 2,
"lastTaskSuccessful": true
},
{
"taskName": "FileSizeCountTask",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0
"lastUpdatedTimestamp": 1732273536690,
"lastUpdatedSeqNumber": 2,
"lastTaskSuccessful": true
},
{
"taskName": "TableCountTask",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0
"taskName": "OmTableInsightTask",
"lastUpdatedTimestamp": 1732273536679,
"lastUpdatedSeqNumber": 2,
"lastTaskSuccessful": true
},
{
"taskName": "NSSummaryTaskWithFSO",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0
"taskName": "NSSummaryTask",
"lastUpdatedTimestamp": 1732273536688,
"lastUpdatedSeqNumber": 2,
"lastTaskSuccessful": true
},
{
"taskName": "OmDeltaRequest",
"lastUpdatedTimestamp": 1663421088035,
"lastUpdatedSeqNumber": 0
"lastUpdatedTimestamp": 1732296401979,
"lastUpdatedSeqNumber": 2,
"lastTaskSuccessful": true
},
{
"taskName": "OmSnapshotRequest",
"lastUpdatedTimestamp": 1663421088035,
"lastUpdatedSeqNumber": 0
"lastUpdatedTimestamp": 1732273536596,
"lastUpdatedSeqNumber": 0,
"lastTaskSuccessful": true
},
{
"taskName": "ContainerHealthTask",
"taskName": "ContainerSizeCountTask",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0
"lastUpdatedSeqNumber": 0,
"lastTaskSuccessful": null
},
{
"taskName": "PipelineSyncTask",
"lastUpdatedTimestamp": 1663421094507,
"lastUpdatedSeqNumber": 0
"lastUpdatedTimestamp": 1732296438676,
"lastUpdatedSeqNumber": 0,
"lastTaskSuccessful": true
},
{
"taskName": "ContainerHealthTask",
"lastUpdatedTimestamp": 0,
"lastUpdatedSeqNumber": 0,
"lastTaskSuccessful": null
}
],
"unhealthyContainers": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { TaskStatus, TaskStatusResponse } from '@/v2/types/overview.types';
import { BellOutlined, CheckCircleFilled, CloseCircleFilled, WarningFilled } from '@ant-design/icons';
import { Badge, Button, Dropdown, Menu } from 'antd';
import React, { useEffect } from 'react';

//----------Types---------//
type TaskAlertDropdownProps = {
data: TaskStatusResponse;
failedTasks: number;
notStartedTasks: number
}

const TaskAlertDropdown: React.FC<TaskAlertDropdownProps> = ({ data, failedTasks, notStartedTasks }) => {

function getTaskIcon(task: TaskStatus) {
if (task.lastTaskSuccessful === null) {
return <WarningFilled style={{ color: '#E49F00' }} />;
}
if (!task.lastTaskSuccessful) {
return <CloseCircleFilled style={{ color: '#ff595e' }} />;
}
return <CheckCircleFilled style={{ color: '#1AA57A' }} />;
}

function generateMenu(tasks: TaskStatusResponse) {
return <Menu style={{ display: 'table' }}>
{...tasks.map(task => (
<Menu.Item>
{
getTaskIcon(task)
}
{ task.taskName }
</Menu.Item>
))}
</Menu>
}

return (
<Dropdown overlay={generateMenu(data)} trigger={['click']}>
<Badge count={
failedTasks >= notStartedTasks
? failedTasks
: notStartedTasks
} style={{ backgroundColor:
failedTasks >= notStartedTasks
? '#FF595E'
: '#E49F00'
}}>
<BellOutlined style={{ fontSize: '20px' }}/>
</Badge>
</Dropdown>
);
}

export default TaskAlertDropdown;
Loading