/* * Copyright 2017 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.context.module; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.Stage; import com.navercorp.pinpoint.bootstrap.AgentOption; import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; import com.navercorp.pinpoint.bootstrap.context.TraceContext; import com.navercorp.pinpoint.bootstrap.instrument.DynamicTransformTrigger; import com.navercorp.pinpoint.profiler.instrument.InstrumentEngine; import com.navercorp.pinpoint.common.service.ServiceTypeRegistryService; import com.navercorp.pinpoint.profiler.AgentInfoSender; import com.navercorp.pinpoint.profiler.AgentInformation; import com.navercorp.pinpoint.profiler.ClassFileTransformerDispatcher; import com.navercorp.pinpoint.profiler.instrument.ASMBytecodeDumpService; import com.navercorp.pinpoint.profiler.instrument.BytecodeDumpTransformer; import com.navercorp.pinpoint.profiler.interceptor.registry.InterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.monitor.AgentStatMonitor; import com.navercorp.pinpoint.profiler.sender.DataSender; import com.navercorp.pinpoint.profiler.sender.EnhancedDataSender; import com.navercorp.pinpoint.rpc.client.PinpointClient; import com.navercorp.pinpoint.rpc.client.PinpointClientFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; /** * @author Woonduk Kang(emeroad) */ public class DefaultApplicationContext implements ApplicationContext { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final ProfilerConfig profilerConfig; private final AgentInfoSender agentInfoSender; private final AgentStatMonitor agentStatMonitor; private final TraceContext traceContext; private final PinpointClientFactory clientFactory; private final PinpointClient client; private final EnhancedDataSender tcpDataSender; private final DataSender statDataSender; private final DataSender spanDataSender; private final AgentInformation agentInformation; private final AgentOption agentOption; private final ServiceTypeRegistryService serviceTypeRegistryService; private final ClassFileTransformerDispatcher classFileDispatcher; private final Instrumentation instrumentation; private final InstrumentEngine instrumentEngine; private final DynamicTransformTrigger dynamicTransformTrigger; private final Injector injector; public DefaultApplicationContext(AgentOption agentOption, final InterceptorRegistryBinder interceptorRegistryBinder) { if (agentOption == null) { throw new NullPointerException("agentOption must not be null"); } if (interceptorRegistryBinder == null) { throw new NullPointerException("interceptorRegistryBinder must not be null"); } this.agentOption = agentOption; this.profilerConfig = agentOption.getProfilerConfig(); this.instrumentation = agentOption.getInstrumentation(); this.serviceTypeRegistryService = agentOption.getServiceTypeRegistryService(); if (logger.isInfoEnabled()) { logger.info("DefaultAgent classLoader:{}", this.getClass().getClassLoader()); } final Module applicationContextModule = newApplicationContextModule(agentOption, interceptorRegistryBinder); this.injector = Guice.createInjector(Stage.PRODUCTION, applicationContextModule); this.instrumentEngine = injector.getInstance(InstrumentEngine.class); this.classFileDispatcher = injector.getInstance(ClassFileTransformerDispatcher.class); this.dynamicTransformTrigger = injector.getInstance(DynamicTransformTrigger.class); // ClassFileTransformer classFileTransformer = injector.getInstance(ClassFileTransformer.class); ClassFileTransformer classFileTransformer = wrap(classFileDispatcher); instrumentation.addTransformer(classFileTransformer, true); this.spanDataSender = newUdpSpanDataSender(); logger.info("spanDataSender:{}", spanDataSender); this.statDataSender = newUdpStatDataSender(); logger.info("statDataSender:{}", statDataSender); this.clientFactory = injector.getInstance(PinpointClientFactory.class); logger.info("clientFactory:{}", clientFactory); this.client = injector.getInstance(PinpointClient.class); logger.info("client:{}", client); this.tcpDataSender = injector.getInstance(EnhancedDataSender.class); logger.info("tcpDataSender:{}", tcpDataSender); this.traceContext = injector.getInstance(TraceContext.class); this.agentInformation = injector.getInstance(AgentInformation.class); logger.info("agentInformation:{}", agentInformation); this.agentInfoSender = injector.getInstance(AgentInfoSender.class); this.agentStatMonitor = injector.getInstance(AgentStatMonitor.class); } public ClassFileTransformer wrap(ClassFileTransformerDispatcher classFileTransformerDispatcher) { final boolean enableBytecodeDump = profilerConfig.readBoolean(ASMBytecodeDumpService.ENABLE_BYTECODE_DUMP, ASMBytecodeDumpService.ENABLE_BYTECODE_DUMP_DEFAULT_VALUE); if (enableBytecodeDump) { logger.info("wrapBytecodeDumpTransformer"); return BytecodeDumpTransformer.wrap(classFileTransformerDispatcher, profilerConfig); } return classFileTransformerDispatcher; } protected Module newApplicationContextModule(AgentOption agentOption, InterceptorRegistryBinder interceptorRegistryBinder) { return new ApplicationContextModule(agentOption, profilerConfig, serviceTypeRegistryService, interceptorRegistryBinder); } private DataSender newUdpStatDataSender() { Key<DataSender> statDataSenderKey = Key.get(DataSender.class, StatDataSender.class); return injector.getInstance(statDataSenderKey); } private DataSender newUdpSpanDataSender() { Key<DataSender> spanDataSenderKey = Key.get(DataSender.class, SpanDataSender.class); return injector.getInstance(spanDataSenderKey); } @Override public ProfilerConfig getProfilerConfig() { return profilerConfig; } public Injector getInjector() { return injector; } @Override public TraceContext getTraceContext() { return traceContext; } public DataSender getSpanDataSender() { return spanDataSender; } public InstrumentEngine getInstrumentEngine() { return instrumentEngine; } @Override public DynamicTransformTrigger getDynamicTransformTrigger() { return dynamicTransformTrigger; } @Override public ClassFileTransformerDispatcher getClassFileTransformerDispatcher() { return classFileDispatcher; } @Override public AgentInformation getAgentInformation() { return this.agentInformation; } @Override public void start() { this.agentInfoSender.start(); this.agentStatMonitor.start(); } @Override public void close() { this.agentInfoSender.stop(); this.agentStatMonitor.stop(); // Need to process stop this.spanDataSender.stop(); this.statDataSender.stop(); closeTcpDataSender(); } private void closeTcpDataSender() { final EnhancedDataSender tcpDataSender = this.tcpDataSender; if (tcpDataSender != null) { tcpDataSender.stop(); } final PinpointClient client = this.client; if (client != null) { client.close(); } final PinpointClientFactory clientFactory = this.clientFactory; if (clientFactory != null) { clientFactory.release(); } } }