kieker.monitoring.probe.cxf.OperationExecutionSOAPResponseOutInterceptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kieker Show documentation
Show all versions of kieker Show documentation
Kieker: Application Performance Monitoring and Dynamic Software Analysis
/***************************************************************************
* Copyright 2013 Kieker Project (http://kieker-monitoring.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
package kieker.monitoring.probe.cxf;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.SoapHeaderOutFilterInterceptor;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import kieker.common.logging.Log;
import kieker.common.logging.LogFactory;
import kieker.common.record.controlflow.OperationExecutionRecord;
import kieker.monitoring.core.controller.IMonitoringController;
import kieker.monitoring.core.controller.MonitoringController;
import kieker.monitoring.core.registry.ControlFlowRegistry;
import kieker.monitoring.core.registry.SessionRegistry;
import kieker.monitoring.probe.IMonitoringProbe;
import kieker.monitoring.timer.ITimeSource;
/**
* CXF OutInterceptor to set the sessionIdentifier header for an outgoing soap message.
*
* Look here how to add it to your client config: http://cwiki.apache.org/CXF20DOC/interceptors.html
*
* Setting the soap header with jaxb or aegis databinding didn't work yet:
* http://www.nabble.com/Add-%22out-of-band%22-soap-header-using-simple-frontend-td19380093.html
*
* @author Dennis Kieselhorst, Andre van Hoorn
*
* @since 1.0
*/
public class OperationExecutionSOAPResponseOutInterceptor extends SoapHeaderOutFilterInterceptor implements IMonitoringProbe {
/** This constant contains the signature, which will be used in the monitoring logs. */
public static final String SIGNATURE = "public void " + OperationExecutionSOAPResponseOutInterceptor.class.getName()
+ ".handleMessage(org.apache.cxf.binding.soap.SoapMessage)";
/** Stores the singleton instance of the control flow registry. */
protected static final ControlFlowRegistry CF_REGISTRY = ControlFlowRegistry.INSTANCE;
/** Stores the singleton instance of the session registry. */
protected static final SessionRegistry SESSION_REGISTRY = SessionRegistry.INSTANCE;
/** Stores the singleton instance of the SOAP trace registry. */
protected static final SOAPTraceRegistry SOAP_REGISTRY = SOAPTraceRegistry.getInstance();
private static final Log LOG = LogFactory.getLog(OperationExecutionSOAPResponseOutInterceptor.class);
/** The monitoring controller of this interceptor. */
protected final IMonitoringController monitoringController;
/** The used time source. */
protected final ITimeSource timeSource;
/** The name of the VM. */
protected final String vmName;
/**
* Creates a new instance of this class, using the singleton instance of the {@link MonitoringController} as controller.
*/
public OperationExecutionSOAPResponseOutInterceptor() {
this(MonitoringController.getInstance());
}
/**
* Creates a new instance of this class, using the given instance of a {@link MonitoringController} as controller.
*
* @param monitoringCtrl
* The controller of this interceptor.
*/
public OperationExecutionSOAPResponseOutInterceptor(final IMonitoringController monitoringCtrl) {
this.monitoringController = monitoringCtrl;
this.timeSource = this.monitoringController.getTimeSource();
this.vmName = this.monitoringController.getHostname();
}
@Override
public void handleMessage(final SoapMessage msg) throws Fault {
if (!this.monitoringController.isMonitoringEnabled()) {
return;
}
if (!this.monitoringController.isProbeActivated(SIGNATURE)) {
return;
}
String sessionID;
final long traceId = CF_REGISTRY.recallThreadLocalTraceId();
long tin;
long tout;
boolean isEntryCall = true;
int eoi = -1;
// final int ess = -1;
int myEoi = -1;
int myEss = -1;
if (traceId == -1) {
// Kieker trace Id not registered. Should not happen, since this is a response message!
LOG.warn("Kieker traceId not registered. Will unset all threadLocal variables and return.");
this.unsetKiekerThreadLocalData(); // unset all variables
return;
} else {
// thread-local traceId exists: eoi, ess, and sessionID should have been registered before
eoi = CF_REGISTRY.recallThreadLocalEOI();
sessionID = SESSION_REGISTRY.recallThreadLocalSessionId();
myEoi = SOAP_REGISTRY.recallThreadLocalInRequestEOI();
myEss = SOAP_REGISTRY.recallThreadLocalInRequestESS();
tin = SOAP_REGISTRY.recallThreadLocalInRequestTin();
tout = this.timeSource.getTime();
isEntryCall = SOAP_REGISTRY.recallThreadLocalInRequestIsEntryCall();
}
// The trace is leaving this node, thus we need to clean up the thread-local variables.
this.unsetKiekerThreadLocalData();
// Log this execution
final OperationExecutionRecord rec = new OperationExecutionRecord(SIGNATURE, sessionID, traceId, tin, tout, this.vmName, myEoi, myEss);
this.monitoringController.newMonitoringRecord(rec);
// We don't put Kieker data into response header if request didn't contain Kieker information
if (isEntryCall) {
return;
}
final Document d = DOMUtils.createDocument();
Element e;
Header hdr;
// .) Add sessionId to response header
// There's no need to pass the session ID back.
// 2.) Add traceId to response header
// Actually, there's no need to pass the trace ID back but
// we do this for consistency checks on the caller side.
e = d.createElementNS(SOAPHeaderConstants.NAMESPACE_URI, SOAPHeaderConstants.TRACE_QUALIFIED_NAME);
e.setTextContent(Long.toString(traceId));
hdr = new Header(SOAPHeaderConstants.TRACE_IDENTIFIER_QNAME, e);
msg.getHeaders().add(hdr);
// 3.) Add eoi to response header
e = d.createElementNS(SOAPHeaderConstants.NAMESPACE_URI, SOAPHeaderConstants.EOI_QUALIFIED_NAME);
e.setTextContent(Integer.toString(eoi));
hdr = new Header(SOAPHeaderConstants.EOI_IDENTIFIER_QNAME, e);
msg.getHeaders().add(hdr);
// 4.) Add ess to response header
// There's no need to pass the ESS back.
}
private final void unsetKiekerThreadLocalData() {
CF_REGISTRY.unsetThreadLocalTraceId();
CF_REGISTRY.unsetThreadLocalEOI();
CF_REGISTRY.unsetThreadLocalESS();
SESSION_REGISTRY.unsetThreadLocalSessionId();
SOAP_REGISTRY.unsetThreadLocalInRequestIsEntryCall();
SOAP_REGISTRY.unsetThreadLocalInRequestTin();
SOAP_REGISTRY.unsetThreadLocalInRequestEOI();
SOAP_REGISTRY.unsetThreadLocalInRequestESS();
}
}