com.alibaba.schedulerx.worker.log.appender.SchedulerxLogbackAppender Maven / Gradle / Ivy
package com.alibaba.schedulerx.worker.log.appender;
import java.time.ZoneId;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import com.alibaba.schedulerx.common.constants.CommonConstants;
import com.alibaba.schedulerx.protocol.Worker.WorkerReportLogRequest;
import com.alibaba.schedulerx.worker.SchedulerxWorker;
import com.alibaba.schedulerx.worker.container.ContainerFactory;
import com.alibaba.schedulerx.worker.discovery.ServerDiscovery;
import com.alibaba.schedulerx.worker.discovery.ServerDiscoveryFactory;
import com.alibaba.schedulerx.worker.domain.JobContext;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.StackTraceElementProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import ch.qos.logback.core.encoder.Encoder;
/**
* @author xiaomeng.hxm
*
*/
public class SchedulerxLogbackAppender extends UnsynchronizedAppenderBase {
private String userAgent = "logback";
protected Encoder encoder;
protected String topic = ""; //
protected String source = ""; //
protected String timeZone = "UTC";
protected String timeFormat = "yyyy-MM-dd'T'HH:mmZ";
protected DateTimeFormatter formatter;
protected java.time.format.DateTimeFormatter formatter1;
@Override
public void start() {
try {
doStart();
} catch (Exception e) {
addError("Failed to start SchedulerxLogbackAppender.", e);
}
}
private void doStart() {
try {
formatter = DateTimeFormat.forPattern(timeFormat).withZone(DateTimeZone.forID(timeZone));
} catch (Exception e){
formatter1 = java.time.format.DateTimeFormatter.ofPattern(timeFormat).withZone(ZoneId.of(timeZone));
}
super.start();
}
@Override
public void stop() {
try {
doStop();
} catch (Exception e) {
addError("Failed to stop SchedulerxLogbackAppender.", e);
}
}
private void doStop() throws InterruptedException {
if (!isStarted()) {
return;
}
super.stop();
}
@Override
public void append(E eventObject) {
try {
appendEvent(eventObject);
} catch (Exception e) {
addError("Failed to append event.", e);
}
}
private void appendEvent(E eventObject) {
//init Event Object
if (!(eventObject instanceof LoggingEvent)) {
return;
}
LoggingEvent event = (LoggingEvent) eventObject;
JobContext jobContext = ContainerFactory.getContainerPool().getContext();
//如果不在ThreadContainer的线程中,当前版本不收集
if (jobContext == null) {
addWarn("jobContext is null, threadName=" + event.getThreadName()
+ ", stackTrace=" + event.getCallerData() + ", message=" + event.getFormattedMessage());
return;
}
if (StringUtils.isEmpty(jobContext.getGroupId()) || !LogConfig.INSTANCE.isEnable()) {
return;
}
try {
WorkerReportLogRequest.Builder builder = WorkerReportLogRequest.newBuilder();
builder.setAppGroupId(jobContext.getAppGroupId());
builder.setExecutionId(jobContext.getUniqueId());
builder.setTime(DateTime.now().toString(CommonConstants.DATE_TIME_PATTERN));
builder.setLevel(event.getLevel().toString());
String message = event.getFormattedMessage();
builder.setMessage(message);
builder.setThread(event.getThreadName());
builder.setGroup("schedulerx-user");
builder.setSource(SchedulerxWorker.WORKER_ADDR);
if (this.encoder != null) {
builder.setLog(new String(this.encoder.encode(eventObject)));
} else {
builder.setLog(message);
}
IThrowableProxy iThrowableProxy = event.getThrowableProxy();
if (iThrowableProxy != null) {
String throwable = getExceptionInfo(iThrowableProxy);
throwable += fullDump(event.getThrowableProxy().getStackTraceElementProxyArray());
builder.setThrowable(throwable);
}
ServerDiscovery serverDiscovery = ServerDiscoveryFactory.getDiscovery(jobContext.getGroupId());
if (serverDiscovery != null && serverDiscovery.getLogRouter() != null) {
serverDiscovery.getLogRouter().tell(builder.build(), null);
} else {
addWarn("serverDiscovery or LogRouter is null, groupId=" + jobContext.getGroupId());
}
} catch (Exception e) {
addWarn("report log failed, appGroupId=" + jobContext.getAppGroupId() + ", key=" + jobContext.getUniqueId(), e);
}
}
/**
* createTopic
* @param jobContext
* @return
*/
private String createTopic(JobContext jobContext) {
return "group-" + jobContext.getAppGroupId();
}
public String getTimeFormat() {
return timeFormat;
}
public void setTimeFormat(String timeFormat) {
this.timeFormat = timeFormat;
}
private String getExceptionInfo(IThrowableProxy iThrowableProxy) {
String s = iThrowableProxy.getClassName();
String message = iThrowableProxy.getMessage();
return (message != null) ? (s + ": " + message) : s;
}
private String fullDump(StackTraceElementProxy[] stackTraceElementProxyArray) {
StringBuilder builder = new StringBuilder();
for (StackTraceElementProxy step : stackTraceElementProxyArray) {
builder.append(CoreConstants.LINE_SEPARATOR);
String string = step.toString();
builder.append(CoreConstants.TAB).append(string);
ThrowableProxyUtil.subjoinPackagingData(builder, step);
}
return builder.toString();
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getTimeZone() {
return timeZone;
}
public void setTimeZone(String timeZone) {
this.timeZone = timeZone;
}
public String getUserAgent() {
return userAgent;
}
public void setUserAgent(String userAgent) {
this.userAgent = userAgent;
}
public Encoder getEncoder() {
return encoder;
}
public void setEncoder(Encoder encoder) {
this.encoder = encoder;
}
}