All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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