NIFI-4481:

- Adding support for visualizing if a component is scheduled for primary node only.
This closes #2210.
This commit is contained in:
Matt Gilman 2017-10-12 13:58:50 -04:00 committed by Mark Payne
parent b8a3862078
commit 53e63eaf7c
8 changed files with 111 additions and 9 deletions

View File

@ -16,6 +16,8 @@
*/
package org.apache.nifi.controller.status;
import org.apache.nifi.scheduling.ExecutionNode;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -29,6 +31,7 @@ public class ProcessorStatus implements Cloneable {
private String name;
private String type;
private RunStatus runStatus;
private ExecutionNode executionNode;
private int inputCount;
private long inputBytes;
private int outputCount;
@ -90,6 +93,14 @@ public class ProcessorStatus implements Cloneable {
this.runStatus = runStatus;
}
public ExecutionNode getExecutionNode() {
return executionNode;
}
public void setExecutionNode(ExecutionNode executionNode) {
this.executionNode = executionNode;
}
public void setInputCount(final int inputCount) {
this.inputCount = inputCount;
}
@ -244,6 +255,7 @@ public class ProcessorStatus implements Cloneable {
clonedObj.averageLineageDuration = averageLineageDuration;
clonedObj.flowFilesRemoved = flowFilesRemoved;
clonedObj.runStatus = runStatus;
clonedObj.executionNode = executionNode;
clonedObj.type = type;
clonedObj.counters = counters == null ? null : new HashMap<>(counters);
return clonedObj;
@ -262,6 +274,8 @@ public class ProcessorStatus implements Cloneable {
builder.append(type);
builder.append(", runStatus=");
builder.append(runStatus);
builder.append(", executionNode=");
builder.append(executionNode);
builder.append(", inputCount=");
builder.append(inputCount);
builder.append(", inputBytes=");

View File

@ -31,6 +31,7 @@ public class ProcessorStatusSnapshotDTO implements Cloneable {
private String name;
private String type;
private String runStatus;
private String executionNode;
private Long bytesRead = 0L;
private Long bytesWritten = 0L;
@ -103,6 +104,18 @@ public class ProcessorStatusSnapshotDTO implements Cloneable {
this.runStatus = runStatus;
}
@ApiModelProperty(
value = "Indicates the node where the process will execute.",
allowableValues = "ALL, PRIMARY"
)
public String getExecutionNode() {
return executionNode;
}
public void setExecutionNode(String executionNode) {
this.executionNode = executionNode;
}
/**
* @return The total count and size of flow files that have been accepted in the last five minutes
*/
@ -280,6 +293,7 @@ public class ProcessorStatusSnapshotDTO implements Cloneable {
other.setType(getType());
other.setRunStatus(getRunStatus());
other.setExecutionNode(getExecutionNode());
other.setBytesRead(getBytesRead());
other.setBytesWritten(getBytesWritten());
other.setFlowFilesIn(getFlowFilesIn());

View File

@ -2976,6 +2976,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
status.setRunStatus(RunStatus.Stopped);
}
status.setExecutionNode(procNode.getExecutionNode());
status.setActiveThreadCount(processScheduler.getActiveThreadCount(procNode));
return status;

View File

@ -1106,6 +1106,7 @@ public final class DtoFactory {
// determine the run status
snapshot.setRunStatus(procStatus.getRunStatus().toString());
snapshot.setExecutionNode(procStatus.getExecutionNode().toString());
snapshot.setActiveThreadCount(procStatus.getActiveThreadCount());
snapshot.setType(procStatus.getType());

View File

@ -66,7 +66,6 @@ g.component rect.body.unauthorized {
fill: #f4f6f7;
}
g.component rect.border {
stroke: rgba(0,0,0,0.25);
stroke-width: 1;
@ -187,7 +186,7 @@ text.processor-icon {
font-size: 30px;
}
circle.restricted-background {
circle.restricted-background, circle.is-primary-background {
visibility: hidden;
fill: rgba(255, 255, 255, 0.90);
}
@ -199,6 +198,12 @@ text.restricted {
fill: #ba554a;
}
text.is-primary {
visibility: hidden;
font-size: 12px;
font-weight: bold;
}
text.run-status-icon {
font-size: 13px;
}

View File

@ -103,6 +103,23 @@ input.search-nodes {
color: #888;
}
div.is-primary-icon {
color: #000;
font-family: Roboto;
font-size: 10px;
font-weight: bold;
line-height: 14px;
width: 14px;
height: 14px;
background-color: rgba(255, 255, 255, 0.9);
border: 1px solid #aaa;
border-radius: 7px;
margin-right: 3px;
margin-top: 3px;
float: left;
text-align: center;
}
/* system diagnostics dialog */
#system-diagnostics-refresh-container{

View File

@ -23,9 +23,10 @@
'd3',
'nf.Common',
'nf.Client',
'nf.ClusterSummary',
'nf.CanvasUtils'],
function ($, d3, nfCommon, nfClient, nfCanvasUtils) {
return (nf.Processor = factory($, d3, nfCommon, nfClient, nfCanvasUtils));
function ($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils) {
return (nf.Processor = factory($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils));
});
} else if (typeof exports === 'object' && typeof module === 'object') {
module.exports = (nf.Processor =
@ -33,15 +34,17 @@
require('d3'),
require('nf.Common'),
require('nf.Client'),
require('nf.ClusterSummary'),
require('nf.CanvasUtils')));
} else {
nf.Processor = factory(root.$,
root.d3,
root.nf.Common,
root.nf.Client,
root.nf.ClusterSummary,
root.nf.CanvasUtils);
}
}(this, function ($, d3, nfCommon, nfClient, nfCanvasUtils) {
}(this, function ($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils) {
'use strict';
var nfConnectable;
@ -181,6 +184,27 @@
})
.text('\uf132');
// is primary icon background
processor.append('circle')
.attr({
'r': 9,
'cx': 38,
'cy': 36,
'class': 'is-primary-background'
});
// is primary icon
processor.append('text')
.attr({
'x': 34.75,
'y': 40,
'class': 'is-primary'
})
.text('P')
.append('title').text(function (d) {
return 'This component is only scheduled to execute on the Primary Node';
});
// make processors selectable
processor.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
};
@ -686,11 +710,15 @@
// restricted component indicator
processor.select('circle.restricted-background').style('visibility', showRestricted);
processor.select('text.restricted').style('visibility', showRestricted);
// is primary component indicator
processor.select('circle.is-primary-background').style('visibility', showIsPrimary);
processor.select('text.is-primary').style('visibility', showIsPrimary);
});
};
/**
* Returns whether the resticted indicator should be shown for a given
* Returns whether the resticted indicator should be shown for a given component
* @param d
* @returns {*}
*/
@ -700,7 +728,16 @@
}
return d.component.restricted ? 'visible' : 'hidden';
}
};
/**
* Returns whether the is primary indicator should be shown for a given component
* @param d
* @returns {*}
*/
var showIsPrimary = function (d) {
return nfClusterSummary.isClustered() && d.status.aggregateSnapshot.executionNode === 'PRIMARY' ? 'visible' : 'hidden';
};
/**
* Updates the stats for the processors in the specified selection.

View File

@ -276,6 +276,19 @@
return markup;
};
// formatter for name
var nameFormatter = function (row, cell, value, columnDef, dataContext) {
var markup = '';
if (isClustered && dataContext.executionNode === 'PRIMARY') {
markup += '<div class="is-primary-icon" title="This component is only scheduled to execute on the Primary Node">P</div>';
}
markup += nfCommon.escapeHtml(value);
return markup;
};
// formatter for io
var ioFormatter = function (row, cell, value, columnDef, dataContext) {
return nfCommon.escapeHtml(dataContext.read) + ' / ' + nfCommon.escapeHtml(dataContext.written);
@ -326,9 +339,9 @@
id: 'name',
field: 'name',
name: 'Name',
formatter: nameFormatter,
sortable: true,
resizable: true,
formatter: nfCommon.genericValueFormatter
resizable: true
};
var runStatusColumn = {
id: 'runStatus',