package rocks.inspectit.agent.java.sensor.method.remote.server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import rocks.inspectit.agent.java.config.impl.RegisteredSensorConfig; import rocks.inspectit.agent.java.core.ICoreService; import rocks.inspectit.agent.java.core.IPlatformManager; import rocks.inspectit.agent.java.hooking.IMethodHook; import rocks.inspectit.agent.java.sdk.opentracing.internal.impl.SpanImpl; import rocks.inspectit.agent.java.sensor.method.http.StartEndMarker; import rocks.inspectit.agent.java.tracing.core.ServerInterceptor; import rocks.inspectit.agent.java.tracing.core.adapter.ClientAdapterProvider; import rocks.inspectit.agent.java.tracing.core.adapter.ResponseAdapter; import rocks.inspectit.agent.java.tracing.core.adapter.ServerAdapterProvider; import rocks.inspectit.agent.java.tracing.core.adapter.ServerRequestAdapter; import rocks.inspectit.agent.java.tracing.core.transformer.SpanTransformer; import rocks.inspectit.shared.all.tracing.data.AbstractSpan; /** * The hook is the default implementation of remote server. The hook works with the * {@link ServerInterceptor} in order to correctly handle server request start in the * {@link #beforeBody(long, long, Object, Object[], RegisteredSensorConfig)} and request end in the * {@link #secondAfterBody(ICoreService, long, long, Object, Object[], Object, RegisteredSensorConfig)}. * <p> * This hook measures also measures execution time. * <p> * The created spans will be passed to the give core service of the second after body method. * * @author Thomas Kluge * @author Ivan Senic * */ public class RemoteServerHook implements IMethodHook { /** * The logger of the class. */ private static final Logger LOG = LoggerFactory.getLogger(RemoteServerHook.class); /** * Helps us to ensure that we only execute one remote server hook for each server request on all * remote server sensor implementations. * <p> * Static on purpose. */ private static final StartEndMarker REF_MARKER = new StartEndMarker(); /** * {@link ServerInterceptor}. */ private final ServerInterceptor serverInterceptor; /** * {@link ClientAdapterProvider}. */ private final ServerAdapterProvider serverAdapterProvider; /** * The Platform manager. */ private final IPlatformManager platformManager; /** * The stack containing the created span by this sensor. */ private final ThreadLocal<SpanImpl> spanStack = new ThreadLocal<SpanImpl>(); /** * Default constructor. * * @param serverInterceptor * Our server interceptor. * @param serverAdapterProvider * {@link ServerAdapterProvider} * @param platformManager * The Platform manager * */ public RemoteServerHook(ServerInterceptor serverInterceptor, ServerAdapterProvider serverAdapterProvider, IPlatformManager platformManager) { this.serverInterceptor = serverInterceptor; this.serverAdapterProvider = serverAdapterProvider; this.platformManager = platformManager; } /** * {@inheritDoc} */ @Override public void beforeBody(long methodId, long sensorTypeId, Object object, Object[] parameters, RegisteredSensorConfig rsc) { if (!REF_MARKER.isMarkerSet()) { // get requestAdapter and handle ServerRequestAdapter<?> adapter = serverAdapterProvider.getServerRequestAdapter(object, parameters, rsc); SpanImpl span = serverInterceptor.handleRequest(adapter); if (null != span) { spanStack.set(span); if (LOG.isDebugEnabled()) { LOG.debug("Remote server hook before body span " + span); } } } REF_MARKER.markCall(); } /** * {@inheritDoc} */ @Override public void firstAfterBody(long methodId, long sensorTypeId, Object object, Object[] parameters, Object result, RegisteredSensorConfig rsc) { REF_MARKER.markEndCall(); } /** * {@inheritDoc} */ @Override public void secondAfterBody(ICoreService coreService, long methodId, long sensorTypeId, Object object, Object[] parameters, Object result, RegisteredSensorConfig rsc) { // check if in the right(first) invocation if (REF_MARKER.isMarkerSet() && REF_MARKER.matchesFirst()) { // call ended, remove the marker. REF_MARKER.remove(); // extract span from thread local SpanImpl span = spanStack.get(); spanStack.remove(); if (null != span) { // get requestAdapter and handle ResponseAdapter responseAdapter = serverAdapterProvider.getServerResponseAdapter(object, parameters, result, rsc); serverInterceptor.handleResponse(span, responseAdapter); if (LOG.isDebugEnabled()) { LOG.debug("Remote server hook after body span " + span); } AbstractSpan transformedSpan = SpanTransformer.transformSpan(span); transformedSpan.setPlatformIdent(platformManager.getPlatformId()); transformedSpan.setMethodIdent(methodId); transformedSpan.setSensorTypeIdent(sensorTypeId); // add to core service (use span id as prefix) coreService.addMethodSensorData(sensorTypeId, methodId, String.valueOf(transformedSpan.getSpanIdent().getId()), transformedSpan); } } } }