com.datorama.oss.timbermill.ParentResolver Maven / Gradle / Ivy
package com.datorama.oss.timbermill;
import com.datorama.oss.timbermill.common.cache.AbstractCacheHandler;
import com.datorama.oss.timbermill.unit.Event;
import com.datorama.oss.timbermill.unit.LocalTask;
import com.datorama.oss.timbermill.unit.Task;
import com.datorama.oss.timbermill.unit.TaskStatus;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;
import static com.datorama.oss.timbermill.ElasticsearchClient.GSON;
class ParentResolver {
private static final Logger LOG = LoggerFactory.getLogger(ParentResolver.class);
private Map receivedTasksMap;
private AbstractCacheHandler cacheHandler;
ParentResolver(Map receivedTasksMap, AbstractCacheHandler cacheHandler) {
this.receivedTasksMap = receivedTasksMap;
this.cacheHandler = cacheHandler;
}
Map resolveOrphansReceived() {
return resolveOrphans(receivedTasksMap);
}
private Map resolveOrphans(Map potentialAdoptingTasks) {
Set adoptingCandidates = potentialAdoptingTasks.entrySet().stream().filter(entry -> {
Task parentIndexedTask = entry.getValue();
boolean isParentStartedTask = parentIndexedTask.getStatus() == TaskStatus.UNTERMINATED || parentIndexedTask.getStatus() == TaskStatus.SUCCESS || parentIndexedTask.getStatus() == TaskStatus.ERROR;
boolean isParentNotOrphan = parentIndexedTask.isOrphan() == null || !parentIndexedTask.isOrphan();
return isParentStartedTask && isParentNotOrphan;
}).map(Map.Entry::getKey).collect(Collectors.toSet());
Map orphansMap = findAdoptedOrphansInCache(adoptingCandidates);
return getEnrichedAdoptedOrphans(potentialAdoptingTasks, orphansMap);
}
private Map resolveOrphansWithAdoptedOrphans(Map potentialAdoptingTasks) {
Set adoptingCandidates = potentialAdoptingTasks.keySet();
Map orphansMap = findAdoptedOrphans(adoptingCandidates);
return getEnrichedAdoptedOrphans(potentialAdoptingTasks, orphansMap);
}
private Map getEnrichedAdoptedOrphans(Map potentialAdoptingTasks, Map orphansMap) {
Map adoptedTasksMap = Maps.newHashMap();
for (Map.Entry entry : orphansMap.entrySet()) {
String adoptedId = entry.getKey();
Task adoptedTask = entry.getValue();
if (adoptedTask == null) {
LOG.warn("Missing adopted task from cache {}", adoptedId);
} else {
adoptedTask.setOrphan(false);
populateParentParamsFromAdoptedTask(adoptedTask, potentialAdoptingTasks.get(adoptedTask.getParentId()));
adoptedTasksMap.put(adoptedId, adoptedTask);
}
}
if (!adoptedTasksMap.isEmpty()) {
LOG.debug("Resolving orphans using {} adopted orphans", adoptedTasksMap.size());
Map adoptedTasksNewlyAdoptedTask = resolveOrphansWithAdoptedOrphans(adoptedTasksMap);
adoptedTasksMap.putAll(adoptedTasksNewlyAdoptedTask);
}
return adoptedTasksMap;
}
private Map findAdoptedOrphans(Set adoptingCandidates) {
Map adoptedOrphansTasksFromCache = findAdoptedOrphansInCache(adoptingCandidates);
Map adoptedOrphansReceivedTasks = findAdoptedOrphansInReceivedTasks(adoptingCandidates);
Map orphansMap = Maps.newHashMap();
orphansMap.putAll(adoptedOrphansTasksFromCache);
orphansMap.putAll(adoptedOrphansReceivedTasks);
return orphansMap;
}
private Map findAdoptedOrphansInReceivedTasks(Set adoptingCandidates) {
Map retMap = Maps.newHashMap();
for (Map.Entry entry : receivedTasksMap.entrySet()) {
Task task = entry.getValue();
if (task.isOrphan() != null && task.isOrphan() && adoptingCandidates.contains(task.getParentId())){
retMap.put(entry.getKey(), task);
}
}
return retMap;
}
private Map findAdoptedOrphansInCache(Set adoptingCandidates) {
Map> adoptedOrphansFromCache = cacheHandler.logPullFromOrphansCache(adoptingCandidates, "resolve_orphans");
if (adoptedOrphansFromCache.isEmpty()){
return Maps.newHashMap();
}
else {
List orphansIds = adoptedOrphansFromCache.values().stream().flatMap(List::stream).collect(Collectors.toList());
return cacheHandler.logGetFromTasksCache(orphansIds, "resolve_orphans");
}
}
private static void populateParentParamsFromAdoptedTask(Task task, Task parentIndexedTask) {
ParentProperties parentProperties = getParentProperties(parentIndexedTask, null);
if (StringUtils.isEmpty(parentProperties.getPrimaryId()) && parentProperties.getParentPath() != null && !parentProperties.getParentPath().isEmpty()){
LOG.debug("populateParentParamsFromAdoptedTask primary missing. parentIndexedTask {}", GSON.toJson(parentIndexedTask));
}
List parentsPath = getParentPath(parentProperties);
if(!parentsPath.isEmpty()) {
task.setParentsPath(parentsPath);
}
task.setPrimaryId(parentProperties.getPrimaryId());
if (task.getCtx() == null){
task.setCtx(Maps.newHashMap());
}
for (Map.Entry entry : parentProperties.getContext().entrySet()) {
task.getCtx().putIfAbsent(entry.getKey(), entry.getValue());
}
}
static void populateParentParams(Event event, Task parentIndexedTask, Collection parentCurrentEvent) {
ParentProperties parentProperties = getParentProperties(parentIndexedTask, parentCurrentEvent);
if (StringUtils.isEmpty(parentProperties.getPrimaryId()) && parentProperties.getParentPath() != null && !parentProperties.getParentPath().isEmpty()){
LOG.debug("populateParentParams primary missing. parentIndexedTask {} parentCurrentEvent {}", GSON.toJson(parentIndexedTask), GSON.toJson(parentCurrentEvent));
}
List parentsPath = getParentPath(parentProperties);
if(!parentsPath.isEmpty()) {
event.setParentsPath(parentsPath);
}
event.setPrimaryId(parentProperties.getPrimaryId());
if (event.getContext() == null){
event.setContext(Maps.newHashMap());
}
for (Map.Entry entry : parentProperties.getContext().entrySet()) {
event.getContext().putIfAbsent(entry.getKey(), entry.getValue());
}
}
private static List getParentPath(ParentProperties parentProperties) {
List parentsPath = new ArrayList<>();
Collection parentParentsPath = parentProperties.getParentPath();
if ((parentParentsPath != null) && !parentParentsPath.isEmpty()) {
parentsPath.addAll(parentParentsPath);
}
String parentName = parentProperties.getParentName();
if (parentName != null) {
parentsPath.add(parentName);
}
return parentsPath;
}
private static ParentProperties getParentProperties(Task parentIndexedTask, Collection parentCurrentEvent) {
Map context = Maps.newHashMap();
String primaryId = null;
Collection parentPath = null;
String parentName = null;
if (parentCurrentEvent != null && !parentCurrentEvent.isEmpty()){
for (Event previousEvent : parentCurrentEvent) {
String previousPrimaryId = previousEvent.getPrimaryId();
if (previousPrimaryId != null){
primaryId = previousPrimaryId;
}
Map previousContext = previousEvent.getContext();
if (previousContext != null){
context.putAll(previousContext);
}
Collection previousPath = previousEvent.getParentsPath();
if (previousPath != null){
parentPath = previousPath;
}
String previousName = previousEvent.getName();
if (previousName != null){
parentName = previousName;
}
}
}
if (parentIndexedTask != null){
String indexedPrimary = parentIndexedTask.getPrimaryId();
if (indexedPrimary != null) {
primaryId = indexedPrimary;
}
Map indexedContext = parentIndexedTask.getCtx();
if (indexedContext != null) {
context.putAll(indexedContext);
}
List indexedParentsPath = parentIndexedTask.getParentsPath();
if (indexedParentsPath != null) {
parentPath = indexedParentsPath;
}
String indexedName = parentIndexedTask.getName();
if (indexedName != null) {
parentName = indexedName;
}
}
return new ParentProperties(primaryId, context, parentPath, parentName);
}
static class ParentProperties{
private final String primaryId;
private final Map context;
private final Collection parentPath;
private final String parentName;
ParentProperties(String primaryId, Map context, Collection parentPath, String parentName) {
this.primaryId = primaryId;
this.context = context;
this.parentPath = parentPath;
this.parentName = parentName;
}
String getPrimaryId() {
return primaryId;
}
Map getContext() {
return context;
}
Collection getParentPath() {
return parentPath;
}
String getParentName() {
return parentName;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy