From 89dd7d218c569d9d936373862bff9ff6a4928cf1 Mon Sep 17 00:00:00 2001 From: Arunan Sugunakumar Date: Thu, 13 Jun 2024 11:33:23 +0530 Subject: [PATCH] Add custom executor and watcher for runtime diagnostic tool --- components/mediation-diagnostics/pom.xml | 66 +++++++ .../action/executor/MetricsSnapshot.java | 167 ++++++++++++++++++ .../trafficanalyzer/SimpleMovingAverage.java | 115 ++++++++++++ .../trafficanalyzer/TrafficAnalyzer.java | 111 ++++++++++++ .../TrafficAnalyzerRunnable.java | 129 ++++++++++++++ pom.xml | 7 + 6 files changed, 595 insertions(+) create mode 100644 components/mediation-diagnostics/pom.xml create mode 100644 components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/action/executor/MetricsSnapshot.java create mode 100644 components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/SimpleMovingAverage.java create mode 100644 components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzer.java create mode 100644 components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzerRunnable.java diff --git a/components/mediation-diagnostics/pom.xml b/components/mediation-diagnostics/pom.xml new file mode 100644 index 0000000000..83e0208520 --- /dev/null +++ b/components/mediation-diagnostics/pom.xml @@ -0,0 +1,66 @@ + + + + + org.wso2.carbon.mediation + carbon-mediation + 4.7.207-SNAPSHOT + ../../pom.xml + + + org.wso2.carbon.mediation.diagnostics + WSO2 Carbon Mediation - Mediation Diagnostics + + 4.0.0 + jar + + + This module is common library module used by both WSO2 MI and WSO2 APIM. + This contains custom Log Watcher and Action Executor implementation related to WSO2 Diagnostic tool. + + + + + org.wso2.runtime.diagnostics + runtime-diagnostics-tool + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + de.jflex + maven-jflex-plugin + 1.4.3 + + + + generate + + + false + + + + + + + diff --git a/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/action/executor/MetricsSnapshot.java b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/action/executor/MetricsSnapshot.java new file mode 100644 index 0000000000..4102585c6b --- /dev/null +++ b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/action/executor/MetricsSnapshot.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). + * + * WSO2 LLC. licenses this file to you 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.wso2.carbon.diagnostics.action.executor; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.wso2.diagnostics.actionexecutor.ActionExecutor; +import org.wso2.diagnostics.actionexecutor.ServerProcess; +import org.wso2.diagnostics.utils.JMXDataRetriever; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import static org.wso2.diagnostics.utils.JMXDataRetriever.getAttributeValue; + +public class MetricsSnapshot implements ActionExecutor { + private static final Logger log = LogManager.getLogger(MetricsSnapshot.class); + + private final String pid; + + public MetricsSnapshot() { + this.pid = ServerProcess.getProcessId(); + } + + /** + * Method used to take server information. + * + * @param folderPath folder path of the dump folder + */ + @Override + public void execute(String folderPath) { + + if (new File(folderPath).exists()) { + + String filepath = folderPath + "/metrics-snapshot.txt"; + try { + FileWriter writer = new FileWriter(filepath); + writer.write(getServerMetrics()); + writer.close(); + log.info("MetricsSnapshot executed successfully."); + } catch (IOException e) { + log.error("Unable to do write server information to file."); + } + } + } + + /** + * Method used to get server information. + * + * @return server information + */ + public String getServerMetrics() { + String metrics = ""; + metrics += "Server Metrics\n"; + metrics += "==============\n"; + metrics += "Memory Usage: " + JMXDataRetriever.getMemoryUsage(pid) + "%\n"; + metrics += "CPU Usage: " + JMXDataRetriever.getCpuUsage(pid) + "%\n"; + metrics += "\n"; + + metrics += "Http Listener Metrics\n"; + metrics += "==============\n"; + metrics += "Active Connections: " + getAttributeValue("http-listener", pid, "ActiveConnections") + "\n"; + metrics += "LastSecondConnections: " + getAttributeValue("http-listener", pid, "LastSecondConnections") + "\n"; + metrics += "Last5SecondConnections: " + getAttributeValue("http-listener", pid, "Last5SecondConnections") + "\n"; + metrics += "Last15SecondConnections: " + getAttributeValue("http-listener", pid, "Last15SecondConnections") + "\n"; + metrics += "LastMinuteConnections: " + getAttributeValue("http-listener", pid, "LastMinuteConnections") + "\n"; + metrics += "LastSecondRequests: " + getAttributeValue("http-listener", pid, "LastSecondRequests") + "\n"; + metrics += "Last15SecondRequests: " + getAttributeValue("http-listener", pid, "Last15SecondRequests") + "\n"; + metrics += "LastMinuteRequests: " + getAttributeValue("http-listener", pid, "LastMinuteRequests") + "\n"; + + metrics += "\n"; + metrics += "Https Listener Metrics\n"; + metrics += "==============\n"; + metrics += "Active Connections: " + getAttributeValue("https-listener", pid, "ActiveConnections") + "\n"; + metrics += "LastSecondConnections: " + getAttributeValue("https-listener", pid, "LastSecondConnections") + "\n"; + metrics += "Last5SecondConnections: " + getAttributeValue("https-listener", pid, "Last5SecondConnections") + "\n"; + metrics += "Last15SecondConnections: " + getAttributeValue("https-listener", pid, "Last15SecondConnections") + "\n"; + metrics += "LastMinuteConnections: " + getAttributeValue("https-listener", pid, "LastMinuteConnections") + "\n"; + metrics += "LastSecondRequests: " + getAttributeValue("https-listener", pid, "LastSecondRequests") + "\n"; + metrics += "Last15SecondRequests: " + getAttributeValue("https-listener", pid, "Last15SecondRequests") + "\n"; + metrics += "LastMinuteRequests: " + getAttributeValue("https-listener", pid, "LastMinuteRequests") + "\n"; + + metrics += "\n"; + metrics += "Http Sender Metrics\n"; + metrics += "==============\n"; + metrics += "Active Connections: " + getAttributeValue("http-sender", pid, "ActiveConnections") + "\n"; + metrics += "LastSecondConnections: " + getAttributeValue("http-sender", pid, "LastSecondConnections") + "\n"; + metrics += "Last5SecondConnections: " + getAttributeValue("http-sender", pid, "Last5SecondConnections") + "\n"; + metrics += "Last15SecondConnections: " + getAttributeValue("http-sender", pid, "Last15SecondConnections") + "\n"; + metrics += "LastMinuteConnections: " + getAttributeValue("http-sender", pid, "LastMinuteConnections") + "\n"; + metrics += "LastSecondRequests: " + getAttributeValue("http-sender", pid, "LastSecondRequests") + "\n"; + metrics += "Last15SecondRequests: " + getAttributeValue("http-sender", pid, "Last15SecondRequests") + "\n"; + metrics += "LastMinuteRequests: " + getAttributeValue("http-sender", pid, "LastMinuteRequests") + "\n"; + + metrics += "\n"; + metrics += "Https Sender Metrics\n"; + metrics += "==============\n"; + metrics += "Active Connections: " + getAttributeValue("https-sender", pid, "ActiveConnections") + "\n"; + metrics += "LastSecondConnections: " + getAttributeValue("https-sender", pid, "LastSecondConnections") + "\n"; + metrics += "Last5SecondConnections: " + getAttributeValue("https-sender", pid, "Last5SecondConnections") + "\n"; + metrics += "Last15SecondConnections: " + getAttributeValue("https-sender", pid, "Last15SecondConnections") + "\n"; + metrics += "LastMinuteConnections: " + getAttributeValue("https-sender", pid, "LastMinuteConnections") + "\n"; + metrics += "LastSecondRequests: " + getAttributeValue("https-sender", pid, "LastSecondRequests") + "\n"; + metrics += "Last15SecondRequests: " + getAttributeValue("https-sender", pid, "Last15SecondRequests") + "\n"; + metrics += "LastMinuteRequests: " + getAttributeValue("https-sender", pid, "LastMinuteRequests") + "\n"; + metrics += "\n"; + + metrics += "Http Listener RequestMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("http-listener", pid, "RequestSizesMap"); + metrics += "\n"; + + metrics += "Http Listener ResponseMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("http-listener", pid, "ResponseSizesMap"); + metrics += "\n"; + + metrics += "Https Listener RequestMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("https-listener", pid, "RequestSizesMap"); + metrics += "\n"; + + metrics += "Https Listener ResponseMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("https-listener", pid, "ResponseSizesMap"); + metrics += "\n"; + + metrics += "Http Sender RequestMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("http-sender", pid, "RequestSizesMap"); + metrics += "\n"; + + metrics += "Http Sender ResponseMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("http-sender", pid, "ResponseSizesMap"); + metrics += "\n"; + + metrics += "Https Sender RequestMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("https-sender", pid, "RequestSizesMap"); + metrics += "\n"; + + metrics += "Https Sender ResponseMap\n"; + metrics += "==============\n"; + metrics += JMXDataRetriever.getAttributeValue("https-sender", pid, "ResponseSizesMap"); + metrics += "\n"; + + return metrics; + } +} diff --git a/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/SimpleMovingAverage.java b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/SimpleMovingAverage.java new file mode 100644 index 0000000000..f27fa43027 --- /dev/null +++ b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/SimpleMovingAverage.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.wso2.carbon.diagnostics.trafficanalyzer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class is responsible for calculating the Simple Moving Average of a given data set. + */ +public class SimpleMovingAverage { + + private final Logger log = LogManager.getLogger(SimpleMovingAverage.class); + + private final int windowSize; + private double ma; // Exponential Moving Average + + private double currentThreshold; + private final List tempList; + + public SimpleMovingAverage(int windowSize) { + + this.windowSize = windowSize; + this.ma = Double.NaN; + this.currentThreshold = Double.NaN; + this.tempList = new ArrayList<>(); + } + + public double update(int newDataPoint) { + + if (log.isDebugEnabled()) { + log.debug("Updating Simple Moving Average with new data point: " + newDataPoint); + } + addDataToList(newDataPoint); + List tempList = getTempList(); + Double ma = findAverage(tempList); + setMa(ma); + return ma; + } + + private double findAverage(List list) { + + int sum = 0; + for (int i : list) { + sum += i; + } + double average = (double) sum / list.size(); + if (log.isDebugEnabled()) { + log.debug("Simple Moving Average: " + average); + } + return average; + } + + public void addDataToList(int newData) { + + updateThresholdStd(); + if (tempList.size() < windowSize) { + tempList.add(newData); + } else { + tempList.remove(0); + tempList.add(newData); + } + } + + // Update the threshold using the standard deviation + private void updateThresholdStd() { + + double sumSquaredDiff = 0.0; + double k = 2; + for (int value : tempList) { + double diff = value - ma; + sumSquaredDiff += diff * diff; + } + double std = Math.sqrt(sumSquaredDiff / tempList.size()); + currentThreshold = ma + k * std; + if (log.isDebugEnabled()) { + log.debug("Updating Moving Average Threshold: " + currentThreshold); + } + } + + public List getTempList() { + + return tempList; + } + + + public void setMa(double ma) { + + this.ma = ma; + } + + public double getCurrentThreshold() { + + return currentThreshold; + } +} diff --git a/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzer.java b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzer.java new file mode 100644 index 0000000000..3c876def40 --- /dev/null +++ b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzer.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.wso2.carbon.diagnostics.trafficanalyzer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.wso2.diagnostics.actionexecutor.ServerProcess; +import org.wso2.diagnostics.watchers.Watcher; + +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import static org.wso2.diagnostics.utils.CommonUtils.getBooleanValue; +import static org.wso2.diagnostics.utils.CommonUtils.getIntegerValue; + +import static org.wso2.diagnostics.utils.Constants.LAST_SECOND_REQUESTS_ENABLED; +import static org.wso2.diagnostics.utils.Constants.LAST_SECOND_REQUESTS_WINDOW_SIZE; +import static org.wso2.diagnostics.utils.Constants.LAST_SECOND_REQUESTS_INTERVAL; +import static org.wso2.diagnostics.utils.Constants.LAST_SECOND_REQUESTS_DELAY; +import static org.wso2.diagnostics.utils.Constants.LAST_FIFTEEN_SECONDS_REQUESTS_ENABLED; +import static org.wso2.diagnostics.utils.Constants.LAST_FIFTEEN_SECONDS_REQUESTS_WINDOW_SIZE; +import static org.wso2.diagnostics.utils.Constants.LAST_FIFTEEN_SECONDS_REQUESTS_INTERVAL; +import static org.wso2.diagnostics.utils.Constants.LAST_FIFTEEN_SECONDS_REQUESTS_DELAY; +import static org.wso2.diagnostics.utils.Constants.LAST_MINUTE_REQUESTS_ENABLED; +import static org.wso2.diagnostics.utils.Constants.LAST_MINUTE_REQUESTS_WINDOW_SIZE; +import static org.wso2.diagnostics.utils.Constants.LAST_MINUTE_REQUESTS_INTERVAL; +import static org.wso2.diagnostics.utils.Constants.LAST_MINUTE_REQUESTS_DELAY; +import static org.wso2.diagnostics.utils.Constants.WATCHER_INITIAL_DELAY; + +/** + * This class is responsible for initialing TrafficAnalyzerRunnable threads. + */ +public class TrafficAnalyzer implements Watcher { + + private final Logger log = LogManager.getLogger(TrafficAnalyzer.class); + + ScheduledExecutorService globalExecutorService; + Map configMap; + + public void init(Map configMap) { + + this.globalExecutorService = Executors.newSingleThreadScheduledExecutor(); + this.configMap = configMap; + } + + public void start() { + + boolean isLastSecondRequestsEnabled = getBooleanValue(configMap.get(LAST_SECOND_REQUESTS_ENABLED), false); + if (isLastSecondRequestsEnabled) { + int lastSecondRequestsWindowSize = getIntegerValue(configMap.get(LAST_SECOND_REQUESTS_WINDOW_SIZE), 300); + int lastSecondRequestsInterval = getIntegerValue(configMap.get(LAST_SECOND_REQUESTS_INTERVAL), 1); + int lastSecondRequestsDelay = getIntegerValue(configMap.get(LAST_SECOND_REQUESTS_DELAY), 60); + TrafficAnalyzerRunnable lastSecondRequests = new TrafficAnalyzerRunnable(ServerProcess.getProcessId(), + lastSecondRequestsWindowSize, lastSecondRequestsDelay, "LastSecondRequests"); + globalExecutorService.scheduleAtFixedRate(lastSecondRequests, WATCHER_INITIAL_DELAY, + lastSecondRequestsInterval, java.util.concurrent.TimeUnit.SECONDS); + log.info("LastSecondRequests Traffic Analyzer is enabled with window size: " + lastSecondRequestsWindowSize + + ", interval: " + lastSecondRequestsInterval + ", delay: " + lastSecondRequestsDelay); + } + + boolean isLastFifteenSecondsRequestsEnabled = + getBooleanValue(configMap.get(LAST_FIFTEEN_SECONDS_REQUESTS_ENABLED), false); + if (isLastFifteenSecondsRequestsEnabled) { + int lastFifteenSecondsRequestsWindowSize = + getIntegerValue(configMap.get(LAST_FIFTEEN_SECONDS_REQUESTS_WINDOW_SIZE), 100); + int lastFifteenSecondsRequestsInterval = + getIntegerValue(configMap.get(LAST_FIFTEEN_SECONDS_REQUESTS_INTERVAL), 15); + int lastFifteenSecondsRequestsDelay = + getIntegerValue(configMap.get(LAST_FIFTEEN_SECONDS_REQUESTS_DELAY), 4); + TrafficAnalyzerRunnable + lastFifteenSecondsRequests = new TrafficAnalyzerRunnable(ServerProcess.getProcessId(), + lastFifteenSecondsRequestsWindowSize, lastFifteenSecondsRequestsDelay, "Last15SecondRequests"); + globalExecutorService.scheduleAtFixedRate(lastFifteenSecondsRequests, WATCHER_INITIAL_DELAY, + lastFifteenSecondsRequestsInterval, java.util.concurrent.TimeUnit.SECONDS); + log.info("LastFifteenSecondsRequests Traffic Analyzer is enabled with window size: " + + lastFifteenSecondsRequestsWindowSize + ", interval: " + lastFifteenSecondsRequestsInterval + + ", delay: " + lastFifteenSecondsRequestsDelay); + } + + boolean isLastMinuteRequestsEnabled = getBooleanValue(configMap.get(LAST_MINUTE_REQUESTS_ENABLED), false); + if (isLastMinuteRequestsEnabled) { + int lastMinuteRequestsWindowSize = getIntegerValue(configMap.get(LAST_MINUTE_REQUESTS_WINDOW_SIZE), 100); + int lastMinuteRequestsInterval = getIntegerValue(configMap.get(LAST_MINUTE_REQUESTS_INTERVAL), 60); + int lastMinuteRequestsDelay = getIntegerValue(configMap.get(LAST_MINUTE_REQUESTS_DELAY), 1); + TrafficAnalyzerRunnable lastMinuteRequests = new TrafficAnalyzerRunnable(ServerProcess.getProcessId(), + lastMinuteRequestsWindowSize, lastMinuteRequestsDelay, "LastMinuteRequests"); + globalExecutorService.scheduleAtFixedRate(lastMinuteRequests, WATCHER_INITIAL_DELAY, + lastMinuteRequestsInterval, java.util.concurrent.TimeUnit.SECONDS); + log.info("LastMinuteRequests Traffic Analyzer is enabled with window size: " + + lastMinuteRequestsWindowSize + ", interval: " + lastMinuteRequestsInterval + + ", delay: " + lastMinuteRequestsDelay); + } + } +} diff --git a/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzerRunnable.java b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzerRunnable.java new file mode 100644 index 0000000000..7b298abccf --- /dev/null +++ b/components/mediation-diagnostics/src/main/java/org/wso2/carbon/diagnostics/trafficanalyzer/TrafficAnalyzerRunnable.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you 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.wso2.carbon.diagnostics.trafficanalyzer; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.wso2.diagnostics.utils.ConfigMapHolder; +import org.wso2.diagnostics.utils.Constants; +import org.wso2.diagnostics.utils.JMXDataRetriever; + +import java.time.Duration; +import java.time.Instant; + +/** + * This class is responsible for analyzing the traffic of the server. + */ +public class TrafficAnalyzerRunnable implements Runnable { + + private static final Logger log = LogManager.getLogger(TrafficAnalyzerRunnable.class); + private final SimpleMovingAverage movingAverage; + int httpListenerValue = 0; + int httpSenderValue = 0; + int httpsListenerValue = 0; + int httpsSenderValue = 0; + String pid; + String attribute; + int delay; + int delayCounter; + private static Instant lastNotification; + + public TrafficAnalyzerRunnable(String pid, int windowSize, int delay, String attribute) { + + this.attribute = attribute; + this.pid = pid; + movingAverage = new SimpleMovingAverage(windowSize); + this.delay = delay; + delayCounter = 0; + } + + public void run() { + if (log.isDebugEnabled()) { + log.debug("Traffic analyzer thread executing for pid: " + pid + ", attribute: " + attribute + + ", delay: " + delay + ", delay counter: " + delayCounter + ", last notification: " + lastNotification); + } + int newHttpListenerAttributeValue = JMXDataRetriever.getIntAttributeValue("http-listener", pid, attribute); + needToAlert(httpListenerValue, newHttpListenerAttributeValue, "http-listener"); + httpListenerValue = newHttpListenerAttributeValue; + + int newHttpsListenerAttributeValue = JMXDataRetriever.getIntAttributeValue("https-listener", pid, attribute); + needToAlert(httpsListenerValue, newHttpsListenerAttributeValue, "https-listener"); + httpsListenerValue = newHttpsListenerAttributeValue; + + int newHttpSenderAttributeValue = JMXDataRetriever.getIntAttributeValue("http-sender", pid, attribute); + needToAlert(httpSenderValue, newHttpSenderAttributeValue, "http-sender"); + httpSenderValue = newHttpSenderAttributeValue; + + int newHttpsSenderAttributeValue = JMXDataRetriever.getIntAttributeValue("https-sender", pid, attribute); + needToAlert(httpsSenderValue, newHttpsSenderAttributeValue, "https-sender"); + httpsSenderValue = newHttpsSenderAttributeValue; + + } + + private void needToAlert(int oldValue, int newValue, String type) { + + if (log.isDebugEnabled()) { + log.debug("Checking if need to alert for attribute: " + attribute + ", type: " + type + + ", current Threshold: " + movingAverage.getCurrentThreshold() + ", new value: " + newValue); + } + boolean doNotify = true; + int notifyInterval = Integer.parseInt( + (String) ConfigMapHolder.getInstance().getConfigMap().get(Constants.TRAFFIC_NOTIFY_INTERVAL)); + if (lastNotification != null) { + Duration duration = Duration.between(lastNotification, Instant.now()); + if (duration.getSeconds() < notifyInterval) { + doNotify = false; + } + } + if (this.detectAnomalies(newValue) && doNotify) { + lastNotification = Instant.now(); + log.info("Attribute " + attribute + " of type " + type + " increased more than the threshold, old value: " + + oldValue + ", new value: " + newValue + ", threshold: " + movingAverage.getCurrentThreshold()); + } + } + + // Update EMAs for each time frame + public void update(int newDataPoint) { + + movingAverage.update(newDataPoint); + } + + public Double getThreshold() { + + return movingAverage.getCurrentThreshold(); + } + + public Boolean detectAnomalies(int newData) { + + if (newData <= 0) { + return Boolean.FALSE; + } + this.update(newData); + Double threshold = getThreshold(); + boolean isAnomaly = newData > threshold; + if (isAnomaly & delayCounter == 0) { + delayCounter = delay; + return Boolean.TRUE; + } + if (delayCounter != 0) { + delayCounter -= 1; + } + return Boolean.FALSE; + } +} diff --git a/pom.xml b/pom.xml index a54ee7e6bb..92736f530f 100644 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,7 @@ components/mediation-initializer components/mediation-monitor components/mediation-config-admin + components/mediation-diagnostics components/business-adaptors components/mediation-admin components/mediation-connector @@ -2472,6 +2473,11 @@ bsf-all ${bsf.version} + + org.wso2.runtime.diagnostics + runtime-diagnostics-tool + ${runtime.diagnostics.version} + @@ -2665,6 +2671,7 @@ 2.1.18.wso2v1 6.3.50 + 1.1.0