From bb52e1c02487717b1882357fbfb6673586282abb Mon Sep 17 00:00:00 2001 From: thc202 Date: Fri, 10 Oct 2025 12:39:24 +0100 Subject: [PATCH] callhome: keep stats of fatal/warn/error logged Add counters for fatal/warn/error and their loggers. Signed-off-by: thc202 --- addOns/callhome/CHANGELOG.md | 3 +- addOns/callhome/callhome.gradle.kts | 2 + .../addon/callhome/ExtensionCallHome.java | 67 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/addOns/callhome/CHANGELOG.md b/addOns/callhome/CHANGELOG.md index a8f5ca2d672..dd2d95a379d 100644 --- a/addOns/callhome/CHANGELOG.md +++ b/addOns/callhome/CHANGELOG.md @@ -4,7 +4,8 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased - +### Added +- Add statistics for the number of fatal/warn/error logged. ## [0.15.0] - 2025-09-02 ### Added diff --git a/addOns/callhome/callhome.gradle.kts b/addOns/callhome/callhome.gradle.kts index 8f2b434dce0..f4de549b0da 100644 --- a/addOns/callhome/callhome.gradle.kts +++ b/addOns/callhome/callhome.gradle.kts @@ -13,6 +13,8 @@ zapAddOn { } dependencies { + compileOnly(libs.log4j.core) + testImplementation(project(":testutils")) } diff --git a/addOns/callhome/src/main/java/org/zaproxy/addon/callhome/ExtensionCallHome.java b/addOns/callhome/src/main/java/org/zaproxy/addon/callhome/ExtensionCallHome.java index 6bb0a362f5c..a755d7b9bd8 100644 --- a/addOns/callhome/src/main/java/org/zaproxy/addon/callhome/ExtensionCallHome.java +++ b/addOns/callhome/src/main/java/org/zaproxy/addon/callhome/ExtensionCallHome.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.StringReader; import java.lang.management.ManagementFactory; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.LocalDateTime; import java.util.HashMap; @@ -36,8 +37,16 @@ import net.sf.json.JSONObject; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.httpclient.URI; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.Filter.Result; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.Property; +import org.apache.logging.log4j.core.filter.LevelRangeFilter; +import org.apache.logging.log4j.core.layout.PatternLayout; import org.parosproxy.paros.Constant; import org.parosproxy.paros.control.Control; import org.parosproxy.paros.control.Control.Mode; @@ -59,6 +68,7 @@ import org.zaproxy.zap.extension.stats.ExtensionStats; import org.zaproxy.zap.extension.stats.InMemoryStats; import org.zaproxy.zap.network.HttpRequestConfig; +import org.zaproxy.zap.utils.Stats; import org.zaproxy.zap.utils.ZapXmlConfiguration; public class ExtensionCallHome extends ExtensionAdaptor @@ -101,6 +111,8 @@ public String toString() { } } + private final StatsLogHandler statsLogHandler; + private HttpSender httpSender = null; private CallHomeParam param; @@ -121,6 +133,8 @@ public ExtensionCallHome() { setI18nPrefix(PREFIX); // Just before the Network extension. setOrder(Integer.MAX_VALUE - 1); + + statsLogHandler = new StatsLogHandler(); } @Override @@ -142,6 +156,8 @@ public void postInit() { @Override public void unload() { this.setAutoUpdateSupplier(null); + + statsLogHandler.remove(); } private OptionsCallHomePanel getOptionsPanel() { @@ -301,6 +317,7 @@ public boolean test(Entry t) { || key.startsWith("stats.graphql.") || key.startsWith("stats.hud.") || key.startsWith("stats.llm.") + || key.startsWith("stats.log.") || key.startsWith("stats.network.") || key.startsWith("stats.oast.") || key.startsWith("stats.openapi.") @@ -512,4 +529,54 @@ private static void updateOutput(String message) { View.getSingleton().getOutputPanel().append(sb.toString()); } } + + private static class StatsLogHandler { + + StatsLogHandler() { + LoggerContext.getContext() + .getConfiguration() + .getRootLogger() + .addAppender(new StatsAppender(), null, null); + } + + void remove() { + LoggerContext.getContext() + .getConfiguration() + .getRootLogger() + .removeAppender(StatsAppender.NAME); + } + + static class StatsAppender extends AbstractAppender { + + private static final String NAME = "ZAP-StatsAppender"; + private static final Property[] NO_PROPERTIES = {}; + + StatsAppender() { + super( + NAME, + LevelRangeFilter.createFilter( + Level.FATAL, Level.WARN, Result.NEUTRAL, Result.NEUTRAL), + PatternLayout.newBuilder() + .withDisableAnsi(true) + .withCharset(StandardCharsets.UTF_8) + .withPattern("%m%n") + .build(), + true, + NO_PROPERTIES); + start(); + } + + @Override + public void append(LogEvent event) { + Level level = event.getLevel(); + if (level.isLessSpecificThan(Level.INFO)) { + return; + } + + String base = "stats.log." + event.getLevel().name().toLowerCase(Locale.ROOT); + Stats.incCounter(base); + Stats.incCounter(base + "." + event.getLoggerName()); + } + } + } }