io.datakernel.jmx.ExceptionStats Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datakernel-eventloop Show documentation
Show all versions of datakernel-eventloop Show documentation
Efficient non-blocking network and file I/O, for building Node.js-like client/server applications with
high performance requirements. It is similar to Event Loop in Node.js.
Although Eventloop runs in a single thread, multiple event loops can be
launched at the same time allowing for efficient CPU usage.
/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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 io.datakernel.jmx;
import io.datakernel.annotation.Nullable;
import java.time.Instant;
import java.util.List;
import static io.datakernel.jmx.MBeanFormat.*;
import static java.lang.System.currentTimeMillis;
public final class ExceptionStats implements JmxStats, JmxStatsWithReset {
private static final long DETAILS_REFRESH_TIMEOUT = 1000L;
@Nullable
private Class extends Throwable> exceptionClass;
private int count;
private long lastExceptionTimestamp;
@Nullable
private Throwable throwable;
@Nullable
private Object context;
private ExceptionStats() {
}
public static ExceptionStats create() {
return new ExceptionStats();
}
public void recordException(Throwable throwable, @Nullable Object context) {
this.count++;
long now = currentTimeMillis();
if (now >= lastExceptionTimestamp + DETAILS_REFRESH_TIMEOUT) {
this.exceptionClass = throwable != null ? throwable.getClass() : null;
this.throwable = throwable;
this.context = context;
this.lastExceptionTimestamp = now;
}
}
public void recordException(Throwable throwable) {
recordException(throwable, null);
}
@Override
public void resetStats() {
this.count = 0;
this.lastExceptionTimestamp = 0;
this.exceptionClass = null;
this.throwable = null;
this.context = null;
}
@Override
public void add(ExceptionStats another) {
this.count += another.count;
if (another.lastExceptionTimestamp >= this.lastExceptionTimestamp) {
this.lastExceptionTimestamp = another.lastExceptionTimestamp;
this.exceptionClass = another.exceptionClass;
this.throwable = another.throwable;
this.context = another.context;
}
}
@JmxAttribute(optional = true)
public int getTotal() {
return count;
}
@JmxAttribute(optional = true)
@Nullable
public String getLastType() {
return exceptionClass != null ? exceptionClass.toString() : null;
}
@JmxAttribute(optional = true)
@Nullable
public Instant getLastTime() {
return lastExceptionTimestamp != 0L ? Instant.ofEpochMilli(lastExceptionTimestamp) : null;
}
@JmxAttribute(optional = true)
@Nullable
public Throwable getLastException() {
return throwable;
}
@JmxAttribute(optional = true)
@Nullable
public String getLastMessage() {
return throwable != null ? throwable.getMessage() : null;
}
@JmxAttribute
public String getMultilineError() {
if (count == 0) return "";
StringBuilder summary = new StringBuilder("Count: " + count + " " + formatTimestamp(lastExceptionTimestamp));
if (throwable != null) {
summary.append("\nStack Trace: ");
summary.append(formatExceptionMultiline(throwable).trim());
}
if (context != null) {
summary.append("\nContext: ");
summary.append(context.toString());
}
return summary.toString();
}
@JmxAttribute
@Nullable
public List getError() {
return formatMultilineStringAsList(getMultilineError());
}
@Override
public String toString() {
String last = "";
if (exceptionClass != null) {
last = "; " + exceptionClass.getSimpleName();
last += " @" + formatTimestamp(lastExceptionTimestamp);
}
return Integer.toString(count) + last;
}
@Nullable
public Object getContext(){
return context;
}
}