提交 388d2481 编写于 作者: wu-sheng's avatar wu-sheng

Fix typo, and remove unnecessary lock in NoConcurrencyAceessObject. Refact...

Fix typo, and remove unnecessary lock in NoConcurrencyAceessObject. Refact FileWriter and SnifferConfigInitializer.
上级 fa81a0f6
......@@ -24,7 +24,8 @@ SkyWalking: Large-Scale Distributed Systems Tracing Infrastructure, also known D
* Support popular rpc frameworks, such as [dubbo](https://github.com/alibaba/dubbo), [dubbox](https://github.com/dangdangdotcom/dubbox), [motan](https://github.com/weibocom/motan) etc., trigger email-alert when application occurs unexpected exception.
* Auto-instrumentation mechenism, **no need to CHANGE any application source code**.
* Easy to deploy, **even in product mode** (since 2.0) . No need of Hadoop, HBase, or Cassandra Cluster.
* Pure Java server implementation. provide gRPC (since 2.0) and HTTP (since 2.1) cross-platform spans collecting service.
* Pure Java server implementation. provide HTTP (since 2.1) cross-platform spans collecting service.
* High performance stream process.
# Supported components
......
......@@ -19,20 +19,24 @@ public class ConfigInitializer {
initNextLevel(properties, rootConfigType, new ConfigDesc());
}
private static void initNextLevel(Properties properties, Class<?> recentConfigType, ConfigDesc parentDesc) throws IllegalArgumentException, IllegalAccessException {
private static void initNextLevel(Properties properties, Class<?> recentConfigType,
ConfigDesc parentDesc) throws IllegalArgumentException, IllegalAccessException {
for (Field field : recentConfigType.getFields()) {
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
String configKey = (parentDesc + "." + field.getName()).toLowerCase();
String value = properties.getProperty(configKey);
if (value != null) {
if (field.getType().equals(int.class))
Class<?> type = field.getType();
if (type.equals(int.class))
field.set(null, Integer.valueOf(value));
if (field.getType().equals(String.class))
else if (type.equals(String.class))
field.set(null, value);
if (field.getType().equals(long.class))
else if (type.equals(long.class))
field.set(null, Long.valueOf(value));
if (field.getType().equals(boolean.class))
else if (type.equals(boolean.class))
field.set(null, Boolean.valueOf(value));
else if (type.isEnum())
field.set(null, Enum.valueOf((Class<Enum>)type, value.toUpperCase()));
}
}
}
......@@ -44,7 +48,6 @@ public class ConfigInitializer {
}
}
class ConfigDesc {
private LinkedList<String> descs = new LinkedList<String>();
......
......@@ -2,16 +2,15 @@ package com.a.eye.skywalking.agent;
import com.a.eye.skywalking.agent.junction.SkyWalkingEnhanceMatcher;
import com.a.eye.skywalking.api.boot.ServiceManager;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.conf.SnifferConfigInitializer;
import com.a.eye.skywalking.api.logging.EasyLogResolver;
import com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefine;
import com.a.eye.skywalking.api.plugin.PluginBootstrap;
import com.a.eye.skywalking.api.plugin.PluginFinder;
import com.a.eye.skywalking.api.plugin.PluginException;
import com.a.eye.skywalking.api.plugin.PluginFinder;
import com.a.eye.skywalking.logging.ILog;
import com.a.eye.skywalking.logging.LogManager;
import java.lang.instrument.Instrumentation;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.type.TypeDescription;
......@@ -19,10 +18,6 @@ import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;
import java.io.File;
import java.lang.instrument.Instrumentation;
import java.net.URL;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.not;
......@@ -50,7 +45,7 @@ public class SkyWalkingAgent {
public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException {
logger = LogManager.getLogger(SkyWalkingAgent.class);
initConfig();
SnifferConfigInitializer.initialize();
final PluginFinder pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
......@@ -92,33 +87,4 @@ public class SkyWalkingAgent {
private static <T extends NamedElement> ElementMatcher.Junction<T> enhanceClassMatcher(PluginFinder pluginFinder) {
return new SkyWalkingEnhanceMatcher<T>(pluginFinder);
}
private static String generateLocationPath() {
return SkyWalkingAgent.class.getName().replaceAll("\\.", "/") + ".class";
}
private static void initConfig() {
Config.Agent.IS_PREMAIN_MODE = true;
Config.Agent.PATH = initAgentBasePath();
SnifferConfigInitializer.initialize();
}
/**
* Try to allocate the skywalking-agent.jar
* Some config files or output resources are from this path.
*
* @return the path, where the skywalking-agent.jar is.
*/
private static String initAgentBasePath() {
try {
String urlString = SkyWalkingAgent.class.getClassLoader().getSystemClassLoader().getResource(generateLocationPath()).toString();
urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!'));
return new File(new URL(urlString).getFile()).getParentFile().getAbsolutePath();
} catch (Exception e) {
logger.error("Failed to init config .", e);
return "";
}
}
}
package com.a.eye.skywalking.api.conf;
import com.a.eye.skywalking.api.logging.LogLevel;
public class Config {
public static class Agent {
public static String APPLICATION_CODE = "";
public static boolean IS_PREMAIN_MODE = false;
public static String PATH = "";
public static int SAMPLING_CYCLE = 1;
}
public static class Collector{
public static class Collector {
public static String SERVERS = "";
public static String SERVICE_NAME = "/segments";
......@@ -24,15 +22,14 @@ public class Config {
public static int SIZE = 512;
}
public static class Logging {
// log文件名
public static String LOG_FILE_NAME = "skywalking-api.log";
public static String FILE_NAME = "skywalking-api.log";
// log文件文件夹名字
public static String LOG_DIR_NAME = "logs";
public static String DIR = "";
// 最大文件大小
public static int MAX_LOG_FILE_LENGTH = 300 * 1024 * 1024;
// skywalking 系统错误文件日志
public static String SYSTEM_ERROR_LOG_FILE_NAME = "skywalking-api-error.log";
public static int MAX_FILE_SIZE = 300 * 1024 * 1024;
public static LogLevel LEVEL = LogLevel.DEBUG;
}
}
package com.a.eye.skywalking.api.conf;
import com.a.eye.skywalking.trace.GlobalIdGenerator;
public class Constants {
/**
* This is the version, which will be the first segment of traceid.
* Ref {@link GlobalIdGenerator#generate()}
*/
public final static String SDK_VERSION = "302017";
public static String PATH_SEPARATOR = System.getProperty("file.separator", "/");
public static String LINE_SEPARATOR = System.getProperty("line.separator", "\n");
}
......@@ -7,29 +7,59 @@ import com.a.eye.skywalking.api.util.StringUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
/**
* The <code>SnifferConfigInitializer</code> initializes all configs in several way.
*
* @author wusheng
* @see {@link #initialize()}, to learn more about how to initialzie.
*/
public class SnifferConfigInitializer {
private static ILog logger = LogManager.getLogger(SnifferConfigInitializer.class);
private static String CONFIG_FILE_NAME = "/sky-walking.config";
/**
* Try to locate config file, named {@link #CONFIG_FILE_NAME}, in following order:
* 1. Path from SystemProperty. {@link #loadConfigBySystemProperty()}
* 2. class path.
* 3. Path, where agent is. {@link #loadConfigFromAgentFolder()}
*
* If no found in any path, agent is still going to run in default config, {@link Config},
* but in initialization steps, these following configs must be set, by config file or system properties:
*
* 1. applicationCode. "-DapplicationCode=" or {@link Config.Agent#APPLICATION_CODE}
* 2. servers. "-Dservers=" or {@link Config.Collector#SERVERS}
*/
public static void initialize() {
InputStream configFileStream;
if (Config.Agent.IS_PREMAIN_MODE) {
configFileStream = fetchAuthFileInputStream();
} else {
configFileStream = SnifferConfigInitializer.class.getResourceAsStream("/sky-walking.config");
configFileStream = loadConfigBySystemProperty();
if (configFileStream == null) {
configFileStream = SnifferConfigInitializer.class.getResourceAsStream(CONFIG_FILE_NAME);
if (configFileStream == null) {
logger.info("No {} file found in class path.", CONFIG_FILE_NAME);
configFileStream = loadConfigFromAgentFolder();
}else{
logger.info("{} file found in class path.", CONFIG_FILE_NAME);
}
}
if (configFileStream == null) {
logger.info("Not provide sky-walking certification documents, sky-walking api run in default config.");
logger.info("No {} found, sky-walking is going to run in default config.", CONFIG_FILE_NAME);
} else {
try {
Properties properties = new Properties();
properties.load(configFileStream);
ConfigInitializer.initialize(properties, Config.class);
} catch (Exception e) {
logger.error("Failed to read the config file, sky-walking api run in default config.", e);
logger.error("Failed to read the config file, sky-walking is going to run in default config.", e);
}
}
......@@ -38,7 +68,7 @@ public class SnifferConfigInitializer {
Config.Agent.APPLICATION_CODE = applicationCode;
}
String servers = System.getProperty("servers");
if(!StringUtil.isEmpty(servers)) {
if (!StringUtil.isEmpty(servers)) {
Config.Collector.SERVERS = servers;
}
......@@ -50,12 +80,78 @@ public class SnifferConfigInitializer {
}
}
private static InputStream fetchAuthFileInputStream() {
try {
return new FileInputStream(Config.Agent.PATH + File.separator + "sky-walking.config");
} catch (Exception e) {
logger.warn("sky-walking.config is missing, use default config.");
/**
* Load the config file by the path, which is provided by system property, usually with a "-DconfigPath=" arg.
*
* @return the config file {@link InputStream}, or null if not exist.
*/
private static InputStream loadConfigBySystemProperty() {
String configPath = System.getProperty("configPath");
if (StringUtil.isEmpty(configPath)) {
return null;
}
File configFile = new File(configPath, CONFIG_FILE_NAME);
if (configFile.exists() && configFile.isFile()) {
try {
logger.info("{} found in path {}, according system property.", CONFIG_FILE_NAME, configPath);
return new FileInputStream(configFile);
} catch (FileNotFoundException e) {
logger.error(e, "Fail to load {} in path {}, according system property.", CONFIG_FILE_NAME, configPath);
}
}
logger.info("No {} found in path {}, according system property.", CONFIG_FILE_NAME, configPath);
return null;
}
/**
* Load the config file, where the agent jar is.
*
* @return the config file {@link InputStream}, or null if not exist.
*/
private static InputStream loadConfigFromAgentFolder() {
String agentBasePath = initAgentBasePath();
if (!StringUtil.isEmpty(agentBasePath)) {
File configFile = new File(agentBasePath, CONFIG_FILE_NAME);
if (configFile.exists() && configFile.isFile()) {
try {
logger.info("{} file found in agent folder.", CONFIG_FILE_NAME);
return new FileInputStream(configFile);
} catch (FileNotFoundException e) {
logger.error(e, "Fail to load {} in path {}, according auto-agent-folder mechanism.", CONFIG_FILE_NAME, agentBasePath);
}
}
}
logger.info("No {} file found in agent folder.", CONFIG_FILE_NAME);
return null;
}
/**
* Try to allocate the skywalking-agent.jar
* Some config files or output resources are from this path.
*
* @return he path, where the skywalking-agent.jar is
*/
private static String initAgentBasePath() {
String classResourcePath = SnifferConfigInitializer.class.getName().replaceAll("\\.", "/") + ".class";
URL resource = SnifferConfigInitializer.class.getClassLoader().getSystemClassLoader().getResource(classResourcePath);
if (resource != null) {
String urlString = resource.toString();
urlString = urlString.substring(urlString.indexOf("file:"), urlString.indexOf('!'));
File agentJarFile = null;
try {
agentJarFile = new File(new URL(urlString).getFile());
} catch (MalformedURLException e) {
logger.error(e, "Can not locate agent jar file by url:", urlString);
}
if (agentJarFile.exists()) {
return agentJarFile.getParentFile().getAbsolutePath();
}
}
logger.info("Can not locate agent jar file.");
return null;
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Constants;
import com.a.eye.skywalking.api.util.StringUtil;
import com.a.eye.skywalking.logging.ILog;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import static com.a.eye.skywalking.api.conf.Config.Logging.LEVEL;
import static com.a.eye.skywalking.api.logging.LogLevel.*;
/**
* Created by xin on 16-6-23.
* The <code>EasyLogger</code> is a simple implementation of {@link ILog}.
*
* @author wusheng
*/
public class EasyLogger implements ILog {
private Class toBeLoggerClass;
private Class targetClass;
public EasyLogger(Class toBeLoggerClass) {
this.toBeLoggerClass = toBeLoggerClass;
public EasyLogger(Class targetClass) {
this.targetClass = targetClass;
}
public void logger(LogLevel level, String message, Throwable e) {
Throwable dummyException = new Throwable();
StackTraceElement locations[] = dummyException.getStackTrace();
if (locations != null && locations.length > 2) {
if (ERROR.equals(level) || WARN.equals(level)) {
WriterFactory.getLogWriter().writeError(formatMessage(level, message, locations[2]));
} else {
WriterFactory.getLogWriter().write(formatMessage(level, message, locations[2]));
}
}
if (e != null) {
WriterFactory.getLogWriter().writeError(ThrowableFormatter.format(e));
}
private void logger(LogLevel level, String message, Throwable e) {
WriterFactory.getLogWriter().write(format(level, message, e));
}
private String replaceParam(String message, Object... parameters) {
int startSize = 0;
int parametersIndex = 0;
int index = -1;
int index;
String tmpMessage = message;
while ((index = message.indexOf("{}", startSize)) != -1) {
if (parametersIndex >= parameters.length) {
......@@ -53,69 +45,97 @@ public class EasyLogger implements ILog {
return tmpMessage;
}
String format(LogLevel level, String message, Throwable t) {
return StringUtil.join(' ', level.name(),
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),
targetClass.getSimpleName(),
": ",
message,
t == null ? "" : format(t)
);
}
String format(Throwable t) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
t.printStackTrace(new java.io.PrintWriter(buf, true));
String expMessage = buf.toString();
try {
buf.close();
} catch (IOException e) {
e.printStackTrace();
}
private String formatMessage(LogLevel level, String message, StackTraceElement caller) {
return level + " " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " "
+ caller.getClassName() + "." + caller.getMethodName() + "(" + caller.getFileName() + ":" + caller.getLineNumber() + ") " + message;
return Constants.LINE_SEPARATOR + expMessage;
}
@Override
public void info(String format) {
logger(INFO, format, null);
if (isInfoEnable())
logger(INFO, format, null);
}
@Override
public void info(String format, Object... arguments) {
logger(INFO, replaceParam(format, arguments), null);
if (isInfoEnable())
logger(INFO, replaceParam(format, arguments), null);
}
@Override
public void warn(String format, Object... arguments) {
logger(WARN, replaceParam(format, arguments), null);
if (isWarnEnable())
logger(WARN, replaceParam(format, arguments), null);
}
@Override
public void error(String format, Throwable e) {
logger(ERROR, format, e);
if (isErrorEnable())
logger(ERROR, format, e);
}
@Override
public void error(Throwable e, String format, Object... arguments) {
logger(ERROR, replaceParam(format, arguments), e);
if (isErrorEnable())
logger(ERROR, replaceParam(format, arguments), e);
}
@Override
public boolean isDebugEnable() {
return true;
return DEBUG.compareTo(LEVEL) >= 0;
}
@Override
public boolean isInfoEnable() {
return true;
return INFO.compareTo(LEVEL) >= 0;
}
@Override
public boolean isWarnEnable() {
return true;
return WARN.compareTo(LEVEL) >= 0;
}
@Override
public boolean isErrorEnable() {
return true;
return ERROR.compareTo(LEVEL) >= 0;
}
@Override
public void debug(String format) {
logger(DEBUG, format, null);
if (isDebugEnable()) {
logger(DEBUG, format, null);
}
}
@Override
public void debug(String format, Object... arguments) {
logger(DEBUG, replaceParam(format, arguments), null);
if (isDebugEnable()) {
logger(DEBUG, replaceParam(format, arguments), null);
}
}
@Override
public void error(String format) {
logger(ERROR, format, null);
if (isErrorEnable()) {
logger(ERROR, format, null);
}
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.conf.Constants;
import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.util.DaemonThreadFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Callable;
/**
* The <code>FileWriter</code> support async file output, by using a queue as buffer.
*
* @author wusheng
*/
public class FileWriter implements IWriter, EventHandler<LogMessageHolder> {
private static FileWriter instance;
private static Object createLock = new Object();
private Disruptor<LogMessageHolder> disruptor;
private RingBuffer<LogMessageHolder> buffer;
private FileOutputStream fileOutputStream;
private volatile boolean started = false;
private volatile int fileSize;
private volatile int lineNum;
public static FileWriter get() {
if (instance == null) {
synchronized (createLock) {
if (instance == null) {
instance = new FileWriter();
}
}
}
return instance;
}
private FileWriter() {
disruptor = new Disruptor<LogMessageHolder>(new EventFactory<LogMessageHolder>() {
@Override
public LogMessageHolder newInstance() {
return new LogMessageHolder();
}
}, 1024, DaemonThreadFactory.INSTANCE);
disruptor.handleEventsWith(this);
buffer = disruptor.getRingBuffer();
lineNum = 0;
disruptor.start();
}
@Override
public void onEvent(LogMessageHolder event, long sequence, boolean endOfBatch) throws Exception {
if (hasWriteStream()) {
try {
lineNum++;
write(event.getMessage() + Constants.LINE_SEPARATOR, endOfBatch);
} finally {
event.setMessage(null);
}
}
}
private void write(String message, boolean forceFlush) {
try {
fileOutputStream.write(message.getBytes());
fileSize += message.length();
if (forceFlush || lineNum % 20 == 0) {
fileOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
switchFile();
}
}
private void switchFile() {
if (fileSize > Config.Logging.MAX_FILE_SIZE) {
forceExecute(new Callable() {
@Override public Object call() throws Exception {
fileOutputStream.flush();
return null;
}
});
forceExecute(new Callable() {
@Override public Object call() throws Exception {
fileOutputStream.close();
return null;
}
});
forceExecute(new Callable() {
@Override public Object call() throws Exception {
new File(Config.Logging.DIR, Config.Logging.FILE_NAME)
.renameTo(new File(Config.Logging.DIR,
Config.Logging.FILE_NAME + new SimpleDateFormat(".yyyy_MM_dd_HH_mm_ss").format(new Date())));
return null;
}
});
forceExecute(new Callable() {
@Override public Object call() throws Exception {
fileOutputStream = null;
started = false;
return null;
}
});
}
}
private void forceExecute(Callable callable) {
try {
callable.call();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean hasWriteStream() {
if (fileOutputStream != null) {
return true;
}
if (!started) {
File logFilePath = new File(Config.Logging.DIR);
if (!logFilePath.exists()) {
logFilePath.mkdirs();
} else if (!logFilePath.isDirectory()) {
System.err.println("Log dir(" + Config.Logging.DIR + ") is not a directory.");
}
try {
fileOutputStream = new FileOutputStream(new File(logFilePath, Config.Logging.FILE_NAME), true);
fileSize = Long.valueOf(new File(logFilePath, Config.Logging.FILE_NAME).length()).intValue();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
started = true;
}
return fileOutputStream != null;
}
@Override
public void write(String message) {
long next = buffer.next();
try {
LogMessageHolder messageHolder = buffer.get(next);
messageHolder.setMessage(message);
} finally {
buffer.publish(next);
}
}
}
......@@ -2,6 +2,4 @@ package com.a.eye.skywalking.api.logging;
public interface IWriter {
void write(String message);
void writeError(String message);
}
......@@ -3,6 +3,6 @@ package com.a.eye.skywalking.api.logging;
/**
* Created by xin on 2016/12/7.
*/
public enum LogLevel {
INFO, DEBUG, WARN, ERROR
public enum LogLevel{
DEBUG, INFO, WARN, ERROR;
}
package com.a.eye.skywalking.api.logging;
/**
* The <code>LogMessageHolder</code> is a {@link String} holder,
* in order to in-process propagation String across the disruptor queue.
*
* @author wusheng
*/
public class LogMessageHolder {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SyncFileWriter implements IWriter {
private static SyncFileWriter writer;
private FileOutputStream os;
private int bufferSize;
private static final Object lock = new Object();
private SyncFileWriter() {
try {
File logFilePath = new File(Config.Agent.PATH, Config.Logging.LOG_DIR_NAME);
if (!logFilePath.exists()) {
logFilePath.mkdirs();
}
os = new FileOutputStream(new File(logFilePath, Config.Logging.LOG_FILE_NAME), true);
bufferSize = Long.valueOf(new File(logFilePath, Config.Logging.LOG_FILE_NAME).length()).intValue();
} catch (IOException e) {
writeErrorLog(e);
}
}
public static IWriter instance() {
if (writer == null) {
writer = new SyncFileWriter();
}
return writer;
}
public void write(String message) {
writeLogRecord(message);
switchLogFileIfNecessary();
}
@Override
public void writeError(String message) {
this.write(message);
}
private void writeLogRecord(String message) {
try {
os.write(message.getBytes());
os.write("\n".getBytes());
bufferSize += message.length();
} catch (IOException e) {
writeErrorLog(e);
}
}
private void switchLogFileIfNecessary() {
if (bufferSize > Config.Logging.MAX_LOG_FILE_LENGTH) {
synchronized (lock) {
if (bufferSize > Config.Logging.MAX_LOG_FILE_LENGTH) {
try {
closeInputStream();
renameLogFile();
revertInputStream();
} catch (IOException e) {
writeErrorLog(e);
}
bufferSize = 0;
}
}
}
}
private void revertInputStream() throws FileNotFoundException {
os = new FileOutputStream(new File(Config.Logging.LOG_DIR_NAME, Config.Logging.LOG_FILE_NAME), true);
}
private void renameLogFile() {
new File(Config.Logging.LOG_DIR_NAME, Config.Logging.LOG_FILE_NAME)
.renameTo(new File(Config.Logging.LOG_DIR_NAME, Config.Logging.LOG_FILE_NAME + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
}
private void closeInputStream() throws IOException {
this.os.flush();
this.os.close();
}
private void writeErrorLog(Throwable e) {
FileOutputStream fileOutputStream = null;
try {
File file = new File(Config.Logging.LOG_DIR_NAME, Config.Logging.SYSTEM_ERROR_LOG_FILE_NAME);
fileOutputStream = new FileOutputStream(file, true);
fileOutputStream.write(("Failed to init sync File Writer.\n" + ThrowableFormatter.format(e)).getBytes());
} catch (Exception e1) {
System.err.print(ThrowableFormatter.format(e1));
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e1) {
System.err.print(ThrowableFormatter.format(e1));
}
}
}
}
}
package com.a.eye.skywalking.api.logging;
public class STDOutWriter implements IWriter {
public enum SystemOutWriter implements IWriter {
INSTANCE;
@Override
public void write(String message) {
System.out.println(message);
}
@Override
public void writeError(String message) {
System.err.println(message);
}
}
package com.a.eye.skywalking.api.logging;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Created by xin on 16-6-24.
*/
public class ThrowableFormatter {
public static String format(Throwable e) {
ByteArrayOutputStream buf = new ByteArrayOutputStream();
e.printStackTrace(new java.io.PrintWriter(buf, true));
String expMessage = buf.toString();
try {
buf.close();
} catch (IOException e1) {
System.err.println("Failed to close throwable stack stream.");
e.printStackTrace();
}
return expMessage;
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.util.StringUtil;
public class WriterFactory {
public static IWriter getLogWriter(){
if (Config.Agent.IS_PREMAIN_MODE){
return SyncFileWriter.instance();
if (!StringUtil.isEmpty(Config.Logging.DIR)){
return FileWriter.get();
}else{
return new STDOutWriter();
return SystemOutWriter.INSTANCE;
}
}
}
......@@ -2,10 +2,9 @@ package com.a.eye.skywalking.api.plugin.interceptor.assist;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.InterceptorException;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
/**
* {@link NoCocurrencyAceessObject} is method invocation counter,
* {@link NoConcurrencyAceessObject} is method invocation counter,
* when {@link #whenEnter(EnhancedClassInstanceContext, Runnable)}, counter + 1;
* and when {@link #whenExist(EnhancedClassInstanceContext, Runnable)}, counter -1;
*
......@@ -13,22 +12,16 @@ import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAround
*
* @author wusheng
*/
public class NoCocurrencyAceessObject {
protected String invokeCounterKey = "__$invokeCounterKey";
protected Object invokeCounterInstLock = new Object();
public class NoConcurrencyAceessObject {
private static String invokeCounterKey = "__$invokeCounterKey";
public void whenEnter(EnhancedClassInstanceContext context, Runnable runnable) {
if (!context.isContain(invokeCounterKey)) {
synchronized (invokeCounterInstLock) {
if (!context.isContain(invokeCounterKey)) {
context.set(invokeCounterKey, 0);
}
}
context.set(invokeCounterKey, 0);
}
int counter = context.get(invokeCounterKey,
Integer.class);
if(++counter == 1){
if (++counter == 1) {
runnable.run();
}
context.set(invokeCounterKey, counter);
......@@ -41,7 +34,7 @@ public class NoCocurrencyAceessObject {
}
int counter = context.get(invokeCounterKey,
Integer.class);
if(--counter == 0){
if (--counter == 0) {
runnable.run();
}
context.set(invokeCounterKey, counter);
......
package com.a.eye.skywalking.api.conf;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class ConstantsTest {
@Test
public void testSDKVersion(){
Assert.assertEquals("302017", Constants.SDK_VERSION);
}
}
package com.a.eye.skywalking.api.conf;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
......@@ -11,27 +10,15 @@ public class SnifferConfigInitializerTest {
@Test
public void testInitialize(){
Config.Agent.IS_PREMAIN_MODE = false;
SnifferConfigInitializer.initialize();
Assert.assertEquals("crmApp", Config.Agent.APPLICATION_CODE);
Assert.assertEquals("127.0.0.1:8080", Config.Collector.SERVERS);
Assert.assertNotNull(Config.Buffer.SIZE);
Assert.assertNotNull(Config.Logging.LOG_DIR_NAME);
Assert.assertNotNull(Config.Logging.LOG_FILE_NAME);
Assert.assertNotNull(Config.Logging.MAX_LOG_FILE_LENGTH);
Assert.assertNotNull(Config.Logging.SYSTEM_ERROR_LOG_FILE_NAME);
}
@Test(expected = ExceptionInInitializerError.class)
public void testErrorInitialize(){
Config.Agent.IS_PREMAIN_MODE = true;
SnifferConfigInitializer.initialize();
}
@AfterClass
public static void reset(){
Config.Agent.IS_PREMAIN_MODE = false;
Assert.assertNotNull(Config.Logging.DIR);
Assert.assertNotNull(Config.Logging.FILE_NAME);
Assert.assertNotNull(Config.Logging.MAX_FILE_SIZE);
Assert.assertNotNull(Config.Logging.FILE_NAME);
}
}
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.conf.Constants;
import java.io.PrintStream;
import org.junit.AfterClass;
import org.junit.Assert;
......@@ -26,8 +26,6 @@ public class EasyLoggerTest {
@Test
public void testLog(){
Config.Agent.IS_PREMAIN_MODE = false;
PrintStream output = Mockito.mock(PrintStream.class);
System.setOut(output);
PrintStream err = Mockito.mock(PrintStream.class);
......@@ -50,12 +48,20 @@ public class EasyLoggerTest {
logger.error("hello world", new NullPointerException());
logger.error(new NullPointerException(),"hello {}", "world");
Mockito.verify(output,times(4))
.println(anyString());
Mockito.verify(err,times(7))
Mockito.verify(output,times(9))
.println(anyString());
}
@Test
public void testFormat() {
NullPointerException exception = new NullPointerException();
EasyLogger logger = new EasyLogger(EasyLoggerTest.class);
String formatLines = logger.format(exception);
String[] lines = formatLines.split(Constants.LINE_SEPARATOR);
Assert.assertEquals("java.lang.NullPointerException", lines[1]);
Assert.assertEquals("\tat com.a.eye.skywalking.api.logging.EasyLoggerTest.testFormat(EasyLoggerTest.java:57)", lines[2]);
}
@AfterClass
public static void reset(){
System.setOut(outRef);
......
package com.a.eye.skywalking.api.logging;
import com.a.eye.skywalking.api.conf.Config;
import com.a.eye.skywalking.api.conf.Constants;
import java.io.File;
import java.io.IOException;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* @author wusheng
*/
public class FileWriterTest {
@BeforeClass
public static void beforeTestFile() throws IOException {
Config.Logging.MAX_FILE_SIZE = 10;
File directory = new File("");
Config.Logging.DIR = directory.getCanonicalPath() + Constants.PATH_SEPARATOR + "/log-test/";
}
@Test
public void testWriteFile() throws InterruptedException {
FileWriter writer = FileWriter.get();
for (int i = 0; i < 100; i++) {
writer.write("abcd");
}
Thread.sleep(10000L);
}
@AfterClass
public static void clear() {
Config.Logging.MAX_FILE_SIZE = 300 * 1024 * 1024;
deleteDir(new File(Config.Logging.DIR));
Config.Logging.DIR = "";
}
private static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
}
......@@ -12,14 +12,12 @@ import static org.mockito.Mockito.times;
/**
* Created by wusheng on 2017/2/28.
*/
public class STDOutWriterTest {
public class SystemOutWriterTest {
private static PrintStream outRef;
private static PrintStream errRef;
@BeforeClass
public static void initAndHoldOut(){
outRef = System.out;
errRef = System.err;
}
@Test
......@@ -27,19 +25,7 @@ public class STDOutWriterTest {
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setOut(mockStream);
STDOutWriter writer = new STDOutWriter();
writer.write("hello");
Mockito.verify(mockStream,times(1)).println(anyString());
}
@Test
public void testWriteError(){
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setErr(mockStream);
STDOutWriter writer = new STDOutWriter();
writer.writeError("hello");
SystemOutWriter.INSTANCE.write("hello");
Mockito.verify(mockStream,times(1)).println(anyString());
}
......@@ -47,6 +33,5 @@ public class STDOutWriterTest {
@AfterClass
public static void reset(){
System.setOut(outRef);
System.setErr(errRef);
}
}
package com.a.eye.skywalking.api.logging;
import org.junit.Assert;
import org.junit.Test;
/**
* Created by wusheng on 2017/2/28.
*/
public class ThrowableFormatterTest {
@Test
public void testFormat() {
NullPointerException exception = new NullPointerException();
String formatLines = ThrowableFormatter.format(exception);
String[] lines = formatLines.split(System.lineSeparator());
Assert.assertEquals("java.lang.NullPointerException", lines[0]);
Assert.assertEquals("\tat com.a.eye.skywalking.api.logging.ThrowableFormatterTest.testFormat(ThrowableFormatterTest.java:12)", lines[1]);
}
}
......@@ -15,7 +15,7 @@ public class WriterFactoryTest {
private static PrintStream errRef;
@BeforeClass
public static void initAndHoldOut(){
public static void initAndHoldOut() {
errRef = System.err;
}
......@@ -24,19 +24,18 @@ public class WriterFactoryTest {
* reset {@link System#out} to a Mock object, for avoid a console system.error.
*/
@Test
public void testGetLogWriter(){
Config.Agent.IS_PREMAIN_MODE = true;
public void testGetLogWriter() {
PrintStream mockStream = Mockito.mock(PrintStream.class);
System.setErr(mockStream);
Assert.assertEquals(SyncFileWriter.instance(), WriterFactory.getLogWriter());
Assert.assertEquals(SystemOutWriter.INSTANCE, WriterFactory.getLogWriter());
Config.Agent.IS_PREMAIN_MODE = false;
Assert.assertTrue(WriterFactory.getLogWriter() instanceof STDOutWriter);
Config.Logging.DIR = "/only/test/folder";
Assert.assertTrue(WriterFactory.getLogWriter() instanceof FileWriter);
}
@AfterClass
public static void reset(){
Config.Agent.IS_PREMAIN_MODE = false;
public static void reset() {
Config.Logging.DIR = "";
System.setErr(errRef);
}
}
package com.a.eye.skywalking.api.plugin.assist;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.assist.NoCocurrencyAceessObject;
import com.a.eye.skywalking.api.plugin.interceptor.assist.NoConcurrencyAceessObject;
import org.junit.Assert;
import org.junit.Test;
/**
* @author wusheng
*/
public class NoCocurrencyAceessObjectTest {
public class NoConcurrencyAceessObjectTest {
@Test
public void testEntraExitCounter(){
NoCocurrencyAceessObject object = new NoCocurrencyAceessObject();
NoConcurrencyAceessObject object = new NoConcurrencyAceessObject();
final EnhancedClassInstanceContext context = new EnhancedClassInstanceContext();
object.whenEnter(context, new Runnable() {
@Override
......
......@@ -2,7 +2,7 @@ package com.a.eye.skywalking.plugin.jedis.v2;
import com.a.eye.skywalking.api.context.ContextManager;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.assist.NoCocurrencyAceessObject;
import com.a.eye.skywalking.api.plugin.interceptor.assist.NoConcurrencyAceessObject;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
......@@ -17,7 +17,7 @@ import com.a.eye.skywalking.trace.tag.Tags;
*
* @author zhangxin
*/
public class JedisMethodInterceptor extends NoCocurrencyAceessObject implements InstanceMethodsAroundInterceptor {
public class JedisMethodInterceptor extends NoConcurrencyAceessObject implements InstanceMethodsAroundInterceptor {
/**
* The key name that redis connection information in {@link EnhancedClassInstanceContext#context}.
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册