mirror of https://github.com/apache/nifi.git
NIFI-4481:
- Adding support for visualizing if a component is scheduled for primary node only. This closes #2210.
This commit is contained in:
parent
b8a3862078
commit
53e63eaf7c
|
@ -16,6 +16,8 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.controller.status;
|
package org.apache.nifi.controller.status;
|
||||||
|
|
||||||
|
import org.apache.nifi.scheduling.ExecutionNode;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -29,6 +31,7 @@ public class ProcessorStatus implements Cloneable {
|
||||||
private String name;
|
private String name;
|
||||||
private String type;
|
private String type;
|
||||||
private RunStatus runStatus;
|
private RunStatus runStatus;
|
||||||
|
private ExecutionNode executionNode;
|
||||||
private int inputCount;
|
private int inputCount;
|
||||||
private long inputBytes;
|
private long inputBytes;
|
||||||
private int outputCount;
|
private int outputCount;
|
||||||
|
@ -90,6 +93,14 @@ public class ProcessorStatus implements Cloneable {
|
||||||
this.runStatus = runStatus;
|
this.runStatus = runStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutionNode getExecutionNode() {
|
||||||
|
return executionNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutionNode(ExecutionNode executionNode) {
|
||||||
|
this.executionNode = executionNode;
|
||||||
|
}
|
||||||
|
|
||||||
public void setInputCount(final int inputCount) {
|
public void setInputCount(final int inputCount) {
|
||||||
this.inputCount = inputCount;
|
this.inputCount = inputCount;
|
||||||
}
|
}
|
||||||
|
@ -244,6 +255,7 @@ public class ProcessorStatus implements Cloneable {
|
||||||
clonedObj.averageLineageDuration = averageLineageDuration;
|
clonedObj.averageLineageDuration = averageLineageDuration;
|
||||||
clonedObj.flowFilesRemoved = flowFilesRemoved;
|
clonedObj.flowFilesRemoved = flowFilesRemoved;
|
||||||
clonedObj.runStatus = runStatus;
|
clonedObj.runStatus = runStatus;
|
||||||
|
clonedObj.executionNode = executionNode;
|
||||||
clonedObj.type = type;
|
clonedObj.type = type;
|
||||||
clonedObj.counters = counters == null ? null : new HashMap<>(counters);
|
clonedObj.counters = counters == null ? null : new HashMap<>(counters);
|
||||||
return clonedObj;
|
return clonedObj;
|
||||||
|
@ -262,6 +274,8 @@ public class ProcessorStatus implements Cloneable {
|
||||||
builder.append(type);
|
builder.append(type);
|
||||||
builder.append(", runStatus=");
|
builder.append(", runStatus=");
|
||||||
builder.append(runStatus);
|
builder.append(runStatus);
|
||||||
|
builder.append(", executionNode=");
|
||||||
|
builder.append(executionNode);
|
||||||
builder.append(", inputCount=");
|
builder.append(", inputCount=");
|
||||||
builder.append(inputCount);
|
builder.append(inputCount);
|
||||||
builder.append(", inputBytes=");
|
builder.append(", inputBytes=");
|
||||||
|
|
|
@ -31,6 +31,7 @@ public class ProcessorStatusSnapshotDTO implements Cloneable {
|
||||||
private String name;
|
private String name;
|
||||||
private String type;
|
private String type;
|
||||||
private String runStatus;
|
private String runStatus;
|
||||||
|
private String executionNode;
|
||||||
|
|
||||||
private Long bytesRead = 0L;
|
private Long bytesRead = 0L;
|
||||||
private Long bytesWritten = 0L;
|
private Long bytesWritten = 0L;
|
||||||
|
@ -103,6 +104,18 @@ public class ProcessorStatusSnapshotDTO implements Cloneable {
|
||||||
this.runStatus = runStatus;
|
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
|
* @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.setType(getType());
|
||||||
|
|
||||||
other.setRunStatus(getRunStatus());
|
other.setRunStatus(getRunStatus());
|
||||||
|
other.setExecutionNode(getExecutionNode());
|
||||||
other.setBytesRead(getBytesRead());
|
other.setBytesRead(getBytesRead());
|
||||||
other.setBytesWritten(getBytesWritten());
|
other.setBytesWritten(getBytesWritten());
|
||||||
other.setFlowFilesIn(getFlowFilesIn());
|
other.setFlowFilesIn(getFlowFilesIn());
|
||||||
|
|
|
@ -2976,6 +2976,7 @@ public class FlowController implements EventAccess, ControllerServiceProvider, R
|
||||||
status.setRunStatus(RunStatus.Stopped);
|
status.setRunStatus(RunStatus.Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status.setExecutionNode(procNode.getExecutionNode());
|
||||||
status.setActiveThreadCount(processScheduler.getActiveThreadCount(procNode));
|
status.setActiveThreadCount(processScheduler.getActiveThreadCount(procNode));
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -1106,6 +1106,7 @@ public final class DtoFactory {
|
||||||
|
|
||||||
// determine the run status
|
// determine the run status
|
||||||
snapshot.setRunStatus(procStatus.getRunStatus().toString());
|
snapshot.setRunStatus(procStatus.getRunStatus().toString());
|
||||||
|
snapshot.setExecutionNode(procStatus.getExecutionNode().toString());
|
||||||
|
|
||||||
snapshot.setActiveThreadCount(procStatus.getActiveThreadCount());
|
snapshot.setActiveThreadCount(procStatus.getActiveThreadCount());
|
||||||
snapshot.setType(procStatus.getType());
|
snapshot.setType(procStatus.getType());
|
||||||
|
|
|
@ -66,7 +66,6 @@ g.component rect.body.unauthorized {
|
||||||
fill: #f4f6f7;
|
fill: #f4f6f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
g.component rect.border {
|
g.component rect.border {
|
||||||
stroke: rgba(0,0,0,0.25);
|
stroke: rgba(0,0,0,0.25);
|
||||||
stroke-width: 1;
|
stroke-width: 1;
|
||||||
|
@ -187,7 +186,7 @@ text.processor-icon {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle.restricted-background {
|
circle.restricted-background, circle.is-primary-background {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
fill: rgba(255, 255, 255, 0.90);
|
fill: rgba(255, 255, 255, 0.90);
|
||||||
}
|
}
|
||||||
|
@ -199,6 +198,12 @@ text.restricted {
|
||||||
fill: #ba554a;
|
fill: #ba554a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
text.is-primary {
|
||||||
|
visibility: hidden;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
text.run-status-icon {
|
text.run-status-icon {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,23 @@ input.search-nodes {
|
||||||
color: #888;
|
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 dialog */
|
||||||
|
|
||||||
#system-diagnostics-refresh-container{
|
#system-diagnostics-refresh-container{
|
||||||
|
|
|
@ -23,9 +23,10 @@
|
||||||
'd3',
|
'd3',
|
||||||
'nf.Common',
|
'nf.Common',
|
||||||
'nf.Client',
|
'nf.Client',
|
||||||
|
'nf.ClusterSummary',
|
||||||
'nf.CanvasUtils'],
|
'nf.CanvasUtils'],
|
||||||
function ($, d3, nfCommon, nfClient, nfCanvasUtils) {
|
function ($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils) {
|
||||||
return (nf.Processor = factory($, d3, nfCommon, nfClient, nfCanvasUtils));
|
return (nf.Processor = factory($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils));
|
||||||
});
|
});
|
||||||
} else if (typeof exports === 'object' && typeof module === 'object') {
|
} else if (typeof exports === 'object' && typeof module === 'object') {
|
||||||
module.exports = (nf.Processor =
|
module.exports = (nf.Processor =
|
||||||
|
@ -33,15 +34,17 @@
|
||||||
require('d3'),
|
require('d3'),
|
||||||
require('nf.Common'),
|
require('nf.Common'),
|
||||||
require('nf.Client'),
|
require('nf.Client'),
|
||||||
|
require('nf.ClusterSummary'),
|
||||||
require('nf.CanvasUtils')));
|
require('nf.CanvasUtils')));
|
||||||
} else {
|
} else {
|
||||||
nf.Processor = factory(root.$,
|
nf.Processor = factory(root.$,
|
||||||
root.d3,
|
root.d3,
|
||||||
root.nf.Common,
|
root.nf.Common,
|
||||||
root.nf.Client,
|
root.nf.Client,
|
||||||
|
root.nf.ClusterSummary,
|
||||||
root.nf.CanvasUtils);
|
root.nf.CanvasUtils);
|
||||||
}
|
}
|
||||||
}(this, function ($, d3, nfCommon, nfClient, nfCanvasUtils) {
|
}(this, function ($, d3, nfCommon, nfClient, nfClusterSummary, nfCanvasUtils) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var nfConnectable;
|
var nfConnectable;
|
||||||
|
@ -181,6 +184,27 @@
|
||||||
})
|
})
|
||||||
.text('\uf132');
|
.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
|
// make processors selectable
|
||||||
processor.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
|
processor.call(nfSelectable.activate).call(nfContextMenu.activate).call(nfQuickSelect.activate);
|
||||||
};
|
};
|
||||||
|
@ -686,11 +710,15 @@
|
||||||
// restricted component indicator
|
// restricted component indicator
|
||||||
processor.select('circle.restricted-background').style('visibility', showRestricted);
|
processor.select('circle.restricted-background').style('visibility', showRestricted);
|
||||||
processor.select('text.restricted').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
|
* @param d
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
@ -700,7 +728,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.component.restricted ? 'visible' : 'hidden';
|
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.
|
* Updates the stats for the processors in the specified selection.
|
||||||
|
|
|
@ -276,6 +276,19 @@
|
||||||
return markup;
|
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
|
// formatter for io
|
||||||
var ioFormatter = function (row, cell, value, columnDef, dataContext) {
|
var ioFormatter = function (row, cell, value, columnDef, dataContext) {
|
||||||
return nfCommon.escapeHtml(dataContext.read) + ' / ' + nfCommon.escapeHtml(dataContext.written);
|
return nfCommon.escapeHtml(dataContext.read) + ' / ' + nfCommon.escapeHtml(dataContext.written);
|
||||||
|
@ -326,9 +339,9 @@
|
||||||
id: 'name',
|
id: 'name',
|
||||||
field: 'name',
|
field: 'name',
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
|
formatter: nameFormatter,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
resizable: true,
|
resizable: true
|
||||||
formatter: nfCommon.genericValueFormatter
|
|
||||||
};
|
};
|
||||||
var runStatusColumn = {
|
var runStatusColumn = {
|
||||||
id: 'runStatus',
|
id: 'runStatus',
|
||||||
|
|
Loading…
Reference in New Issue