From 2c193e14832fce2056b9a03c709d1f97b518e842 Mon Sep 17 00:00:00 2001 From: Tadayoshi Sato Date: Thu, 31 Mar 2022 14:56:43 +0900 Subject: [PATCH] feat(springboot): ENTESB-18661 implement LogQueryMBean for Logback/Spring Boot Fix #2722 --- hawtio-log-logback/pom.xml | 52 ++++++ .../io/hawt/log/logback/LogbackLogQuery.java | 152 ++++++++++++++++++ .../log/logback/LogbackLogQueryMBean.java | 20 +++ .../hawt/log/logback/LoggingEventMapper.java | 58 +++++++ .../hawt/log/logback/LogbackLogQueryTest.java | 69 ++++++++ .../src/main/java/io/hawt/log/LogEvent.java | 137 ++++++++-------- .../io/hawt/log/support/LogQueryBase.java | 72 +++++++++ .../io/hawt/log/support/LogQuerySupport.java | 10 +- .../java/io/hawt/log/support/LruList.java | 18 ++- .../{log4j => support}/MavenCoordHelper.java | 5 +- .../java/io/hawt/log/support/Objects.java | 24 +-- .../ThrowableFormatter.java | 9 +- platforms/springboot/pom.xml | 12 +- .../SpringHawtioContextListener.java | 8 +- pom.xml | 10 +- 15 files changed, 540 insertions(+), 116 deletions(-) create mode 100644 hawtio-log-logback/pom.xml create mode 100644 hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQuery.java create mode 100644 hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQueryMBean.java create mode 100644 hawtio-log-logback/src/main/java/io/hawt/log/logback/LoggingEventMapper.java create mode 100644 hawtio-log-logback/src/test/java/io/hawt/log/logback/LogbackLogQueryTest.java create mode 100644 hawtio-log/src/main/java/io/hawt/log/support/LogQueryBase.java rename hawtio-log/src/main/java/io/hawt/log/{log4j => support}/MavenCoordHelper.java (97%) rename hawtio-log/src/main/java/io/hawt/log/{log4j => support}/ThrowableFormatter.java (96%) diff --git a/hawtio-log-logback/pom.xml b/hawtio-log-logback/pom.xml new file mode 100644 index 0000000000..b0a73540a1 --- /dev/null +++ b/hawtio-log-logback/pom.xml @@ -0,0 +1,52 @@ + + + + io.hawt + project + 2.15-SNAPSHOT + + + 4.0.0 + hawtio-log-logback + ${project.artifactId} + hawtio :: hawtio-log-logback + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot-version} + pom + import + + + + + + + io.hawt + hawtio-log + ${project.version} + + + + ch.qos.logback + logback-classic + + + + + junit + junit + ${junit-version} + test + + + org.assertj + assertj-core + ${assertj-core-version} + + + + diff --git a/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQuery.java b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQuery.java new file mode 100644 index 0000000000..a085ba9a16 --- /dev/null +++ b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQuery.java @@ -0,0 +1,152 @@ +package io.hawt.log.logback; + +import java.util.ArrayList; +import java.util.List; + +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.AppenderAttachable; +import io.hawt.log.LogEvent; +import io.hawt.log.LogFilter; +import io.hawt.log.LogResults; +import io.hawt.log.support.LogQueryBase; +import io.hawt.log.support.LruList; +import io.hawt.log.support.Predicate; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An implementation of {@link LogbackLogQueryMBean}. + */ +public class LogbackLogQuery extends LogQueryBase implements LogbackLogQueryMBean { + + private static final transient Logger LOG = LoggerFactory.getLogger(LogbackLogQuery.class); + + private static final String APPENDER_NAME = "LogQuery"; + + private int size = 2000; + private LruList events; + + private final Appender appender = new HawtioAppender(); + + private final LoggingEventMapper eventMapper; + + public LogbackLogQuery() { + super(); + eventMapper = new LoggingEventMapper(getHostName()); + } + + @Override + public void start() { + super.start(); + appender.start(); + reconnectAppender(); + } + + @Override + public void reconnectAppender() { + ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); + Logger root = loggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME); + + if (root instanceof AppenderAttachable) { + appender.setContext((Context) loggerFactory); + @SuppressWarnings("unchecked") + AppenderAttachable attachable = (AppenderAttachable) root; + attachable.addAppender(appender); + LOG.info("Connected to Logback appender to trap logs with Hawtio log plugin"); + } else { + LOG.warn("No appender-attachable root logger found so cannot attach Hawtio log appender!"); + } + } + + @Override + public void logMessage(LoggingEvent record) { + getEvents().add(record); + } + + @Override + public LogResults getLogResults(int count) { + return filterLogResults(null, count); + } + + @Override + public LogResults queryLogResults(LogFilter filter) { + Predicate predicate = createPredicate(filter); + int count = filter == null ? -1 : filter.getCount(); + return filterLogResults(predicate, count); + } + + protected LogResults filterLogResults(Predicate predicate, int maxCount) { + int matched = 0; + long from = Long.MAX_VALUE; + long to = Long.MIN_VALUE; + List list = new ArrayList<>(); + Iterable elements = getEvents().getElements(); + for (LoggingEvent element : elements) { + LogEvent logEvent = eventMapper.toLogEvent(element); + long timestamp = element.getTimeStamp(); + if (timestamp > to) { + to = timestamp; + } + if (timestamp < from) { + from = timestamp; + } + if (predicate == null || predicate.matches(logEvent)) { + list.add(logEvent); + matched += 1; + if (maxCount > 0 && matched >= maxCount) { + break; + } + } + } + + LogResults results = new LogResults(); + results.setEvents(list); + if (from < Long.MAX_VALUE) { + results.setFromTimestamp(from); + } + if (to > Long.MIN_VALUE) { + results.setToTimestamp(to); + } + LOG.debug("Requested {} logging items, returning {} event(s) from possible {}", + maxCount, results.getEvents().size(), getEvents().size()); + return results; + } + + // ------------------------------------------------------------------------- + // Properties + // ------------------------------------------------------------------------- + + public LruList getEvents() { + if (events == null) { + events = new LruList<>(LoggingEvent.class, getSize()); + } + return events; + } + + @Override + public int getSize() { + return size; + } + + /** + * Only for testing. + */ + public void setSize(int size) { + this.size = size; + } + + private class HawtioAppender extends AppenderBase { + public HawtioAppender() { + setName(APPENDER_NAME); + } + + @Override + protected void append(LoggingEvent event) { + logMessage(event); + } + } +} diff --git a/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQueryMBean.java b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQueryMBean.java new file mode 100644 index 0000000000..ad2f205e21 --- /dev/null +++ b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LogbackLogQueryMBean.java @@ -0,0 +1,20 @@ +package io.hawt.log.logback; + +import ch.qos.logback.classic.spi.LoggingEvent; +import io.hawt.log.support.LogQuerySupportMBean; + +/** + * The MBean operations for {@link LogbackLogQuery} + */ +public interface LogbackLogQueryMBean extends LogQuerySupportMBean { + /** + * Provides a hook you can call if the underlying log4j + * configuration is reloaded so that you can force the appender + * to get re-registered. + */ + void reconnectAppender(); + + void logMessage(LoggingEvent record); + + int getSize(); +} diff --git a/hawtio-log-logback/src/main/java/io/hawt/log/logback/LoggingEventMapper.java b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LoggingEventMapper.java new file mode 100644 index 0000000000..07c9b637ca --- /dev/null +++ b/hawtio-log-logback/src/main/java/io/hawt/log/logback/LoggingEventMapper.java @@ -0,0 +1,58 @@ +package io.hawt.log.logback; + +import java.util.Date; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.classic.spi.ThrowableProxy; +import io.hawt.log.LogEvent; +import io.hawt.log.support.ThrowableFormatter; + +public class LoggingEventMapper { + + private String hostName; + + public LoggingEventMapper(String hostName) { + this.hostName = hostName; + } + + public LogEvent toLogEvent(LoggingEvent loggingEvent) { + LogEvent answer = new LogEvent(); + answer.setClassName(loggingEvent.getLoggerName()); + + ThrowableProxy throwable = (ThrowableProxy) loggingEvent.getThrowableProxy(); + if (throwable != null) { + ThrowableFormatter formatter = new ThrowableFormatter(); + String[] stack = formatter.doRender(throwable.getThrowable()); + if (stack != null) { + answer.setException(stack); + } + } + + StackTraceElement[] callerData = loggingEvent.getCallerData(); + if (callerData != null && callerData.length > 0) { + StackTraceElement ste = callerData[0]; + answer.setFileName(ste.getFileName()); + answer.setClassName(ste.getClassName()); + answer.setMethodName(ste.getMethodName()); + answer.setLineNumber(String.valueOf(ste.getLineNumber())); + } + + Level level = loggingEvent.getLevel(); + if (level != null) { + answer.setLevel(level.toString()); + } + answer.setLogger(loggingEvent.getLoggerName()); + String message = loggingEvent.getFormattedMessage(); + if (message != null) { + answer.setMessage(message); + } + answer.setProperties(loggingEvent.getMDCPropertyMap()); + answer.setSeq(loggingEvent.getTimeStamp()); + answer.setTimestamp(new Date(loggingEvent.getTimeStamp())); + answer.setThread(loggingEvent.getThreadName()); + answer.setHost(hostName); + + return answer; + } +} diff --git a/hawtio-log-logback/src/test/java/io/hawt/log/logback/LogbackLogQueryTest.java b/hawtio-log-logback/src/test/java/io/hawt/log/logback/LogbackLogQueryTest.java new file mode 100644 index 0000000000..2bee167a42 --- /dev/null +++ b/hawtio-log-logback/src/test/java/io/hawt/log/logback/LogbackLogQueryTest.java @@ -0,0 +1,69 @@ +package io.hawt.log.logback; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import io.hawt.log.LogEvent; +import io.hawt.log.LogFilter; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LogbackLogQueryTest { + private static final transient Logger LOG = LoggerFactory.getLogger(LogbackLogQueryTest.class); + + private LogbackLogQuery logQuery; + + @Before + public void setUp() { + logQuery = new LogbackLogQuery(); + logQuery.start(); + } + + @After + public void tearDown() { + logQuery.stop(); + } + + @Test + public void testGetLogResults() throws Exception { + // Given + String message = "testGetLogResults - Hello Hawtio"; + IntStream.range(0, 10).forEach(i -> LOG.info(message + " #{}", i)); + + // When + List events = logQuery.getLogResults(10).getEvents(); + + // Then + assertThat(events.size()).isEqualTo(10); + List messages = events.stream() + .map(LogEvent::getMessage) + .collect(Collectors.toList()); + assertThat(messages).contains(message + " #5"); + } + + @Test + public void testQueryLogResults() throws Exception { + // Given + String message = "testQueryLogResults - Hello Hawtio"; + IntStream.range(0, 10).forEach(i -> LOG.info(message + " #{}", i)); + + // When + LogFilter filter = new LogFilter(); + filter.setMatchesText(message); + filter.setCount(10); + List events = logQuery.queryLogResults(filter).getEvents(); + + // Then + assertThat(events.size()).isEqualTo(10); + events.stream() + .map(LogEvent::getMessage) + .forEach(m -> assertThat(m).contains(message)); + } + +} diff --git a/hawtio-log/src/main/java/io/hawt/log/LogEvent.java b/hawtio-log/src/main/java/io/hawt/log/LogEvent.java index 4dcbd493ce..7a6ddb4cb1 100644 --- a/hawtio-log/src/main/java/io/hawt/log/LogEvent.java +++ b/hawtio-log/src/main/java/io/hawt/log/LogEvent.java @@ -7,20 +7,20 @@ import java.util.Date; import java.util.Map; -@JsonIgnoreProperties(ignoreUnknown=true) +@JsonIgnoreProperties(ignoreUnknown = true) public class LogEvent implements Comparable, Serializable { private static final long serialVersionUID = 1L; private static String defaultContainerName; - private String host; - private Long seq; - private Date timestamp; - private String level; - private String logger; - private String thread; - private String message; - private String[] exception; - private Map properties; + private String host; + private Long seq; + private Date timestamp; + private String level; + private String logger; + private String thread; + private String message; + private String[] exception; + private Map properties; private String className; private String fileName; private String methodName; @@ -32,11 +32,11 @@ public class LogEvent implements Comparable, Serializable { } public static LogEvent toLogEvent(Object element) { - if (element instanceof LogEvent) { - return (LogEvent) element; - } - return null; - } + if (element instanceof LogEvent) { + return (LogEvent) element; + } + return null; + } public LogEvent() { this.containerName = getDefaultContainerName(); @@ -50,7 +50,8 @@ public boolean equals(Object o) { LogEvent logEvent = (LogEvent) o; if (host != null ? !host.equals(logEvent.host) : logEvent.host != null) return false; - if (containerName != null ? !containerName.equals(logEvent.containerName) : logEvent.containerName != null) return false; + if (containerName != null ? !containerName.equals(logEvent.containerName) : logEvent.containerName != null) + return false; if (logger != null ? !logger.equals(logEvent.logger) : logEvent.logger != null) return false; if (message != null ? !message.equals(logEvent.message) : logEvent.message != null) return false; if (seq != null ? !seq.equals(logEvent.seq) : logEvent.seq != null) return false; @@ -105,12 +106,12 @@ public String toString() { } public String getHost() { - return host; - } + return host; + } - public void setHost(String host) { - this.host = host; - } + public void setHost(String host) { + this.host = host; + } public String getContainerName() { return containerName; @@ -121,68 +122,68 @@ public void setContainerName(String containerName) { } public Long getSeq() { - return seq; - } + return seq; + } - public void setSeq(Long seq) { - this.seq = seq; - } + public void setSeq(Long seq) { + this.seq = seq; + } - public Date getTimestamp() { - return timestamp; - } + public Date getTimestamp() { + return timestamp; + } - public void setTimestamp(Date timestamp) { - this.timestamp = timestamp; - } + public void setTimestamp(Date timestamp) { + this.timestamp = timestamp; + } - public String getLevel() { - return level; - } + public String getLevel() { + return level; + } - public void setLevel(String level) { - this.level = level; - } + public void setLevel(String level) { + this.level = level; + } - public String getLogger() { - return logger; - } + public String getLogger() { + return logger; + } - public void setLogger(String logger) { - this.logger = logger; - } + public void setLogger(String logger) { + this.logger = logger; + } - public String getThread() { - return thread; - } + public String getThread() { + return thread; + } - public void setThread(String thread) { - this.thread = thread; - } + public void setThread(String thread) { + this.thread = thread; + } - public String getMessage() { - return message; - } + public String getMessage() { + return message; + } - public void setMessage(String message) { - this.message = message; - } + public void setMessage(String message) { + this.message = message; + } - public Map getProperties() { - return properties; - } + public Map getProperties() { + return properties; + } - public void setProperties(Map properties) { - this.properties = properties; - } + public void setProperties(Map properties) { + this.properties = properties; + } - public String[] getException() { - return exception; - } + public String[] getException() { + return exception; + } - public void setException(String[] exception) { - this.exception = exception; - } + public void setException(String[] exception) { + this.exception = exception; + } public String getClassName() { return className; diff --git a/hawtio-log/src/main/java/io/hawt/log/support/LogQueryBase.java b/hawtio-log/src/main/java/io/hawt/log/support/LogQueryBase.java new file mode 100644 index 0000000000..f876a02777 --- /dev/null +++ b/hawtio-log/src/main/java/io/hawt/log/support/LogQueryBase.java @@ -0,0 +1,72 @@ +package io.hawt.log.support; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import io.hawt.log.LogEvent; +import io.hawt.log.LogFilter; + +import static io.hawt.log.support.Objects.contains; + +public abstract class LogQueryBase extends LogQuerySupport { + + protected Predicate createPredicate(LogFilter filter) { + if (filter == null) { + return null; + } + List> predicates = new ArrayList<>(); + + Set levels = filter.getLevelsSet(); + if (levels.size() > 0) { + predicates.add(e -> e.getLevel() != null && levels.contains(e.getLevel())); + } + Long before = filter.getBeforeTimestamp(); + if (before != null) { + Date date = new Date(before); + predicates.add(e -> e.getTimestamp() != null && e.getTimestamp().before(date)); + } + Long after = filter.getAfterTimestamp(); + if (after != null) { + Date date = new Date(after); + predicates.add(e -> e.getTimestamp() != null && e.getTimestamp().after(date)); + } + + String matchesText = filter.getMatchesText(); + if (matchesText != null && matchesText.length() > 0) { + predicates.add(e -> matches(e, matchesText)); + } + + if (predicates.isEmpty()) { + return null; + } else if (predicates.size() == 1) { + return predicates.get(0); + } else { + return new Predicate() { + @Override + public String toString() { + return "AndPredicate" + predicates; + } + + @Override + public boolean matches(LogEvent event) { + return predicates.stream().allMatch(p -> p.matches(event)); + } + }; + } + } + + private boolean matches(LogEvent event, String text) { + if (contains(text, event.getClassName(), event.getMessage(), event.getLogger(), event.getThread())) { + return true; + } + String[] throwableStrRep = event.getException(); + if (throwableStrRep != null && contains(text, throwableStrRep)) { + return true; + } + Map properties = event.getProperties(); + return properties != null && contains(text, properties.toString()); + } +} diff --git a/hawtio-log/src/main/java/io/hawt/log/support/LogQuerySupport.java b/hawtio-log/src/main/java/io/hawt/log/support/LogQuerySupport.java index a6bb84bd5a..51a576857e 100644 --- a/hawtio-log/src/main/java/io/hawt/log/support/LogQuerySupport.java +++ b/hawtio-log/src/main/java/io/hawt/log/support/LogQuerySupport.java @@ -13,6 +13,7 @@ import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; + import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectInstance; @@ -54,9 +55,8 @@ protected static String loadString(URL url) throws IOException { StringWriter writer = new StringWriter(); final char[] buffer = new char[4096]; int n; - while ( -1 != ( n = reader.read( buffer ) ) ) - { - writer.write( buffer, 0, n ); + while (-1 != (n = reader.read(buffer))) { + writer.write(buffer, 0, n); } writer.flush(); return writer.toString(); @@ -223,7 +223,7 @@ protected String getArtifactFile(String mavenCoords, String filePath, String cla String coords = mavenCoords.replace(':', '/'); String[] array = coords.split("\\s+"); - if (array == null || array.length < 2) { + if (array.length < 2) { return loadCoords(coords, filePath, classifier); } else { // lets enumerate all values if space separated @@ -294,8 +294,6 @@ protected void addJarEntryToIndex(JarEntry entry, StringBuilder buffer) { } } - - /** * Returns true if the file path is "/" or empty */ diff --git a/hawtio-log/src/main/java/io/hawt/log/support/LruList.java b/hawtio-log/src/main/java/io/hawt/log/support/LruList.java index aec84a853c..3bb761d7cb 100644 --- a/hawtio-log/src/main/java/io/hawt/log/support/LruList.java +++ b/hawtio-log/src/main/java/io/hawt/log/support/LruList.java @@ -1,7 +1,9 @@ package io.hawt.log.support; import java.lang.reflect.Array; +import java.util.ArrayList; import java.util.Arrays; +import java.util.stream.StreamSupport; /** * A simple LRU list that stores a fixed size @@ -17,10 +19,10 @@ public class LruList { public LruList(Class klass, int size) { this.klass = klass; - this.size = size; if (size <= 0) { throw new IllegalArgumentException("The size must be greater than 0"); } + this.size = size; elements = createArray(size); maxElements = elements.length; } @@ -45,7 +47,7 @@ public synchronized void clear() { public synchronized void add(T element) { if (null == element) { - throw new NullPointerException("Attempted to add null object to buffer"); + throw new NullPointerException("Attempted to add null object to buffer"); } if (size() == maxElements) { Object e = elements[start]; @@ -70,18 +72,18 @@ public synchronized Iterable getElements() { return getElements(size()); } - public synchronized Iterable getElements(int nb) { + public synchronized Iterable getElements(int number) { int s = size(); - nb = Math.min(Math.max(0, nb), s); - T[] e = createArray(nb); - for (int i = 0; i < nb; i++) { - e[i] = elements[(i + s - nb + start) % maxElements]; + int n = Math.min(Math.max(0, number), s); + T[] e = createArray(n); + for (int i = 0; i < n; i++) { + e[i] = elements[(i + s - n + start) % maxElements]; } return Arrays.asList(e); } + @SuppressWarnings("unchecked") private T[] createArray(int size) { return (T[]) Array.newInstance(klass, size); } - } diff --git a/hawtio-log/src/main/java/io/hawt/log/log4j/MavenCoordHelper.java b/hawtio-log/src/main/java/io/hawt/log/support/MavenCoordHelper.java similarity index 97% rename from hawtio-log/src/main/java/io/hawt/log/log4j/MavenCoordHelper.java rename to hawtio-log/src/main/java/io/hawt/log/support/MavenCoordHelper.java index 56b96664cc..9666b94cf3 100644 --- a/hawtio-log/src/main/java/io/hawt/log/log4j/MavenCoordHelper.java +++ b/hawtio-log/src/main/java/io/hawt/log/support/MavenCoordHelper.java @@ -1,7 +1,5 @@ -package io.hawt.log.log4j; +package io.hawt.log.support; -import io.hawt.log.support.MavenCoordinates; -import io.hawt.log.support.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,7 +92,6 @@ public static String getMavenCoordinates(Class cls) throws IOException { return buffer.toString(); } - /** * Find class given class name. * diff --git a/hawtio-log/src/main/java/io/hawt/log/support/Objects.java b/hawtio-log/src/main/java/io/hawt/log/support/Objects.java index 066cc850ee..4a6bbb368a 100644 --- a/hawtio-log/src/main/java/io/hawt/log/support/Objects.java +++ b/hawtio-log/src/main/java/io/hawt/log/support/Objects.java @@ -1,21 +1,13 @@ package io.hawt.log.support; +import java.util.Arrays; + public final class Objects { public static boolean isBlank(String text) { return text == null || text.trim().length() == 0; } - /** - * A helper method for comparing objects for equality while handling nulls - */ - public static boolean equal(Object a, Object b) { - if (a == b) { - return true; - } - return a != null && b != null && a.equals(b); - } - /** * A helper method for performing an ordered comparison on the objects * handling nulls and objects which do not handle sorting gracefully @@ -35,8 +27,7 @@ public static int compare(Object a, Object b) { return 1; } if (a instanceof Comparable) { - Comparable comparable = (Comparable)a; - return comparable.compareTo(b); + return ((Comparable) a).compareTo(b); } int answer = a.getClass().getName().compareTo(b.getClass().getName()); if (answer == 0) { @@ -46,11 +37,8 @@ public static int compare(Object a, Object b) { } public static boolean contains(String matchesText, String... values) { - for (String v : values) { - if (v != null && v.contains(matchesText)) { - return true; - } - } - return false; + return Arrays.stream(values) + .filter(java.util.Objects::nonNull) + .anyMatch(v -> v.contains(matchesText)); } } diff --git a/hawtio-log/src/main/java/io/hawt/log/log4j/ThrowableFormatter.java b/hawtio-log/src/main/java/io/hawt/log/support/ThrowableFormatter.java similarity index 96% rename from hawtio-log/src/main/java/io/hawt/log/log4j/ThrowableFormatter.java rename to hawtio-log/src/main/java/io/hawt/log/support/ThrowableFormatter.java index 8a8576c4d5..ee28f52eb8 100644 --- a/hawtio-log/src/main/java/io/hawt/log/log4j/ThrowableFormatter.java +++ b/hawtio-log/src/main/java/io/hawt/log/support/ThrowableFormatter.java @@ -1,4 +1,4 @@ -package io.hawt.log.log4j; +package io.hawt.log.support; import java.io.File; import java.lang.reflect.Method; @@ -7,8 +7,6 @@ import java.util.HashMap; import java.util.Map; -import io.hawt.log.support.Objects; - /** * Code modified from log4j to format exceptions */ @@ -22,7 +20,6 @@ public class ThrowableFormatter { */ private Method getClassNameMethod; - /** * Construct new instance. */ @@ -43,7 +40,7 @@ public String[] doRender(final Throwable throwable) { if (getStackTraceMethod != null) { try { Object[] noArgs = null; - Object[] elements = (Object[])getStackTraceMethod.invoke(throwable, noArgs); + Object[] elements = (Object[]) getStackTraceMethod.invoke(throwable, noArgs); String[] lines = new String[elements.length + 1]; lines[0] = throwable.toString(); Map classMap = new HashMap(); @@ -68,7 +65,7 @@ private String formatElement(final Object element, final Map classMap) { StringBuffer buf = new StringBuffer("\tat "); buf.append(element); try { - String className = getClassNameMethod.invoke(element, (Object[])null).toString(); + String className = getClassNameMethod.invoke(element, (Object[]) null).toString(); Object classDetails = classMap.get(className); if (classDetails != null) { buf.append(classDetails); diff --git a/platforms/springboot/pom.xml b/platforms/springboot/pom.xml index f86bb02847..0ab198097a 100644 --- a/platforms/springboot/pom.xml +++ b/platforms/springboot/pom.xml @@ -38,6 +38,16 @@ hawtio-system ${project.version} + + io.hawt + hawtio-log + ${project.version} + + + io.hawt + hawtio-log-logback + ${project.version} + org.springframework.boot spring-boot-actuator @@ -90,7 +100,7 @@ org.mockito mockito-core - 2.20.0 + ${mockito-core-version} test diff --git a/platforms/springboot/src/main/java/io/hawt/springboot/SpringHawtioContextListener.java b/platforms/springboot/src/main/java/io/hawt/springboot/SpringHawtioContextListener.java index dd1e3fdbfc..61559c522b 100755 --- a/platforms/springboot/src/main/java/io/hawt/springboot/SpringHawtioContextListener.java +++ b/platforms/springboot/src/main/java/io/hawt/springboot/SpringHawtioContextListener.java @@ -5,23 +5,27 @@ import javax.servlet.ServletContextEvent; import io.hawt.HawtioContextListener; +import io.hawt.log.logback.LogbackLogQuery; import io.hawt.system.ConfigManager; import io.hawt.system.HawtioProperty; public class SpringHawtioContextListener extends HawtioContextListener { public final String servletPath; + private final LogbackLogQuery logQuery; public SpringHawtioContextListener(final ConfigManager configManager, - final String servletPath) { + final String servletPath) { super(configManager); this.servletPath = Objects.requireNonNull(servletPath); + this.logQuery = new LogbackLogQuery(); } @Override public void contextInitialized(final ServletContextEvent servletContextEvent) { super.contextInitialized(servletContextEvent); + logQuery.start(); servletContextEvent.getServletContext() - .setAttribute(HawtioProperty.SERVLET_PATH, this.servletPath); + .setAttribute(HawtioProperty.SERVLET_PATH, this.servletPath); } } diff --git a/pom.xml b/pom.xml index d879efd526..a2e2a77da0 100644 --- a/pom.xml +++ b/pom.xml @@ -57,9 +57,10 @@ 1.1.0 1.12 - 5.3.14 + 5.3.17 2.6.2 + 3.22.0 1.15 2.11.0 1.2 @@ -74,7 +75,7 @@ 9.4.43.v20210629 ${jetty-version} 1.7.0 - 4.12 + 4.13.2 4.3.3 [4.0,5) 11.0.2 @@ -86,6 +87,7 @@ 2.6 3.0.0-M1 3.2.3 + 4.3.1 20171018 5.0.0 3.1.0 @@ -118,6 +120,7 @@ hawtio-ide hawtio-local-jvm-mbean hawtio-log + hawtio-log-logback hawtio-log-osgi hawtio-plugin-mbean hawtio-system @@ -249,7 +252,7 @@ org.apache.maven.plugins maven-failsafe-plugin ${maven-failsafe-plugin-version} - + @@ -283,6 +286,7 @@ org.apache.maven.plugins maven-gpg-plugin + ${gpg.passphrase}