/** * Dianping.com Inc. * Copyright (c) 2003-${year} All Rights Reserved. */ package com.dianping.pigeon.remoting.provider.process.filter; import java.io.Serializable; import java.util.Calendar; import java.util.Map; import com.dianping.pigeon.remoting.common.codec.SerializerType; import org.apache.commons.lang.StringUtils; import org.springframework.util.CollectionUtils; import com.dianping.pigeon.config.ConfigManagerLoader; import com.dianping.pigeon.extension.ExtensionLoader; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.monitor.Monitor; import com.dianping.pigeon.monitor.MonitorLoader; import com.dianping.pigeon.monitor.MonitorTransaction; import com.dianping.pigeon.remoting.common.domain.InvocationContext.TimePhase; import com.dianping.pigeon.remoting.common.domain.InvocationContext.TimePoint; import com.dianping.pigeon.remoting.common.domain.InvocationRequest; import com.dianping.pigeon.remoting.common.domain.InvocationResponse; import com.dianping.pigeon.remoting.common.monitor.SizeMonitor; import com.dianping.pigeon.remoting.common.process.ServiceInvocationFilter; import com.dianping.pigeon.remoting.common.process.ServiceInvocationHandler; import com.dianping.pigeon.remoting.common.util.Constants; import com.dianping.pigeon.remoting.common.util.ContextUtils; import com.dianping.pigeon.remoting.common.util.InvocationUtils; import com.dianping.pigeon.remoting.provider.domain.ProviderChannel; import com.dianping.pigeon.remoting.provider.domain.ProviderContext; import com.dianping.pigeon.remoting.provider.process.ProviderContextProcessor; import com.dianping.pigeon.remoting.provider.service.method.ServiceMethod; import com.dianping.pigeon.remoting.provider.service.method.ServiceMethodFactory; public class MonitorProcessFilter implements ServiceInvocationFilter<ProviderContext> { private static final Logger logger = LoggerLoader.getLogger(MonitorProcessFilter.class); private static final Logger accessLogger = LoggerLoader.getLogger(com.dianping.pigeon.util.Constants.ACCESS_LOG_NAME); private static final Monitor monitor = MonitorLoader.getMonitor(); private static final boolean isAccessLogEnabled = ConfigManagerLoader.getConfigManager() .getBooleanValue("pigeon.provider.accesslog.enable", false); private static final String KEY_LOG_SERVICE_EXCEPTION = "pigeon.provider.logserviceexception"; private static final ProviderContextProcessor contextProcessor = ExtensionLoader .getExtension(ProviderContextProcessor.class); public MonitorProcessFilter() { ConfigManagerLoader.getConfigManager().getBooleanValue(KEY_LOG_SERVICE_EXCEPTION, true); } @Override public InvocationResponse invoke(ServiceInvocationHandler handler, ProviderContext invocationContext) throws Throwable { invocationContext.getTimeline().add(new TimePoint(TimePhase.O)); InvocationRequest request = invocationContext.getRequest(); ProviderChannel channel = invocationContext.getChannel(); MonitorTransaction transaction = null; String fromIp = null; if (monitor != null) { String methodUri = null; try { ServiceMethod serviceMethod = ServiceMethodFactory.getMethod(request); invocationContext.setServiceMethod(serviceMethod); methodUri = InvocationUtils.getRemoteCallFullName(request.getServiceName(), request.getMethodName(), serviceMethod.getOriginalParameterClasses()); } catch (Throwable e) { } try { if (StringUtils.isBlank(methodUri)) { methodUri = InvocationUtils.getRemoteCallFullName(request.getServiceName(), request.getMethodName(), request.getParamClassName()); } invocationContext.setMethodUri(methodUri); transaction = monitor.createTransaction("PigeonService", methodUri, invocationContext); if (transaction != null) { transaction.setStatusOk(); monitor.setCurrentServiceTransaction(transaction); transaction.logEvent("PigeonService.app", request.getApp(), ""); String parameters = ""; fromIp = channel.getRemoteAddress(); if (Constants.LOG_PARAMETERS) { StringBuilder event = new StringBuilder(); event.append(InvocationUtils.toJsonString(request.getParameters(), 1000, 50)); parameters = event.toString(); } transaction.logEvent("PigeonService.client", fromIp, parameters); transaction.logEvent("PigeonService.QPS", "S" + Calendar.getInstance().get(Calendar.SECOND), ""); String reqSize = SizeMonitor.getInstance().getLogSize(request.getSize()); if (reqSize != null) { transaction.logEvent("PigeonService.requestSize", reqSize, "" + request.getSize()); } if (!Constants.PROTOCOL_DEFAULT.equals(channel.getProtocol())) { transaction.addData("Protocol", channel.getProtocol()); } if (SerializerType.isThrift(request.getSerialize())) { monitor.logEvent("PigeonService.protocol", request.getApp(), fromIp); } } ContextUtils.putLocalContext("CurrentServiceUrl", request.getServiceName() + "#" + request.getMethodName()); } catch (Throwable e) { monitor.logError(e); } } InvocationResponse response = null; try { try { response = handler.handle(invocationContext); } catch (RuntimeException e) { if (transaction != null) { try { transaction.setStatusError(e); } catch (Throwable e2) { monitor.logMonitorError(e2); } } if (monitor != null) { monitor.logError(e); } } if (transaction != null) { try { if (response != null) { String respSize = SizeMonitor.getInstance().getLogSize(response.getSize()); if (respSize != null) { transaction.logEvent("PigeonService.responseSize", respSize, "" + response.getSize()); } } Map<String, Serializable> globalContext = ContextUtils.getGlobalContext(); if (!CollectionUtils.isEmpty(globalContext)) { String sourceApp = (String) globalContext.get(Constants.CONTEXT_KEY_SOURCE_APP); if (sourceApp != null) { transaction.addData("SourceApp", sourceApp); } String sourceIp = (String) globalContext.get(Constants.CONTEXT_KEY_SOURCE_IP); if (sourceIp != null) { transaction.addData("SourceIp", sourceIp); } } String from = (String) ContextUtils.getLocalContext("RequestIp"); if (from != null) { transaction.logEvent("PigeonConsole.client", from, ""); String app = (String) ContextUtils.getLocalContext("RequestApp"); if (app != null) { transaction.logEvent("PigeonConsole.app", app, ""); } } transaction.writeMonitorContext(); } catch (Throwable e) { monitor.logError(e); } } } finally { Throwable serviceError = invocationContext.getServiceError(); if (serviceError != null && monitor != null) { monitor.logError(invocationContext.getServiceError()); } Throwable frameworkError = invocationContext.getFrameworkError(); if (frameworkError != null && monitor != null) { monitor.logError(frameworkError); transaction.setStatusError(frameworkError); } if (transaction != null) { invocationContext.getTimeline().add(new TimePoint(TimePhase.E, System.currentTimeMillis())); try { transaction.complete(); if (isAccessLogEnabled) { accessLogger.info(new StringBuilder().append(request.getApp()).append("@").append(fromIp) .append("@").append(request).toString()); } } catch (Throwable e) { monitor.logMonitorError(e); } monitor.clearServiceTransaction(); } if (contextProcessor != null) { contextProcessor.clearContext(); } ContextUtils.clearLocalContext(); ContextUtils.clearRequestContext(); ContextUtils.clearGlobalContext(); } return response; } }