blob: c30ec8fcce76d7e198475e80e508cd19d913c64a [file] [log] [blame]
package net.sf.taverna.t2.ui.perspectives.biocatalogue.integration.health_check;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.biocatalogue.x2009.xml.rest.MonitoringStatusLabel;
import org.biocatalogue.x2009.xml.rest.Service;
import org.biocatalogue.x2009.xml.rest.ServiceTest;
import org.biocatalogue.x2009.xml.rest.TestScript;
import net.sf.taverna.biocatalogue.model.SoapOperationIdentity;
import net.sf.taverna.biocatalogue.model.Util;
import net.sf.taverna.biocatalogue.model.connectivity.BioCatalogueClient;
import net.sf.taverna.t2.activities.wsdl.WSDLActivity;
import net.sf.taverna.t2.activities.wsdl.WSDLActivityConfigurationBean;
import net.sf.taverna.t2.ui.perspectives.biocatalogue.MainComponentFactory;
import net.sf.taverna.t2.visit.VisitReport;
import net.sf.taverna.t2.visit.VisitReport.Status;
import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
/**
* A {@link HealthChecker} for a {@link WSDLActivity}.
*
* @author Sergejs Aleksejevs
*/
public class BioCatalogueWSDLActivityHealthChecker implements HealthChecker<WSDLActivity>
{
private static final int MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA = 48 * 60 * 60 * 1000; // 48hrs
private Logger logger;
public BioCatalogueWSDLActivityHealthChecker() {
logger = Logger.getLogger(BioCatalogueWSDLActivityHealthChecker.class);
}
public boolean canVisit(Object subject) {
return (subject instanceof WSDLActivity);
}
public VisitReport visit(WSDLActivity activity, List<Object> ancestors)
{
WSDLActivityConfigurationBean configBean = activity.getConfiguration();
SoapOperationIdentity soapOpIdentity = new SoapOperationIdentity(configBean.getWsdl(), configBean.getOperation(), null);
try {
// make BioCatalogue API request to fetch the data
Service serviceWithMonitoringData = BioCatalogueClient.getInstance().lookupParentServiceMonitoringData(soapOpIdentity);
MonitoringStatusLabel.Enum serviceStatusLabel = null;
VisitReport.Status status = null;
String visitReportLabel = null;
String visitReportExplanation = null;
List<VisitReport> subReports = new ArrayList<VisitReport>();
if (serviceWithMonitoringData == null) {
// BioCatalogue doesn't "know" about this service - it appears not to be registered;
// --> nothing to report to Taverna
return (null);
}
else if (serviceWithMonitoringData.getLatestMonitoringStatus() == null) {
// BioCatalogue "knows" this service, but for some reason there was no monitoring data available;
// possibly an API change? either way --> nothing to report to Taverna
return (null);
}
else
{
Calendar lastCheckedAt = serviceWithMonitoringData.getLatestMonitoringStatus().getLastChecked();
String agoString = Util.getAgoString(lastCheckedAt, Calendar.getInstance(), MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA);
if (agoString == null) {
return (null);
}
serviceStatusLabel = serviceWithMonitoringData.getLatestMonitoringStatus().getLabel();
switch (serviceStatusLabel.intValue()) {
case MonitoringStatusLabel.INT_PASSED:
visitReportLabel = "Service Catalogue: all tests passed " + agoString;
visitReportExplanation = "The Service Catalogue reports that all available tests for this WSDL service have " +
"been successful. They have been last executed " + agoString;
status = Status.OK;
break;
case MonitoringStatusLabel.INT_WARNING:
case MonitoringStatusLabel.INT_FAILED:
visitReportLabel = "Service Catalogue: some tests failed " + agoString;
visitReportExplanation = "Some test scripts for this WSDL service have failed";
// only extract data about failing test scripts
subReports = createTestScriptSubReportsForFailingService(activity, serviceWithMonitoringData);
if (subReports.size() == 0) {
// failing tests must have been for endpoint / WSDL location - but not for scripts;
// Taverna doesn't need to know about the former, as it replicates internal checks
return (null);
}
else {
// determine the worst status and report as the one of the collection of subreports
status = VisitReport.getWorstStatus(subReports);
}
break;
case MonitoringStatusLabel.INT_UNCHECKED:
// monitoring record states that the status of this service was not (yet) checked;
// possibly monitoring on BioCatalogue was switched off before this service was registered;
// --> nothing to report to Taverna
return (null);
default:
visitReportLabel = "Service Catalogue: unknown monitoring status received - \"" + serviceStatusLabel.toString() + "\"";
visitReportExplanation = "The Service Catalogue has returned a new monitoring status for this service: \"" +
serviceStatusLabel.toString() + "\"\n\n" +
"It has never been used before and probably indicates a change in the Service Catalogue API. " +
"Please report this issue to the Service Catalogue developers.";
status = Status.WARNING;
break;
}
}
// wrap determined values into a single VisitReport object; then attach data to identify
// this service in associated VisitExplainer
VisitReport report = new VisitReport(BioCatalogueWSDLActivityHealthCheck.getInstance(), activity,
visitReportLabel, BioCatalogueWSDLActivityHealthCheck.MESSAGE_IN_VISIT_REPORT, status, subReports);
report.setProperty(BioCatalogueWSDLActivityHealthCheck.WSDL_LOCATION_PROPERTY, soapOpIdentity.getWsdlLocation());
report.setProperty(BioCatalogueWSDLActivityHealthCheck.OPERATION_NAME_PROPERTY, soapOpIdentity.getOperationName());
report.setProperty(BioCatalogueWSDLActivityHealthCheck.EXPLANATION_MSG_PROPERTY, visitReportExplanation);
return (report);
}
catch (Exception e) {
// not sure what could have happened - it will be visible in the logs
logger.error("Unexpected error while performing health check for " +
soapOpIdentity.getWsdlLocation() + " service.", e);
return (null);
}
}
private List<VisitReport> createTestScriptSubReportsForFailingService(WSDLActivity activity, Service serviceWithMonitoringData)
{
List<VisitReport> subReports = new ArrayList<VisitReport>();
try {
List<ServiceTest> serviceTests = serviceWithMonitoringData.getMonitoring().getTests().getServiceTestList();
for (ServiceTest test : serviceTests)
{
if (test.getTestType().getTestScript() != null &&
test.getTestType().getTestScript()instanceof TestScript)
{
TestScript testScript = test.getTestType().getTestScript();
String agoString = Util.getAgoString(test.getLatestStatus().getLastChecked(), Calendar.getInstance(),
MILLIS_IN_THE_PAST_FOR_OLDEST_MONITORING_DATA);
// only proceed if this test wasn't run too long ago
if (agoString != null) {
String label = "Service Catalogue: \"" + testScript.getName() + "\" test script " + test.getLatestStatus().getLabel();
VisitReport report = new VisitReport(BioCatalogueWSDLActivityHealthCheck.getInstance(), activity,
label, BioCatalogueWSDLActivityHealthCheck.MESSAGE_IN_VISIT_REPORT,
ServiceMonitoringStatusInterpreter.translateBioCatalogueStatusForTaverna(test.getLatestStatus().getLabel()));
report.setProperty(BioCatalogueWSDLActivityHealthCheck.WSDL_LOCATION_PROPERTY, activity.getConfiguration().getWsdl());
report.setProperty(BioCatalogueWSDLActivityHealthCheck.OPERATION_NAME_PROPERTY, activity.getConfiguration().getOperation());
report.setProperty(BioCatalogueWSDLActivityHealthCheck.EXPLANATION_MSG_PROPERTY,
"This test was last executed " + agoString + "." +
"\n\n" + StringEscapeUtils.escapeHtml(test.getLatestStatus().getMessage()) +
"\n\n---- Test script description ----\n" + StringEscapeUtils.escapeHtml(testScript.getDescription()));
subReports.add(report);
}
}
}
}
catch (Exception e) {
// log the error, but do not terminate the method - maybe some sub reports were successfully
// generated, in which case at least partial result can be returned
logger.error("Encountered unexpected problem while trying to generate a collection of sub-reports " +
"for a failing service: " + activity.getConfiguration().getWsdl(), e);
}
return (subReports);
}
/**
* Health check for the WSDL activities involves fetching
* the monitoring status of each activity from BioCatalogue -
* this *may* be time consuming.
*/
public boolean isTimeConsuming() {
return true;
}
}