org.voovan.tools.log.Formater Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of voovan-framework Show documentation
Show all versions of voovan-framework Show documentation
Voovan is a java framwork and it not depends on any third-party framework.
package org.voovan.tools.log;
import org.voovan.Global;
import org.voovan.tools.*;
import org.voovan.tools.hashwheeltimer.HashWheelTask;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
/**
* 格式化日志信息并输出
*
*使用包括特殊的定义{{}}
*{{s}}: 一个空格
*{{t}}: 制表符
*{{n}}: 换行
*================================
*{{I}}: 消息内容,即要展示的日志内容
*{{F}}: 源码文件名
*{{SI}}: 栈信息输出
*{{L}}: 当前代码的行号
*{{M}}: 当前代码的方法名
*{{C}}: 当前代码的类名称
*{{T}}: 当前线程名
*{{D}}: 当前系统时间
*{{R}}: 从启动到当前代码执行的事件
* ================================
* {{F?}} 前景颜色: ?为0-7,分别为: 0=黑,1=红,2=绿,3=黄,4=蓝,5=紫,6=青,7=白
* {{B?}} 背景颜色: ?为0-7,分别为: 0=黑,1=红,2=绿,3=黄,4=蓝,5=紫,6=青,7=白
* @author helyho
*
* Voovan Framework.
* WebSite: https://github.com/helyho/Voovan
* Licence: Apache v2 License
*/
public class Formater {
private String template;
private volatile LoggerThread loggerThread;
private List logLevel;
private String dateStamp;
private int maxLineLength = -1;
private String lineHead;
private String lineTail;
private static String DATE = TDateTime.now("yyyyMMdd");
static{
Global.getHashWheelTimer().addTask(new HashWheelTask() {
@Override
public void run() {
DATE = TDateTime.now("yyyyMMdd");
}
}, 1);
}
/**
* 构造函数
* @param template 模板
*/
public Formater(String template) {
this.template = template;
logLevel = new Vector();
logLevel.addAll(TObject.asList(LoggerStatic.getLogConfig("LogLevel", LoggerStatic.LOG_LEVEL).split(",")));
dateStamp = DATE;
Global.getHashWheelTimer().addTask(new HashWheelTask() {
@Override
public void run() {
if(Logger.isEnable()) {
//如果日志发生变化则产生新的文件
if (!dateStamp.equals(DATE)) {
loggerThread.setOutputStreams(getOutputStreams());
}
//压缩历史日志文件
packLogFile();
}
}
}, 1);
}
/**
* 获取日志记录级别信息
* @return 获取日志记录级别信息
*/
public List getLogLevel() {
return logLevel;
}
/**
* 获得当前栈元素信息
* @return 栈信息元素
*/
public static StackTraceElement currentStackLine() {
StackTraceElement[] stackTraceElements = TEnv.getStackElements();
return stackTraceElements[6];
}
/**
* 获取当前线程名称
* @return 当前线程名
*/
private static String currentThreadName() {
Thread currentThread = Thread.currentThread();
return currentThread.getName();
}
private int realLength(String str){
return str.replaceAll("\\{\\{n\\}\\}","").replaceAll("\\{\\{.*\\}\\}"," ").replaceAll("\033\\[\\d{2}m", "").length();
}
/**
* 消息缩进
* @param message 消息对象
* @return 随进后的消息
*/
private String lineFormat(Message message){
return TString.tokenReplace(template, message.getTokens()) + TFile.getLineSeparator();
}
/**
* 构造消息格式化 Token
* @param message 消息对象
*/
public void fillTokens(Message message){
Map tokens = new HashMap();
message.setTokens(tokens);
//Message和栈信息公用
tokens.put("t", "\t");
tokens.put("s", " ");
tokens.put("n", TFile.getLineSeparator());
tokens.put("I", message.getMessage());
if(LoggerStatic.HAS_COLOR) {
if (!TEnv.OS_NAME.toUpperCase().contains("WINDOWS")) {
tokens.put("F0", "\033[30m");
tokens.put("F1", "\033[31m");
tokens.put("F2", "\033[32m");
tokens.put("F3", "\033[33m");
tokens.put("F4", "\033[34m");
tokens.put("F5", "\033[35m");
tokens.put("F6", "\033[36m");
tokens.put("F7", "\033[37m");
tokens.put("FD", "\033[39m");
tokens.put("B0", "\033[40m");
tokens.put("B1", "\033[41m");
tokens.put("B2", "\033[42m");
tokens.put("B3", "\033[43m");
tokens.put("B4", "\033[44m");
tokens.put("B5", "\033[45m");
tokens.put("B6", "\033[46m");
tokens.put("B7", "\033[47m");
tokens.put("BD", "\033[49m");
} else {
tokens.put("F0", "");
tokens.put("F1", "");
tokens.put("F2", "");
tokens.put("F3", "");
tokens.put("F4", "");
tokens.put("F5", "");
tokens.put("F6", "");
tokens.put("F7", "");
tokens.put("FD", "");
tokens.put("B0", "");
tokens.put("B1", "");
tokens.put("B2", "");
tokens.put("B3", "");
tokens.put("B4", "");
tokens.put("B5", "");
tokens.put("B6", "");
tokens.put("B7", "");
tokens.put("BD", "");
}
}
if(LoggerStatic.HAS_LEVEL) {
tokens.put("P", TObject.nullDefault(message.getLevel(), "INFO")); //信息级别
}
if(LoggerStatic.HAS_THREAD) {
tokens.put("T", currentThreadName()); //线程
}
if(LoggerStatic.HAS_DATE) {
tokens.put("D", TDateTime.now("yyyy-MM-dd HH:mm:ss:SS z")); //当前时间
}
if(LoggerStatic.HAS_RUNTIME) {
tokens.put("R", Long.toString(System.currentTimeMillis() - LoggerStatic.getStartTimeMillis())); //系统运行时间
}
if(LoggerStatic.HAS_STACK) {
StackTraceElement stackTraceElement = currentStackLine();
tokens.put("SI", stackTraceElement.toString()); //堆栈信息
tokens.put("L", Integer.toString((stackTraceElement.getLineNumber()))); //行号
tokens.put("M", stackTraceElement.getMethodName()); //方法名
tokens.put("F", stackTraceElement.getFileName()); //源文件名
tokens.put("C", stackTraceElement.getClassName()); //类名
}
}
/**
* 格式化消息
* @param message 消息对象
* @return 格式化后的消息
*/
public String format(Message message) {
fillTokens(message);
return lineFormat(message);
}
/**
* 简单格式化
* @param message 消息对象
* @return 格式化后的消息
*/
public String simpleFormat(Message message){
//消息缩进
fillTokens(message);
return TString.tokenReplace(message.getMessage(), message.getTokens());
}
/**
* 消息类型是否可以记录
* @param message 消息对象
* @return 是否可写入
*/
public boolean messageWritable(Message message){
if(logLevel.contains("ALL")){
return true;
}
else if(logLevel.contains(message.getLevel())){
return true;
}else{
return false;
}
}
/**
* 写入消息对象,在进行格式化后的写入
* @param message 消息对象
*/
public void writeFormatedLog(Message message) {
if(messageWritable(message)){
if("SIMPLE".equals(message.getLevel())){
writeLog(simpleFormat(message)+"\r\n");
}else{
writeLog(format(message));
}
}
}
/**
* 写入消息
* @param msg 消息字符串
*/
public synchronized void writeLog(String msg) {
if(Logger.isEnable()){
if (loggerThread == null || loggerThread.isFinished()) {
this.loggerThread = LoggerThread.start(getOutputStreams());
}
loggerThread.addLogMessage(msg);
}
}
/**
* 压缩历史日志文件
*/
private void packLogFile(){
long packSize = (long) (Double.valueOf(LoggerStatic.getLogConfig("PackSize", "1024")) * 1024L * 1024L);
final String logFilePath = getFormatedLogFilePath();
final String tmpFilePath = TFile.getFileDirectory(logFilePath) + ".tmpPackLog";
File logFile = new File(logFilePath);
File tmpLogFile = new File(tmpFilePath);
if(packSize > 0 && logFile.length() > packSize){
//暂停日志输出
try {
if (loggerThread.pause()) {
try {
TFile.moveFile(logFile, tmpLogFile);
//开启独立线程进行文件压缩
Global.getThreadPool().execute(()->{
String logFileExtendNam = TFile.getFileExtension(logFilePath);
String innerLogFilePath = logFilePath.replace("." + logFileExtendNam, "");
try {
File packFile = new File(innerLogFilePath + TDateTime.now("HHmmss") + "." + logFileExtendNam + ".gz");
TZip.encodeGZip(tmpLogFile, packFile);
TFile.deleteFile(tmpLogFile);
} catch (Exception e) {
System.out.println("[ERROR] Pack log file " + innerLogFilePath + "error: ");
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
//查找并关闭旧的文件输出流
for (OutputStream outputStream : loggerThread.getOutputStreams()) {
if (outputStream instanceof FileOutputStream) {
try {
((FileOutputStream)outputStream).close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//重置文件输出流
loggerThread.setOutputStreams(getOutputStreams());
}
} finally {
//恢复日志输出
loggerThread.unpause();
}
}
}
/**
* 获取格式化后的日志文件路径
* @return 返回日志文件名
*/
public static String getFormatedLogFilePath(){
String filePath = "";
String logFile = LoggerStatic.getLogConfig("LogFile", LoggerStatic.LOG_FILE);
if(logFile!=null) {
Map tokens = new HashMap();
tokens.put("D", DATE);
tokens.put("WorkDir", TFile.getContextPath());
filePath = TString.tokenReplace(logFile, tokens);
String fileDirectory = filePath.substring(0, filePath.lastIndexOf(File.separator));
File loggerFile = new File(fileDirectory);
if (!loggerFile.exists()) {
if(!loggerFile.mkdirs()){
System.out.println("Logger file directory error!");
}
}
}else{
filePath = null;
}
return filePath;
}
/**
* 获得一个实例
* @return 新的实例
*/
public static Formater newInstance() {
return new Formater(LoggerStatic.LOG_TEMPLATE);
}
/**
* 获取输出流
* @return 输出流数组
*/
protected static OutputStream[] getOutputStreams(){
String[] LogTypes = LoggerStatic.getLogConfig("LogType", LoggerStatic.LOG_TYPE).split(",");
String logFilePath = getFormatedLogFilePath();
OutputStream[] outputStreams = new OutputStream[LogTypes.length];
for (int i = 0; i < LogTypes.length; i++) {
String logType = LogTypes[i].trim();
switch (logType) {
case "STDOUT":
outputStreams[i] = System.out;
break;
case "STDERR":
outputStreams[i] = System.err;
break;
case "FILE":
try {
outputStreams[i] = new FileOutputStream(logFilePath,true);
} catch (FileNotFoundException e) {
System.out.println("log file: ["+logFilePath+"] is not found.\r\n");
}
break;
default:
break;
}
}
return outputStreams;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy