/* * 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.bootstrap.config; import com.navercorp.pinpoint.bootstrap.util.NumberUtils; import com.navercorp.pinpoint.bootstrap.util.spring.PropertyPlaceholderHelper; import com.navercorp.pinpoint.common.util.logger.CommonLogger; import com.navercorp.pinpoint.common.util.PropertyUtils; import com.navercorp.pinpoint.common.util.logger.StdoutCommonLoggerFactory; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Pattern; /** * @author emeroad * @author netspider */ public class DefaultProfilerConfig implements ProfilerConfig { private static final CommonLogger logger = StdoutCommonLoggerFactory.INSTANCE.getLogger(DefaultProfilerConfig.class.getName()); private static final String DEFAULT_IP = "127.0.0.1"; private final Properties properties; private final PropertyPlaceholderHelper propertyPlaceholderHelper = new PropertyPlaceholderHelper("${", "}"); @Deprecated public static final String INSTRUMENT_ENGINE_JAVASSIST = "JAVASSIST"; public static final String INSTRUMENT_ENGINE_ASM = "ASM"; public interface ValueResolver { String resolve(String value, Properties properties); } private static class BypassResolver implements ValueResolver { public static final ValueResolver RESOLVER = new BypassResolver(); @Override public String resolve(String value, Properties properties) { return value; } } private class PlaceHolderResolver implements ValueResolver { @Override public String resolve(String value, Properties properties) { if (value == null) { return null; } return propertyPlaceholderHelper.replacePlaceholders(value, properties); } } public static ProfilerConfig load(String pinpointConfigFileName) throws IOException { try { Properties properties = PropertyUtils.loadProperty(pinpointConfigFileName); return new DefaultProfilerConfig(properties); } catch (FileNotFoundException fe) { if (logger.isWarnEnabled()) { logger.warn(pinpointConfigFileName + " file does not exist. Please check your configuration."); } throw fe; } catch (IOException e) { if (logger.isWarnEnabled()) { logger.warn(pinpointConfigFileName + " file I/O error. Error:" + e.getMessage(), e); } throw e; } } private boolean profileEnable = false; private String profileInstrumentEngine = INSTRUMENT_ENGINE_ASM; private int interceptorRegistrySize = 1024*8; private String collectorSpanServerIp = DEFAULT_IP; private int collectorSpanServerPort = 9996; private String collectorStatServerIp = DEFAULT_IP; private int collectorStatServerPort = 9995; private String collectorTcpServerIp = DEFAULT_IP; private int collectorTcpServerPort = 9994; private int spanDataSenderWriteQueueSize = 1024 * 5; private int spanDataSenderSocketSendBufferSize = 1024 * 64 * 16; private int spanDataSenderSocketTimeout = 1000 * 3; private int spanDataSenderChunkSize = 1024 * 16; private String spanDataSenderSocketType = "OIO"; private int statDataSenderWriteQueueSize = 1024 * 5; private int statDataSenderSocketSendBufferSize = 1024 * 64 * 16; private int statDataSenderSocketTimeout = 1000 * 3; private int statDataSenderChunkSize = 1024 * 16; private String statDataSenderSocketType = "OIO"; private boolean tcpDataSenderCommandAcceptEnable = false; private boolean tcpDataSenderCommandActiveThreadEnable = false; private boolean tcpDataSenderCommandActiveThreadCountEnable = false; private boolean tcpDataSenderCommandActiveThreadDumpEnable = false; private boolean tcpDataSenderCommandActiveThreadLightDumpEnable = false; private boolean traceAgentActiveThread = true; private boolean traceAgentDataSource = false; private int dataSourceTraceLimitSize = 20; private int callStackMaxDepth = 512; private int jdbcSqlCacheSize = 1024; private boolean traceSqlBindValue = false; private int maxSqlBindValueSize = 1024; // Sampling private boolean samplingEnable = true; private int samplingRate = 1; // span buffering private boolean ioBufferingEnable; private int ioBufferingBufferSize; private int profileJvmCollectInterval; private String profileJvmVendorName; private boolean profilerJvmCollectDetailedMetrics; private Filter<String> profilableClassFilter = new SkipFilter<String>(); private final long DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL = 5 * 60 * 1000L; private long agentInfoSendRetryInterval = DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL; private String applicationServerType; private List<String> applicationTypeDetectOrder = Collections.emptyList(); private List<String> disabledPlugins = Collections.emptyList(); private boolean propagateInterceptorException = false; public DefaultProfilerConfig() { this.properties = new Properties(); } public DefaultProfilerConfig(Properties properties) { if (properties == null) { throw new NullPointerException("properties must not be null"); } this.properties = properties; readPropertyValues(); } @Override public int getInterceptorRegistrySize() { return interceptorRegistrySize; } @Override public String getCollectorSpanServerIp() { return collectorSpanServerIp; } @Override public int getCollectorSpanServerPort() { return collectorSpanServerPort; } @Override public String getCollectorStatServerIp() { return collectorStatServerIp; } @Override public int getCollectorStatServerPort() { return collectorStatServerPort; } @Override public String getCollectorTcpServerIp() { return collectorTcpServerIp; } @Override public int getCollectorTcpServerPort() { return collectorTcpServerPort; } @Override public int getStatDataSenderWriteQueueSize() { return statDataSenderWriteQueueSize; } @Override public int getStatDataSenderSocketSendBufferSize() { return statDataSenderSocketSendBufferSize; } @Override public int getStatDataSenderSocketTimeout() { return statDataSenderSocketTimeout; } @Override public String getStatDataSenderSocketType() { return statDataSenderSocketType; } @Override public int getSpanDataSenderWriteQueueSize() { return spanDataSenderWriteQueueSize; } @Override public int getSpanDataSenderSocketSendBufferSize() { return spanDataSenderSocketSendBufferSize; } @Override public boolean isTcpDataSenderCommandAcceptEnable() { return tcpDataSenderCommandAcceptEnable; } @Override public boolean isTcpDataSenderCommandActiveThreadEnable() { return tcpDataSenderCommandActiveThreadEnable; } @Override public boolean isTcpDataSenderCommandActiveThreadCountEnable() { return tcpDataSenderCommandActiveThreadCountEnable; } @Override public boolean isTcpDataSenderCommandActiveThreadDumpEnable() { return tcpDataSenderCommandActiveThreadDumpEnable; } @Override public boolean isTcpDataSenderCommandActiveThreadLightDumpEnable() { return tcpDataSenderCommandActiveThreadLightDumpEnable; } @Override public boolean isTraceAgentActiveThread() { return traceAgentActiveThread; } @Override public boolean isTraceAgentDataSource() { return traceAgentDataSource; } @Override public int getDataSourceTraceLimitSize() { return dataSourceTraceLimitSize; } @Override public int getSpanDataSenderSocketTimeout() { return spanDataSenderSocketTimeout; } @Override public String getSpanDataSenderSocketType() { return spanDataSenderSocketType; } @Override public int getSpanDataSenderChunkSize() { return spanDataSenderChunkSize; } @Override public int getStatDataSenderChunkSize() { return statDataSenderChunkSize; } @Override public boolean isProfileEnable() { return profileEnable; } @Override public int getJdbcSqlCacheSize() { return jdbcSqlCacheSize; } @Override public boolean isTraceSqlBindValue() { return traceSqlBindValue; } @Override public int getMaxSqlBindValueSize() { return maxSqlBindValueSize; } @Override public boolean isSamplingEnable() { return samplingEnable; } @Override public int getSamplingRate() { return samplingRate; } @Override public boolean isIoBufferingEnable() { return ioBufferingEnable; } @Override public int getIoBufferingBufferSize() { return ioBufferingBufferSize; } @Override public int getProfileJvmCollectInterval() { return profileJvmCollectInterval; } @Override public String getProfilerJvmVendorName() { return profileJvmVendorName; } @Override public boolean isProfilerJvmCollectDetailedMetrics() { return profilerJvmCollectDetailedMetrics; } @Override public long getAgentInfoSendRetryInterval() { return agentInfoSendRetryInterval; } @Override public Filter<String> getProfilableClassFilter() { return profilableClassFilter; } @Override public List<String> getApplicationTypeDetectOrder() { return applicationTypeDetectOrder; } @Override public List<String> getDisabledPlugins() { return disabledPlugins; } @Override public String getApplicationServerType() { return applicationServerType; } public void setApplicationServerType(String applicationServerType) { this.applicationServerType = applicationServerType; } @Override public int getCallStackMaxDepth() { return callStackMaxDepth; } public void setCallStackMaxDepth(int callStackMaxDepth) { this.callStackMaxDepth = callStackMaxDepth; } @Override public boolean isPropagateInterceptorException() { return propagateInterceptorException; } @Override public String getProfileInstrumentEngine() { return profileInstrumentEngine; } // for test void readPropertyValues() { // TODO : use Properties' default value instead of using a temp variable. final ValueResolver placeHolderResolver = new PlaceHolderResolver(); this.profileEnable = readBoolean("profiler.enable", true); this.profileInstrumentEngine = readString("profiler.instrument.engine", INSTRUMENT_ENGINE_ASM); this.interceptorRegistrySize = readInt("profiler.interceptorregistry.size", 1024*8); this.collectorSpanServerIp = readString("profiler.collector.span.ip", DEFAULT_IP, placeHolderResolver); this.collectorSpanServerPort = readInt("profiler.collector.span.port", 9996); this.collectorStatServerIp = readString("profiler.collector.stat.ip", DEFAULT_IP, placeHolderResolver); this.collectorStatServerPort = readInt("profiler.collector.stat.port", 9995); this.collectorTcpServerIp = readString("profiler.collector.tcp.ip", DEFAULT_IP, placeHolderResolver); this.collectorTcpServerPort = readInt("profiler.collector.tcp.port", 9994); this.spanDataSenderWriteQueueSize = readInt("profiler.spandatasender.write.queue.size", 1024 * 5); this.spanDataSenderSocketSendBufferSize = readInt("profiler.spandatasender.socket.sendbuffersize", 1024 * 64 * 16); this.spanDataSenderSocketTimeout = readInt("profiler.spandatasender.socket.timeout", 1000 * 3); this.spanDataSenderChunkSize = readInt("profiler.spandatasender.chunk.size", 1024 * 16); this.spanDataSenderSocketType = readString("profiler.spandatasender.socket.type", "OIO"); this.statDataSenderWriteQueueSize = readInt("profiler.statdatasender.write.queue.size", 1024 * 5); this.statDataSenderSocketSendBufferSize = readInt("profiler.statdatasender.socket.sendbuffersize", 1024 * 64 * 16); this.statDataSenderSocketTimeout = readInt("profiler.statdatasender.socket.timeout", 1000 * 3); this.statDataSenderChunkSize = readInt("profiler.statdatasender.chunk.size", 1024 * 16); this.statDataSenderSocketType = readString("profiler.statdatasender.socket.type", "OIO"); this.tcpDataSenderCommandAcceptEnable = readBoolean("profiler.tcpdatasender.command.accept.enable", false); this.tcpDataSenderCommandActiveThreadEnable = readBoolean("profiler.tcpdatasender.command.activethread.enable", false); this.tcpDataSenderCommandActiveThreadCountEnable = readBoolean("profiler.tcpdatasender.command.activethread.count.enable", false); this.tcpDataSenderCommandActiveThreadDumpEnable = readBoolean("profiler.tcpdatasender.command.activethread.threaddump.enable", false); this.tcpDataSenderCommandActiveThreadLightDumpEnable = readBoolean("profiler.tcpdatasender.command.activethread.threadlightdump.enable", false); this.traceAgentActiveThread = readBoolean("profiler.pinpoint.activethread", true); this.traceAgentDataSource = readBoolean("profiler.pinpoint.datasource", false); this.dataSourceTraceLimitSize = readInt("profiler.pinpoint.datasource.tracelimitsize", 20); // CallStack this.callStackMaxDepth = readInt("profiler.callstack.max.depth", 64); if (this.callStackMaxDepth < 2) { this.callStackMaxDepth = 2; } // JDBC this.jdbcSqlCacheSize = readInt("profiler.jdbc.sqlcachesize", 1024); this.traceSqlBindValue = readBoolean("profiler.jdbc.tracesqlbindvalue", false); this.samplingEnable = readBoolean("profiler.sampling.enable", true); this.samplingRate = readInt("profiler.sampling.rate", 1); // configuration for sampling and IO buffer this.ioBufferingEnable = readBoolean("profiler.io.buffering.enable", true); // it may be a problem to be here. need to modify(delete or move or .. ) this configuration. this.ioBufferingBufferSize = readInt("profiler.io.buffering.buffersize", 20); // JVM this.profileJvmCollectInterval = readInt("profiler.jvm.collect.interval", 1000); this.profileJvmVendorName = readString("profiler.jvm.vendor.name", null); this.profilerJvmCollectDetailedMetrics = readBoolean("profiler.jvm.collect.detailed.metrics", false); this.agentInfoSendRetryInterval = readLong("profiler.agentInfo.send.retry.interval", DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL); // service type this.applicationServerType = readString("profiler.applicationservertype", null); // application type detector order this.applicationTypeDetectOrder = readList("profiler.type.detect.order"); this.disabledPlugins = readList("profiler.plugin.disable"); // TODO have to remove // profile package included in order to test "call stack view". // this config must not be used in service environment because the size of profiling information will get heavy. // We may need to change this configuration to regular expression. final String profilableClass = readString("profiler.include", ""); if (!profilableClass.isEmpty()) { this.profilableClassFilter = new ProfilableClassFilter(profilableClass); } this.propagateInterceptorException = readBoolean("profiler.interceptor.exception.propagate", false); logger.info("configuration loaded successfully."); } @Override public String readString(String propertyName, String defaultValue) { return readString(propertyName, defaultValue, BypassResolver.RESOLVER); } private String readString(String propertyName, String defaultValue, ValueResolver valueResolver) { if (valueResolver == null) { throw new NullPointerException("valueResolver must not be null"); } String value = properties.getProperty(propertyName, defaultValue); value = valueResolver.resolve(value, properties); if (logger.isInfoEnabled()) { logger.info(propertyName + "=" + value); } return value; } @Override public int readInt(String propertyName, int defaultValue) { String value = properties.getProperty(propertyName); int result = NumberUtils.parseInteger(value, defaultValue); if (logger.isInfoEnabled()) { logger.info(propertyName + "=" + result); } return result; } @Override public DumpType readDumpType(String propertyName, DumpType defaultDump) { String propertyValue = properties.getProperty(propertyName); if (propertyValue == null) { propertyValue = defaultDump.name(); } String value = propertyValue.toUpperCase(); DumpType result; try { result = DumpType.valueOf(value); } catch (IllegalArgumentException e) { result = defaultDump; } if (logger.isInfoEnabled()) { logger.info(propertyName + "=" + result); } return result; } @Override public long readLong(String propertyName, long defaultValue) { String value = properties.getProperty(propertyName); long result = NumberUtils.parseLong(value, defaultValue); if (logger.isInfoEnabled()) { logger.info(propertyName + "=" + result); } return result; } @Override public List<String> readList(String propertyName) { String value = properties.getProperty(propertyName); if (value == null) { return Collections.emptyList(); } String[] orders = value.trim().split(","); return Arrays.asList(orders); } @Override public boolean readBoolean(String propertyName, boolean defaultValue) { String value = properties.getProperty(propertyName, Boolean.toString(defaultValue)); boolean result = Boolean.parseBoolean(value); if (logger.isInfoEnabled()) { logger.info(propertyName + "=" + result); } return result; } @Override public Map<String, String> readPattern(String propertyNamePatternRegex) { final Pattern pattern = Pattern.compile(propertyNamePatternRegex); final Map<String, String> result = new HashMap<String, String>(); for (Map.Entry<Object, Object> entry : properties.entrySet()) { if (entry.getKey() instanceof String && entry.getValue() instanceof String) { final String key = (String) entry.getKey(); if (pattern.matcher(key).matches()) { final String value = (String) entry.getValue(); result.put(key, value); } } } if (logger.isInfoEnabled()) { logger.info(propertyNamePatternRegex + "=" + result); } return result; } @Override public String toString() { StringBuilder builder = new StringBuilder(1024); builder.append("DefaultProfilerConfig{properties="); builder.append(properties); builder.append(", interceptorRegistrySize="); builder.append(interceptorRegistrySize); builder.append(", propertyPlaceholderHelper="); builder.append(propertyPlaceholderHelper); builder.append(", profileEnable="); builder.append(profileEnable); builder.append(", collectorSpanServerIp="); builder.append(collectorSpanServerIp); builder.append(", collectorSpanServerPort="); builder.append(collectorSpanServerPort); builder.append(", collectorStatServerIp="); builder.append(collectorStatServerIp); builder.append(", collectorStatServerPort="); builder.append(collectorStatServerPort); builder.append(", collectorTcpServerIp="); builder.append(collectorTcpServerIp); builder.append(", collectorTcpServerPort="); builder.append(collectorTcpServerPort); builder.append(", spanDataSenderWriteQueueSize="); builder.append(spanDataSenderWriteQueueSize); builder.append(", spanDataSenderSocketSendBufferSize="); builder.append(spanDataSenderSocketSendBufferSize); builder.append(", spanDataSenderSocketTimeout="); builder.append(spanDataSenderSocketTimeout); builder.append(", spanDataSenderChunkSize="); builder.append(spanDataSenderChunkSize); builder.append(", spanDataSenderSocketType="); builder.append(spanDataSenderSocketType); builder.append(", statDataSenderWriteQueueSize="); builder.append(statDataSenderWriteQueueSize); builder.append(", statDataSenderSocketSendBufferSize="); builder.append(statDataSenderSocketSendBufferSize); builder.append(", statDataSenderSocketTimeout="); builder.append(statDataSenderSocketTimeout); builder.append(", statDataSenderChunkSize="); builder.append(statDataSenderChunkSize); builder.append(", statDataSenderSocketType="); builder.append(statDataSenderSocketType); builder.append(", tcpDataSenderCommandAcceptEnable="); builder.append(tcpDataSenderCommandAcceptEnable); builder.append(", tcpDataSenderCommandActiveThreadEnable="); builder.append(tcpDataSenderCommandActiveThreadEnable); builder.append(", tcpDataSenderCommandActiveThreadCountEnable="); builder.append(tcpDataSenderCommandActiveThreadCountEnable); builder.append(", tcpDataSenderCommandActiveThreadDumpEnable="); builder.append(tcpDataSenderCommandActiveThreadDumpEnable); builder.append(", tcpDataSenderCommandActiveThreadLightDumpEnable="); builder.append(tcpDataSenderCommandActiveThreadLightDumpEnable); builder.append(", traceAgentActiveThread="); builder.append(traceAgentActiveThread); builder.append(", traceAgentDataSource="); builder.append(traceAgentDataSource); builder.append(", dataSourceTraceLimitSize="); builder.append(dataSourceTraceLimitSize); builder.append(", callStackMaxDepth="); builder.append(callStackMaxDepth); builder.append(", jdbcSqlCacheSize="); builder.append(jdbcSqlCacheSize); builder.append(", traceSqlBindValue="); builder.append(traceSqlBindValue); builder.append(", maxSqlBindValueSize="); builder.append(maxSqlBindValueSize); builder.append(", samplingEnable="); builder.append(samplingEnable); builder.append(", samplingRate="); builder.append(samplingRate); builder.append(", ioBufferingEnable="); builder.append(ioBufferingEnable); builder.append(", ioBufferingBufferSize="); builder.append(ioBufferingBufferSize); builder.append(", profileJvmCollectInterval="); builder.append(profileJvmCollectInterval); builder.append(", profilableClassFilter="); builder.append(profilableClassFilter); builder.append(", DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL="); builder.append(DEFAULT_AGENT_INFO_SEND_RETRY_INTERVAL); builder.append(", agentInfoSendRetryInterval="); builder.append(agentInfoSendRetryInterval); builder.append(", applicationServerType="); builder.append(applicationServerType); builder.append(", applicationTypeDetectOrder="); builder.append(applicationTypeDetectOrder); builder.append(", disabledPlugins="); builder.append(disabledPlugins); builder.append("}"); return builder.toString(); } }