All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.voovan.tools.log.LoggerThread Maven / Gradle / Ivy

package org.voovan.tools.log;

import org.voovan.tools.TEnv;
import org.voovan.tools.TString;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 日志输出线程
 *
 * @author helyho
 *
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class LoggerThread implements Runnable {
	private ConcurrentLinkedDeque logQueue;
	private ConcurrentLinkedDeque fileChangelogQueue;
	private OutputStream[] outputStreams;
	private AtomicBoolean finished = new AtomicBoolean(false);
	private int pause = 0; // 0: 正常 , 1: 暂停中, 2: 暂停

	/**
	 * 构造函数
	 * @param outputStreams 输出流数组
	 */
	public LoggerThread(OutputStream[] outputStreams) {
		this.logQueue = new ConcurrentLinkedDeque();
		this.fileChangelogQueue = new ConcurrentLinkedDeque();
		this.outputStreams = outputStreams;

	}

	/**
	 * 是否已经结束
	 * @return true: 结束, false: 运行中
	 */
	public boolean isFinished() {
		return finished.get();
	}

	/**
	 * 暂停日志输出
	 * @return true: 成功, false: 失败
	 */
	public boolean pause(){
		pause = 1;
		return TEnv.wait(3000, ()-> pause != 2);
	}

	/**
	 * 恢复日志输出
	 */
	public void unpause(){
		pause = 0;
	}

	/**
	 * 获取日志输出流集合
	 * @return 输出流数组
	 */
	public OutputStream[] getOutputStreams() {
		return outputStreams;
	}

	/**
	 * 设置日志输出流集合
	 * @param outputStreams 输出流数组
	 */
	public void setOutputStreams(OutputStream[] outputStreams) {
		if(outputStreams != null) {
			for (OutputStream outputStream : getOutputStreams()) {
				if (outputStream instanceof FileOutputStream) {
					try {
						((FileOutputStream) outputStream).close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}

		this.outputStreams = outputStreams;
	}

	/**
	 * 关闭所有的OutputStream
	 */
	public void closeAllOutputStreams() {
		try {
			for (OutputStream outputStream : outputStreams) {
				if (outputStream != null) {
					outputStream.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 刷新日志到目标设备
	 */
	public void flush(){
		for (OutputStream outputStream : outputStreams) {
			if (outputStream != null) {
				try {
					outputStream.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 增加消息
	 *
	 * @param msg 消息字符串
	 */
	public void addLogMessage(String msg) {
		logQueue.offer(msg);
	}

	@Override
	public void run() {
		String formatedMessage = null;

		boolean needFlush = false;

		try {
			while (Logger.isEnable() || logQueue.isEmpty()) {

				try {
					if (this.pause == 1) {
						flush();
						this.pause = 2;
					}

					if (this.pause != 0) {
						Thread.sleep(1);
						continue;
					}

					formatedMessage = logQueue.poll();

					//优化日志输出事件
					if (formatedMessage == null) {

						if (needFlush) {
							flush();
							needFlush = false;
						}

						Thread.sleep(10);
						continue;
					}

					if (formatedMessage != null && outputStreams != null) {
						for (OutputStream outputStream : outputStreams) {
							if (outputStream != null) {
								if (LoggerStatic.HAS_COLOR && !(outputStream instanceof PrintStream)) {
									//文件写入剔除出着色部分
									formatedMessage = TString.fastReplaceAll(formatedMessage, "\033\\[\\d{2}m", "");
								}

								//对于文件输出检测
								if(outputStream instanceof FileOutputStream) {
									//文件如果关闭则将消息加入缓冲,跳过
									if(!((FileOutputStream)outputStream).getChannel().isOpen()){
										fileChangelogQueue.add(formatedMessage);
										continue;
									} else {
										//如果文件输出可用,则尝试输出上一步缓冲中的消息
										while(true) {
											String message = fileChangelogQueue.poll();
											if(message!=null) {
												outputStream.write(message.getBytes());
											} else {
												break;
											}
										}
									}
								}

								outputStream.write(formatedMessage.getBytes());

								needFlush = true;
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			System.out.println("[FRAMEWORK] Main logger thread is terminaled");

			flush();

			finished.set(true);

		} finally {
			try {
				for (OutputStream outputStream : outputStreams) {
					if (outputStream != null) {
						outputStream.close();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	/**
	 * 获取 Web 访问日志记录对象
	 * @param outputStreams 输出流数组
	 * @return 日志记录线程对象
	 */
	public synchronized static LoggerThread start(OutputStream[] outputStreams) {
		LoggerThread loggerThread = new LoggerThread(outputStreams);
		Thread loggerMainThread = new Thread(loggerThread,"VOOVAN@LOGGER_THREAD");
		loggerMainThread.setDaemon(true);
		loggerMainThread.start();
		return loggerThread;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy