use of org.apache.nifi.web.api.dto.status.NodeStatusSnapshotsDTO in project nifi by apache.
the class StatusHistoryEndpointMerger method merge.
@Override
public NodeResponse merge(URI uri, String method, Set<NodeResponse> successfulResponses, Set<NodeResponse> problematicResponses, NodeResponse clientResponse) {
final Map<String, MetricDescriptor<?>> metricDescriptors = getStandardMetricDescriptors(uri);
final StatusHistoryEntity responseEntity = clientResponse.getClientResponse().readEntity(StatusHistoryEntity.class);
final Set<StatusDescriptorDTO> fieldDescriptors = new LinkedHashSet<>();
boolean includeCounters = true;
StatusHistoryDTO lastStatusHistory = null;
final List<NodeStatusSnapshotsDTO> nodeStatusSnapshots = new ArrayList<>(successfulResponses.size());
LinkedHashMap<String, String> noReadPermissionsComponentDetails = null;
for (final NodeResponse nodeResponse : successfulResponses) {
final StatusHistoryEntity nodeResponseEntity = nodeResponse == clientResponse ? responseEntity : nodeResponse.getClientResponse().readEntity(StatusHistoryEntity.class);
final StatusHistoryDTO nodeStatus = nodeResponseEntity.getStatusHistory();
lastStatusHistory = nodeStatus;
if (noReadPermissionsComponentDetails == null && !nodeResponseEntity.getCanRead()) {
// If component details from a history with no read permissions is encountered for the first time, hold on to them to be used in the merged response
noReadPermissionsComponentDetails = nodeStatus.getComponentDetails();
}
if (!Boolean.TRUE.equals(nodeResponseEntity.getCanRead())) {
includeCounters = false;
}
final NodeIdentifier nodeId = nodeResponse.getNodeId();
final NodeStatusSnapshotsDTO nodeStatusSnapshot = new NodeStatusSnapshotsDTO();
nodeStatusSnapshot.setNodeId(nodeId.getId());
nodeStatusSnapshot.setAddress(nodeId.getApiAddress());
nodeStatusSnapshot.setApiPort(nodeId.getApiPort());
nodeStatusSnapshot.setStatusSnapshots(nodeStatus.getAggregateSnapshots());
nodeStatusSnapshots.add(nodeStatusSnapshot);
final List<StatusDescriptorDTO> descriptors = nodeStatus.getFieldDescriptors();
if (descriptors != null) {
fieldDescriptors.addAll(descriptors);
}
}
// the user is not authorized, we want to assume that the user is, in fact, not authorized.
if (includeCounters) {
for (final StatusDescriptorDTO descriptorDto : fieldDescriptors) {
final String fieldName = descriptorDto.getField();
if (!metricDescriptors.containsKey(fieldName)) {
final ValueMapper<ProcessorStatus> valueMapper = s -> {
final Map<String, Long> counters = s.getCounters();
if (counters == null) {
return 0L;
}
return counters.getOrDefault(descriptorDto.getField(), 0L);
};
final MetricDescriptor<ProcessorStatus> metricDescriptor = new StandardMetricDescriptor<>(descriptorDto.getField(), descriptorDto.getLabel(), descriptorDto.getDescription(), Formatter.COUNT, valueMapper);
metricDescriptors.put(fieldName, metricDescriptor);
}
}
}
final StatusHistoryDTO clusterStatusHistory = new StatusHistoryDTO();
clusterStatusHistory.setAggregateSnapshots(mergeStatusHistories(nodeStatusSnapshots, metricDescriptors));
clusterStatusHistory.setGenerated(new Date());
clusterStatusHistory.setNodeSnapshots(nodeStatusSnapshots);
if (lastStatusHistory != null) {
clusterStatusHistory.setComponentDetails(noReadPermissionsComponentDetails == null ? lastStatusHistory.getComponentDetails() : noReadPermissionsComponentDetails);
}
clusterStatusHistory.setFieldDescriptors(new ArrayList<>(fieldDescriptors));
final StatusHistoryEntity clusterEntity = new StatusHistoryEntity();
clusterEntity.setStatusHistory(clusterStatusHistory);
clusterEntity.setCanRead(noReadPermissionsComponentDetails == null);
return new NodeResponse(clientResponse, clusterEntity);
}
use of org.apache.nifi.web.api.dto.status.NodeStatusSnapshotsDTO in project nifi by apache.
the class StatusHistoryEndpointMerger method mergeStatusHistories.
private List<StatusSnapshotDTO> mergeStatusHistories(final List<NodeStatusSnapshotsDTO> nodeStatusSnapshots, final Map<String, MetricDescriptor<?>> metricDescriptors) {
// We want a Map<Date, List<StatusSnapshot>>, which is a Map of "normalized Date" (i.e., a time range, essentially)
// to all Snapshots for that time. The list will contain one snapshot for each node. However, we can have the case
// where the NCM has a different value for the componentStatusSnapshotMillis than the nodes have. In this case,
// we end up with multiple entries in the List<StatusSnapshot> for the same node/timestamp, which skews our aggregate
// results. In order to avoid this, we will use only the latest snapshot for a node that falls into the the time range
// of interest.
// To accomplish this, we have an intermediate data structure, which is a Map of "normalized Date" to an inner Map
// of Node Identifier to StatusSnapshot. We then will flatten this Map and aggregate the results.
final Map<Date, Map<String, StatusSnapshot>> dateToNodeSnapshots = new TreeMap<>();
// group status snapshot's for each node by date
for (final NodeStatusSnapshotsDTO nodeStatusSnapshot : nodeStatusSnapshots) {
for (final StatusSnapshotDTO snapshotDto : nodeStatusSnapshot.getStatusSnapshots()) {
final StatusSnapshot snapshot = createSnapshot(snapshotDto, metricDescriptors);
final Date normalizedDate = normalizeStatusSnapshotDate(snapshot.getTimestamp(), componentStatusSnapshotMillis);
Map<String, StatusSnapshot> nodeToSnapshotMap = dateToNodeSnapshots.get(normalizedDate);
if (nodeToSnapshotMap == null) {
nodeToSnapshotMap = new HashMap<>();
dateToNodeSnapshots.put(normalizedDate, nodeToSnapshotMap);
}
nodeToSnapshotMap.put(nodeStatusSnapshot.getNodeId(), snapshot);
}
}
// aggregate the snapshots by (normalized) timestamp
final Map<Date, List<StatusSnapshot>> snapshotsToAggregate = new TreeMap<>();
for (final Map.Entry<Date, Map<String, StatusSnapshot>> entry : dateToNodeSnapshots.entrySet()) {
final Date normalizedDate = entry.getKey();
final Map<String, StatusSnapshot> nodeToSnapshot = entry.getValue();
final List<StatusSnapshot> snapshotsForTimestamp = new ArrayList<>(nodeToSnapshot.values());
snapshotsToAggregate.put(normalizedDate, snapshotsForTimestamp);
}
final List<StatusSnapshotDTO> aggregatedSnapshots = aggregate(snapshotsToAggregate);
return aggregatedSnapshots;
}
Aggregations