/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.workflow.execution.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.LogFactory;
import de.rcenvironment.core.communication.api.PlatformService;
import de.rcenvironment.core.component.workflow.execution.api.WorkflowExecutionContext;
import de.rcenvironment.core.component.workflow.execution.api.WorkflowState;
import de.rcenvironment.core.component.workflow.model.api.WorkflowNode;
import de.rcenvironment.core.toolkitbridge.transitional.StatsCounter;
import de.rcenvironment.core.utils.common.StringUtils;
/**
* Implementation of {@link WorkflowExecutionStatsService}.
*
* @author Doreen Seider
*/
public class WorkflowExecutionStatsServiceImpl implements WorkflowExecutionStatsService {
private static final int THOUSAND = 1000;
private static final String CAT_WF_EXEC = "Workflow Execution: Workflow runs by number of components";
private static final String CAT_WF_EXEC_DURATION = "Workflow Execution: Duration by number of components [sec]";
private static final String CAT_WF_EXEC_DISTR = "Workflow Execution: Components distribution per workflow run";
private static final String CAT_WF_EXEC_FINAL_STATES = "Workflow Execution: Final states";
private static final String KEY_00_05_COMPS = "00..05 components";
private static final String KEY_06_10_COMPS = "06..10 components";
private static final String KEY_11_20_COMPS = "11..20 components";
private static final String KEY_21_30_COMPS = "21..30 components";
private static final String KEY_31_50_COMPS = "31..50 components";
private static final String KEY_MORE_THAN_50_COMPS = ">50 components";
private static final String KEY_TOTAL = "[total]";
private static final String KEY_LOCAL_COMPS = "local components only";
private static final String KEY_DISTR_COMPS = "components distributed";
private static final int FIFTY = 50;
private static final int THIRTY = 30;
private static final int TWENTY = 20;
private PlatformService platformService;
private Map<String, Long> wfExeStartTimestamps = Collections.synchronizedMap(new HashMap<String, Long>());
@Override
public void addStatsAtWorkflowStart(WorkflowExecutionContext wfExeCtx) {
if (wfExeStartTimestamps.containsKey(wfExeCtx.getExecutionIdentifier())) {
LogFactory.getLog(getClass()).error(StringUtils.format("Stats about duration for component '%s' (%s) not recorded properly: "
+ "last time (start record but no termination record existed)",
wfExeCtx.getInstanceName(), wfExeCtx.getExecutionIdentifier()));
}
wfExeStartTimestamps.put(wfExeCtx.getExecutionIdentifier(), Long.valueOf(System.currentTimeMillis()));
StatsCounter.count(CAT_WF_EXEC, KEY_TOTAL);
int compCount = wfExeCtx.getWorkflowDescription().getWorkflowNodes().size();
if (compCount <= 5) {
StatsCounter.count(CAT_WF_EXEC, KEY_00_05_COMPS);
} else if (compCount <= 10) {
StatsCounter.count(CAT_WF_EXEC, KEY_06_10_COMPS);
} else if (compCount <= TWENTY) {
StatsCounter.count(CAT_WF_EXEC, KEY_11_20_COMPS);
} else if (compCount <= THIRTY) {
StatsCounter.count(CAT_WF_EXEC, KEY_21_30_COMPS);
} else if (compCount <= FIFTY) {
StatsCounter.count(CAT_WF_EXEC, KEY_31_50_COMPS);
} else {
StatsCounter.count(CAT_WF_EXEC, KEY_MORE_THAN_50_COMPS);
}
boolean localOnly = true;
for (WorkflowNode wn : wfExeCtx.getWorkflowDescription().getWorkflowNodes()) {
if (!platformService.matchesLocalInstance(wn.getComponentDescription().getNode())) {
localOnly = false;
break;
}
}
// suggestion: tracking the actual number of involved instances/nodes may be interesting - misc_ro
if (localOnly) {
StatsCounter.count(CAT_WF_EXEC_DISTR, KEY_LOCAL_COMPS);
} else {
StatsCounter.count(CAT_WF_EXEC_DISTR, KEY_DISTR_COMPS);
}
}
@Override
public void addStatsAtWorkflowTermination(WorkflowExecutionContext wfExeCtx, WorkflowState finalWorkflowState) {
if (wfExeStartTimestamps.containsKey(wfExeCtx.getExecutionIdentifier())) {
String statsKey;
int compCount = wfExeCtx.getWorkflowDescription().getWorkflowNodes().size();
if (compCount <= 5) {
statsKey = KEY_00_05_COMPS;
} else if (compCount <= 10) {
statsKey = KEY_06_10_COMPS;
} else if (compCount <= TWENTY) {
statsKey = KEY_11_20_COMPS;
} else if (compCount <= THIRTY) {
statsKey = KEY_21_30_COMPS;
} else if (compCount <= FIFTY) {
statsKey = KEY_31_50_COMPS;
} else {
statsKey = KEY_MORE_THAN_50_COMPS;
}
StatsCounter.registerValue(CAT_WF_EXEC_DURATION, statsKey, Math.abs((System.currentTimeMillis()
- wfExeStartTimestamps.get(wfExeCtx.getExecutionIdentifier())) / THOUSAND));
wfExeStartTimestamps.remove(wfExeCtx.getExecutionIdentifier());
} else {
LogFactory.getLog(getClass()).error(StringUtils.format("Failed to add stats about duration for workflow '%s' (%s)",
wfExeCtx.getInstanceName(), wfExeCtx.getExecutionIdentifier()));
}
StatsCounter.count(CAT_WF_EXEC_FINAL_STATES, finalWorkflowState.getDisplayName());
}
protected void bindPlatformService(PlatformService newService) {
platformService = newService;
}
}