org.yx.log.impl.LogQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sumk-log Show documentation
Show all versions of sumk-log Show documentation
a slf4j framework for sumk
/**
* 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 + "]";
}
}