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

org.yx.log.impl.LogQueue Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
/**
 * Copyright (C) 2016 - 2030 youtongluan.
 *
 * 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 org.yx.log.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

import org.yx.common.matcher.BooleanMatcher;
import org.yx.common.matcher.Matchers;
import org.yx.conf.AppInfo;
import org.yx.main.SumkThreadPool;

public abstract class LogQueue implements Runnable {

	protected final String name;

	private int interval;

	private long handleLogCount;

	private boolean jobStarted;

	protected final BlockingQueue queue;

	private Predicate matcher = BooleanMatcher.FALSE;

	public LogQueue(String name) {
		this.name = name;
		this.interval = AppInfo.getInt("sumk.log.interval." + name, 1000);
		this.queue = new LinkedBlockingQueue<>(Integer.getInteger("sumk.log.queue." + name, 2_0000));
	}

	protected boolean accept(LogObject logObject) {
		String module = logObject.getLoggerName();
		return this.matcher.test(module);
	}

	protected abstract void flush(boolean idle) throws Exception;

	public void config(Map configMap) {
		String patterns = configMap == null ? null : configMap.get(LogAppenders.MODULE);
		if (patterns == null || patterns.isEmpty()) {
			patterns = "*";
		}
		this.matcher = Matchers.createWildcardMatcher(patterns, 1);
		LogAppenders.consoleLog.debug("{} set matcher :{}", this.name, this.matcher);
	}

	public final String name() {
		return this.name;
	}

	public boolean offer(LogObject logObject) {
		if (!accept(logObject)) {
			return false;
		}
		return queue.offer(logObject);
	}

	protected abstract void output(List list) throws Exception;

	@Override
	public void run() {
		Thread.currentThread().setName("log-" + this.name);

		while (true) {
			try {
				this.flush(this.consume());
			} catch (Throwable e) {
				LogAppenders.consoleLog.debug("日志消费失败," + e.toString(), e);

				if (Thread.currentThread().isInterrupted() || e.getClass() == InterruptedException.class) {
					LogAppenders.consoleLog.warn("{}日志停止了", this.name);
					Thread.currentThread().interrupt();
					return;
				}
			}
		}

	}

	private boolean consume() throws Exception {
		LogObject message = queue.poll(interval, TimeUnit.MILLISECONDS);
		if (message == null) {
			return true;
		}
		int batch = Math.min(queue.size() + 10, 100);
		List list = new ArrayList<>(batch);
		list.add(message);
		queue.drainTo(list, batch - 1);

		while (list.size() > 0) {
			output(list);
			this.handleLogCount += list.size();
			list.clear();
			queue.drainTo(list, batch);
		}
		return false;
	}

	public synchronized boolean start(Map map) {
		if (map == null) {
			map = Collections.emptyMap();
		}
		if (!onStart(map)) {
			return false;
		}
		LogAppenders.consoleLog.debug("{} started by {}", this, map);
		if (!jobStarted) {
			startJob();
			this.jobStarted = true;
		}
		return jobStarted;
	}

	protected void startJob() {
		SumkThreadPool.executor().execute(this);
	}

	protected abstract boolean onStart(Map configMap);

	public synchronized void stop() throws Exception {
		this.matcher = BooleanMatcher.FALSE;
		LogAppenders.consoleLog.info("日志{} stoped", this.name);
	}

	public void setInterval(int interval) {
		if (interval > 0) {
			this.interval = interval;
		}
	}

	public long getHandleLogCount() {
		return handleLogCount;
	}

	protected Predicate getMatcher() {
		return matcher;
	}

	protected void setMatcher(Predicate matcher) {
		this.matcher = Objects.requireNonNull(matcher);
	}

	@Override
	public String toString() {
		return this.name + " [queue size:" + queue.size() + ",matcher:" + matcher + ",logCount:" + handleLogCount + "]";
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy