/* * Copyright 2014 NAVER Corp. * * 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 com.navercorp.pinpoint.profiler; import com.navercorp.pinpoint.ProductInfo; import com.navercorp.pinpoint.bootstrap.Agent; import com.navercorp.pinpoint.bootstrap.AgentOption; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.interceptor.InterceptorInvokerHelper; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerBinder; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService; import com.navercorp.pinpoint.profiler.context.module.ApplicationContext; import com.navercorp.pinpoint.profiler.context.module.DefaultApplicationContext; import com.navercorp.pinpoint.profiler.util.SystemPropertyDumper; import com.navercorp.pinpoint.profiler.interceptor.registry.DefaultInterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.logging.Slf4jLoggerBinder; import com.navercorp.pinpoint.rpc.ClassPreLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author emeroad * @author koo.taejin * @author hyungil.jeong */ public class DefaultAgent implements Agent { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final PLoggerBinder binder; private final ProfilerConfig profilerConfig; private final ApplicationContext applicationContext; private final Object agentStatusLock = new Object(); private volatile AgentStatus agentStatus; private final InterceptorRegistryBinder interceptorRegistryBinder; private final ServiceTypeRegistryService serviceTypeRegistryService; static { // Preload classes related to pinpoint-rpc module. ClassPreLoader.preload(); } public DefaultAgent(AgentOption agentOption) { this(agentOption, createInterceptorRegistry(agentOption)); } public static InterceptorRegistryBinder createInterceptorRegistry(AgentOption agentOption) { final int interceptorSize = getInterceptorSize(agentOption); return new DefaultInterceptorRegistryBinder(interceptorSize); } private static int getInterceptorSize(AgentOption agentOption) { if (agentOption == null) { return DefaultInterceptorRegistryBinder.DEFAULT_MAX; } final ProfilerConfig profilerConfig = agentOption.getProfilerConfig(); return profilerConfig.getInterceptorRegistrySize(); } public DefaultAgent(AgentOption agentOption, final InterceptorRegistryBinder interceptorRegistryBinder) { if (agentOption == null) { throw new NullPointerException("agentOption must not be null"); } if (agentOption.getInstrumentation() == null) { throw new NullPointerException("instrumentation must not be null"); } if (agentOption.getProfilerConfig() == null) { throw new NullPointerException("profilerConfig must not be null"); } if (agentOption.getServiceTypeRegistryService() == null) { throw new NullPointerException("serviceTypeRegistryService must not be null"); } if (interceptorRegistryBinder == null) { throw new NullPointerException("interceptorRegistryBinder must not be null"); } logger.info("AgentOption:{}", agentOption); this.binder = new Slf4jLoggerBinder(); bindPLoggerFactory(this.binder); this.interceptorRegistryBinder = interceptorRegistryBinder; interceptorRegistryBinder.bind(); this.serviceTypeRegistryService = agentOption.getServiceTypeRegistryService(); dumpSystemProperties(); dumpConfig(agentOption.getProfilerConfig()); changeStatus(AgentStatus.INITIALIZING); this.profilerConfig = agentOption.getProfilerConfig(); this.applicationContext = newApplicationContext(agentOption, interceptorRegistryBinder); InterceptorInvokerHelper.setPropagateException(profilerConfig.isPropagateInterceptorException()); } protected ApplicationContext newApplicationContext(AgentOption agentOption, InterceptorRegistryBinder interceptorRegistryBinder) { return new DefaultApplicationContext(agentOption, interceptorRegistryBinder); } protected ApplicationContext getApplicationContext() { return applicationContext; } private void dumpSystemProperties() { SystemPropertyDumper dumper = new SystemPropertyDumper(); dumper.dump(); } private void dumpConfig(ProfilerConfig profilerConfig) { if (logger.isInfoEnabled()) { logger.info("{}\n{}", "dumpConfig", profilerConfig); } } private void changeStatus(AgentStatus status) { this.agentStatus = status; if (logger.isDebugEnabled()) { logger.debug("Agent status is changed. {}", status); } } private void bindPLoggerFactory(PLoggerBinder binder) { final String binderClassName = binder.getClass().getName(); PLogger pLogger = binder.getLogger(binder.getClass().getName()); pLogger.info("PLoggerFactory.initialize() bind:{} cl:{}", binderClassName, binder.getClass().getClassLoader()); // Set binder to static LoggerFactory // Should we unset binder at shutdown hook or stop()? PLoggerFactory.initialize(binder); } public ServiceTypeRegistryService getServiceTypeRegistryService() { return serviceTypeRegistryService; } @Override public void start() { synchronized (agentStatusLock) { if (this.agentStatus == AgentStatus.INITIALIZING) { changeStatus(AgentStatus.RUNNING); } else { logger.warn("Agent already started."); return; } } logger.info("Starting {} Agent.", ProductInfo.NAME); this.applicationContext.start(); } @Override public void stop() { stop(false); } public void stop(boolean staticResourceCleanup) { synchronized (agentStatusLock) { if (this.agentStatus == AgentStatus.RUNNING) { changeStatus(AgentStatus.STOPPED); } else { logger.warn("Cannot stop agent. Current status = [{}]", this.agentStatus); return; } } logger.info("Stopping {} Agent.", ProductInfo.NAME); this.applicationContext.close(); // for testcase if (staticResourceCleanup) { PLoggerFactory.unregister(this.binder); this.interceptorRegistryBinder.unbind(); } } }