From 6e844c926130b64e716b6d13031db4ab913bb815 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:40:34 +0200 Subject: [PATCH 01/14] Sync in the middle, WIP --- .gitignore | 2 + README.adoc | 35 +- eclipse-java-formatter.xml | 450 +++++++++++++ license-header | 45 ++ pom.xml | 593 ++++++++++++++++++ src/main/assembly/jar-with-dependencies.xml | 21 + src/main/java/com/teragrep/rlp_11/Main.java | 97 +++ .../java/com/teragrep/rlp_11/RelpProbe.java | 175 ++++++ .../rlp_11/RelpProbeConfiguration.java | 187 ++++++ .../rlp_11/RelpProbeConfigurationError.java | 53 ++ .../com/teragrep/rlp_11/ConnectionTest.java | 135 ++++ .../rlp_11/InvalidConfigValidationTest.java | 219 +++++++ src/test/resources/connectiontest.properties | 17 + 13 files changed, 2011 insertions(+), 18 deletions(-) create mode 100644 .gitignore create mode 100644 eclipse-java-formatter.xml create mode 100644 license-header create mode 100644 pom.xml create mode 100644 src/main/assembly/jar-with-dependencies.xml create mode 100644 src/main/java/com/teragrep/rlp_11/Main.java create mode 100644 src/main/java/com/teragrep/rlp_11/RelpProbe.java create mode 100644 src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java create mode 100644 src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java create mode 100644 src/test/java/com/teragrep/rlp_11/ConnectionTest.java create mode 100644 src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java create mode 100644 src/test/resources/connectiontest.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92322c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +target/ diff --git a/README.adoc b/README.adoc index 0f563cc..e102f52 100644 --- a/README.adoc +++ b/README.adoc @@ -1,35 +1,34 @@ -// Before publishing your new repository: -// 1. Write the readme file -// 2. Update the issues link in Contributing section in the readme file -// 3. Update the discussion link in config.yml file in .github/ISSUE_TEMPLATE directory += RELP Commit Latency Probe rlp_11 -= repo-template - -// Add a short description of your project. Tell what your project does and what it's used for. - -This is a template repository for Teragrep organization. +Measures latency for RELP events. == Features -// List your project's features +Provides Dropwizard metrics -== Documentation +Provides Prometheus endpoint -See the official documentation on https://docs.teragrep.com[docs.teragrep.com]. +== Documentation == Limitations -// If your project has limitations, please list them. Otherwise remove this section. +== How to compile -== How to [compile/use/implement] +[source] +---- +mvn clean package +---- -// add instructions how people can start to use your project +== How to use -== Contributing +[source] +---- +java -jar rlp_11.jar +---- -// Change the repository name in the issues link to match with your project's name +== Contributing -You can involve yourself with our project by https://github.com/teragrep/repo-template/issues/new/choose[opening an issue] or submitting a pull request. +You can involve yourself with our project by https://github.com/teragrep/rlp_11/issues/new/choose[opening an issue] or submitting a pull request. Contribution requirements: diff --git a/eclipse-java-formatter.xml b/eclipse-java-formatter.xml new file mode 100644 index 0000000..53b9f2a --- /dev/null +++ b/eclipse-java-formatter.xml @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/license-header b/license-header new file mode 100644 index 0000000..1ace12e --- /dev/null +++ b/license-header @@ -0,0 +1,45 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5019ef4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,593 @@ + + + 4.0.0 + com.teragrep + rlp_11 + ${revision}${sha1}${changelist} + jar + rlp_11 + RELP Commit Latency Probe + https://teragrep.com + + -SNAPSHOT + 0.0.1-SNAPSHOT + 4.2.28 + 17 + 1.11.3 + 5.11.3 + 17 + 17 + UTF-8 + UTF-8 + 0.16.0 + 0.0.1 + 1.0.1 + 4.0.3 + 8.0.1 + + 2.0.16 + + + + + com.teragrep + cnf_01 + ${cnf_01.version} + + + + com.teragrep + rlp_01 + ${rlp_01.version} + + + + com.teragrep + rlo_14 + ${rlo_14.version} + + + + io.dropwizard.metrics + metrics-core + ${dropwizard.metrics.version} + + + io.dropwizard.metrics + metrics-jmx + ${dropwizard.metrics.version} + + + + io.prometheus + simpleclient + ${prometheus.version} + + + io.prometheus + simpleclient_dropwizard + ${prometheus.version} + + + io.prometheus + simpleclient_servlet + ${prometheus.version} + + + io.prometheus + simpleclient_hotspot + ${prometheus.version} + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} + + + + com.teragrep + rlp_03 + ${rlp_03.version} + test + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.version} + test + + + org.junit.platform + junit-platform-launcher + ${junit.platform.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + test + + + + ${project.basedir}/target + rlp_11 + + + true + src/main/resources + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.5.0 + + + + scan-errors + + check + + process-classes + + error + true + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + scan-warnings + + check + + process-classes + + warning + true + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.4.1 + + + enforce-settings + + enforce + + + + + + + junit:junit + + + + 3.6.53 + + + [17,18) + + + + + com.teragrep:*:0.0.1-SNAPSHOT + + + + All plugins are required to contain specific version. + org.apache.maven.plugins:maven-site-plugin,org.apache.maven.plugins:maven-resources-plugin,org.apache.maven.plugins:maven-clean-plugin,org.apache.maven.plugins:maven-install-plugin,org.apache.maven.plugins:maven-deploy-plugin,org.apache.maven.plugins:maven-compiler-plugin,org.apache.maven.plugins:maven-jar-plugin + + + Do not use any external repositories. + + + + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.43.0 + + + + ${project.basedir}/eclipse-java-formatter.xml + 4.10.0 + + + + ${project.basedir}/license-header + + + + + + UTF-8 + \n + true + false + 2 + recommended_2008_06 + true + true + true + + + + + + .gitattributes + .gitignore + + + + + true + 4 + + + + + + + + check + + compile + + + + + + org.apache.rat + apache-rat-plugin + 0.16.1 + false + + false + false + + + Teragrep + Affero General Public License v3 + + + + + + + Suomen Kanuuna Oy + 2024 + + RELP Commit Latency Probe RLP-11 + + Teragrep + + + true + false + + + .git/** + .gitattributes + .gitignore + .gitmodules + + .github/workflows/* + .github/ISSUE_TEMPLATE/* + .github/PULL_REQUEST_TEMPLATE/* + toolchains.xml + settings.xml + + pom.xml + eclipse-java-formatter.xml + src/main/assembly/jar-with-dependencies.xml + + src/test/resources/*.properties + + README.adoc + + + + + + check + + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.7.1 + + + src/main/assembly/jar-with-dependencies.xml + + + + com.teragrep.rlp_11.Main + true + + + + + + make-assembly + + single + + package + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.2 + + all + true + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.2 + + + + integration-test + verify + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.3 + + false + + + + + + + publish-github-packages + + + github + GitHub Packages + https://maven.pkg.github.com/teragrep/rlp_11 + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + + sign + + verify + + + --pinentry-mode + loopback + + + + + + + + + + diff --git a/src/main/assembly/jar-with-dependencies.xml b/src/main/assembly/jar-with-dependencies.xml new file mode 100644 index 0000000..16d41cd --- /dev/null +++ b/src/main/assembly/jar-with-dependencies.xml @@ -0,0 +1,21 @@ + + jar-with-dependencies + + jar + + false + + + metaInf-services + + + + + true + true + runtime + + + diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java new file mode 100644 index 0000000..f98885f --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -0,0 +1,97 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import com.teragrep.cnf_01.ConfigurationException; +import com.teragrep.cnf_01.PathConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +public class Main { + + private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); + + public static void main(final String[] args) { + PathConfiguration pathConfiguration = new PathConfiguration( + System.getProperty("configurationPath", "etc/rlp_11.properties") + ); + Map map; + try { + map = pathConfiguration.asMap(); + } + catch (ConfigurationException e) { + LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage(), e); + return; + } + RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); + try { + relpProbeConfiguration.validate(); + } + catch (RelpProbeConfigurationError e) { + LOGGER.error("Failed to validate config: <{}>", e.getMessage(), e); + } + + RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); + Thread shutdownHook = new Thread(() -> { + LOGGER.info("Shutting down..."); + relpProbe.stop(); + }); + Runtime.getRuntime().addShutdownHook(shutdownHook); + LOGGER + .info( + "Sending events to <[{}:{}]>", relpProbeConfiguration.getTargetHostname(), + relpProbeConfiguration.getTargetPort() + ); + LOGGER + .info( + "Using hostname <[{}]> and appname <[{}]> for the events.", + relpProbeConfiguration.getEventHostname(), relpProbeConfiguration.getEventAppname() + ); + relpProbe.start(); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java new file mode 100644 index 0000000..8f9dc29 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -0,0 +1,175 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import com.teragrep.rlo_14.Facility; +import com.teragrep.rlo_14.Severity; +import com.teragrep.rlo_14.SyslogMessage; +import com.teragrep.rlp_01.RelpBatch; +import com.teragrep.rlp_01.RelpConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class RelpProbe { + + private final RelpProbeConfiguration config; + private boolean stayRunning = true; + private RelpConnection relpConnection; + private final CountDownLatch latch = new CountDownLatch(1); + private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); + private boolean connected = false; + + public RelpProbe(RelpProbeConfiguration config) { + this.config = config; + } + + public void start() { + relpConnection = new RelpConnection(); + connect(); + int eventDelay = config.getEventDelay(); + while (stayRunning) { + RelpBatch relpBatch = new RelpBatch(); + Instant timestamp = Instant.now(); + byte[] record = new SyslogMessage() + .withTimestamp(timestamp.toEpochMilli()) + .withAppName(config.getEventAppname()) + .withHostname(config.getEventHostname()) + .withFacility(Facility.USER) + .withSeverity(Severity.INFORMATIONAL) + .withMsg(timestamp.getEpochSecond() + "." + timestamp.getNano()) + .toRfc5424SyslogMessage() + .getBytes(StandardCharsets.UTF_8); + relpBatch.insert(record); + + boolean allSent = false; + while (!allSent) { + try { + relpConnection.commit(relpBatch); + } + catch (IllegalStateException | IOException | java.util.concurrent.TimeoutException e) { + LOGGER.warn("Failed to commit: <{}>", e.getMessage()); + relpConnection.tearDown(); + connected = false; + } + allSent = relpBatch.verifyTransactionAll(); + if (!allSent) { + relpBatch.retryAllFailed(); + reconnect(); + } + } + try { + Thread.sleep(eventDelay); + } + catch (InterruptedException e) { + LOGGER.warn("Sleep interrupted: <{}>", e.getMessage()); + } + } + + } + + private void connect() { + while (!connected && stayRunning) { + try { + connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); + } + catch (TimeoutException | IOException e) { + LOGGER + .warn( + "Failed to connect to <[{}:{}]>: <{}>", config.getTargetHostname(), + config.getTargetPort(), e.getMessage() + ); + } + if (!connected) { + try { + Thread.sleep(config.getReconnectInterval()); + } + catch (InterruptedException e) { + LOGGER.warn("Sleep was interrupted: <{}>", e.getMessage()); + } + } + } + } + + private void reconnect() { + disconnect(); + connect(); + } + + private void disconnect() { + if (!connected) { + return; + } + try { + relpConnection.disconnect(); + } + catch (IOException | TimeoutException e) { + LOGGER.warn("Failed to disconnect: <{}>", e.getMessage()); + } + relpConnection.tearDown(); + connected = false; + } + + public void stop() { + disconnect(); + stayRunning = false; + try { + if (!latch.await(5L, TimeUnit.SECONDS)) { + throw new RuntimeException("Timed out while waiting for probe to shutdown."); + } + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java new file mode 100644 index 0000000..6adda51 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java @@ -0,0 +1,187 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Map; + +public class RelpProbeConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbeConfiguration.class); + private final Map config; + + public RelpProbeConfiguration(Map config) { + this.config = config; + } + + public void validate() throws RelpProbeConfigurationError { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Validating the following configuration: {}", config); + } + + if (config.get("event.hostname") == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + + if (config.get("event.appname") == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + + String eventDelay = config.get("event.delay"); + if (eventDelay == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + try { + int eventDelayInt = Integer.parseInt(eventDelay); + if (eventDelayInt <= 0) { + LOGGER.error("Invalid property, expected > 0, received <[{}]>", eventDelay); + throw new RelpProbeConfigurationError( + "Invalid property, expected > 0, received <[" + eventDelay + "]>" + ); + } + } + catch (NumberFormatException e) { + LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + throw new RelpProbeConfigurationError( + "Invalid property received, not a number: <" + e.getMessage() + ">" + ); + } + + if (config.get("target.hostname") == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + + String targetPort = config.get("target.port"); + if (targetPort == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + try { + int targetPortInt = Integer.parseInt(targetPort); + if (targetPortInt <= 0 || targetPortInt > 65535) { + LOGGER + .error( + "Invalid property, expected between 1 and 65535, received <[{}]>", + targetPort + ); + throw new RelpProbeConfigurationError( + "Invalid property, expected between 1 and 65535, received <[" + targetPort + "]>" + ); + } + } + catch (NumberFormatException e) { + LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + throw new RelpProbeConfigurationError( + "Invalid property received, not a number: <" + e.getMessage() + ">" + ); + } + + if (config.get("prometheus.endpoint") == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + + String reconnectInterval = config.get("relp.reconnectinterval"); + if (reconnectInterval == null) { + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); + } + try { + int reconnectIntervalInt = Integer.parseInt(reconnectInterval); + if (reconnectIntervalInt <= 0) { + LOGGER + .error( + "Invalid property, property, expected > 0, received <[{}]>", + reconnectIntervalInt + ); + throw new RelpProbeConfigurationError( + "Invalid property, expected > 0, received <[" + reconnectInterval + + "]>" + ); + } + } + catch (NumberFormatException e) { + LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + throw new RelpProbeConfigurationError( + "Invalid property received, not a number: <" + e.getMessage() + ">" + ); + } + } + + public String getEventHostname() { + return config.get("event.hostname"); + } + + public String getEventAppname() { + return config.get("event.appname"); + } + + public int getEventDelay() { + return Integer.parseInt(config.get("event.delay")); + } + + public String getTargetHostname() { + return config.get("target.hostname"); + } + + public int getTargetPort() { + return Integer.parseInt(config.get("target.port")); + } + + public String getPrometheusEndpoint() { + return config.get("prometheus.endpoint"); + } + + public int getReconnectInterval() { + return Integer.parseInt(config.get("relp.reconnectinterval")); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java new file mode 100644 index 0000000..f0c966d --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java @@ -0,0 +1,53 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +public class RelpProbeConfigurationError extends RuntimeException { + + public RelpProbeConfigurationError(String s) { + super(s); + } +} diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java new file mode 100644 index 0000000..42f0ee0 --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -0,0 +1,135 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import com.teragrep.cnf_01.PathConfiguration; +import com.teragrep.net_01.channel.socket.PlainFactory; +import com.teragrep.net_01.eventloop.EventLoop; +import com.teragrep.net_01.eventloop.EventLoopFactory; +import com.teragrep.net_01.server.ServerFactory; +import com.teragrep.rlp_03.frame.FrameDelegationClockFactory; +import com.teragrep.rlp_03.frame.RelpFrame; +import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate; +import com.teragrep.rlp_03.frame.delegate.FrameContext; +import com.teragrep.rlp_03.frame.delegate.FrameDelegate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class ConnectionTest { + + private static final int serverPort = 12345; + private Thread eventLoopThread; + private EventLoop eventLoop; + private ExecutorService executorService; + private final List records = new ArrayList<>(); + + @BeforeEach + public void StartServer() { + executorService = Executors.newFixedThreadPool(1); + Consumer syslogConsumer = new Consumer<>() { + + @Override + public synchronized void accept(FrameContext frameContext) { + try (RelpFrame relpFrame = frameContext.relpFrame()) { + records.add(relpFrame.payload().toString()); + } + } + }; + Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate(syslogConsumer); + EventLoopFactory eventLoopFactory = new EventLoopFactory(); + eventLoop = Assertions.assertDoesNotThrow(eventLoopFactory::create); + eventLoopThread = new Thread(eventLoop); + eventLoopThread.start(); + ServerFactory serverFactory = new ServerFactory( + eventLoop, + executorService, + new PlainFactory(), + new FrameDelegationClockFactory(frameDelegateSupplier) + ); + Assertions.assertDoesNotThrow(() -> serverFactory.create(serverPort)); + } + + @AfterEach + public void StopServer() { + eventLoop.stop(); + Assertions.assertDoesNotThrow(() -> eventLoopThread.join()); + executorService.shutdown(); + records.clear(); + } + + @Test + public void ConnectToServerTest() { + RelpProbeConfiguration relpProbeConfiguration = Assertions + .assertDoesNotThrow( + () -> new RelpProbeConfiguration( + new PathConfiguration("src/test/resources/connectiontest.properties").asMap() + ) + ); + RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); + + TimerTask task = new TimerTask() { + + public void run() { + relpProbe.stop(); + } + }; + Timer timer = new Timer("Timer"); + timer.schedule(task, 5000L); + + relpProbe.start(); + } +} diff --git a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java new file mode 100644 index 0000000..5bafae4 --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java @@ -0,0 +1,219 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class InvalidConfigValidationTest { + + // event.hostname tests + @Test + public void TestMissingEventHostname() { + Map map = getDefaultMap(); + map.remove("event.hostname"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + // event.appname tests + @Test + public void testMissingAppname() { + Map map = getDefaultMap(); + map.remove("event.appname"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + // event.delay tests + @Test + public void testMissingEventDelay() { + Map map = getDefaultMap(); + map.remove("event.delay"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + @Test + public void testZeroEventDelay() { + Map map = getDefaultMap(); + map.put("event.delay", "0"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Invalid property, expected > 0, received <[0]>", e.getMessage()); + } + + @Test + public void testNonNumericEventDelay() { + Map map = getDefaultMap(); + map.put("event.delay", "not a number"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property received, not a number: ", + e.getMessage() + ); + } + + // target.hostname tests + @Test + public void testMissingTargetHostname() { + Map map = getDefaultMap(); + map.remove("target.hostname"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + // target.port tests + @Test + public void testMissingPort() { + Map map = getDefaultMap(); + map.remove("target.port"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + @Test + public void testTooSmallTargetPort() { + Map map = getDefaultMap(); + map.put("target.port", "0"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property, expected between 1 and 65535, received <[0]>", e.getMessage() + ); + } + + @Test + public void testTooHighTargetPort() { + Map map = getDefaultMap(); + map.put("target.port", "65536"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property, expected between 1 and 65535, received <[65536]>", + e.getMessage() + ); + } + + @Test + public void testNonNumericTargetPort() { + Map map = getDefaultMap(); + map.put("target.port", "not a number"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property received, not a number: ", + e.getMessage() + ); + } + + // relp.reconnectinterval tests + @Test + public void testMissingReconnectInterval() { + Map map = getDefaultMap(); + map.remove("relp.reconnectinterval"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + @Test + public void testZeroReconnectInterval() { + Map map = getDefaultMap(); + map.put("relp.reconnectinterval", "0"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals("Invalid property, expected > 0, received <[0]>", e.getMessage()); + } + + @Test + public void testNonNumericReconnectInterval() { + Map map = getDefaultMap(); + map.put("relp.reconnectinterval", "not a number"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property received, not a number: ", + e.getMessage() + ); + } + + // prometheus.endport tests + @Test + public void testMissingPrometheusEndpoint() { + Map map = getDefaultMap(); + map.remove("prometheus.endpoint"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + private Map getDefaultMap() { + Map map = new HashMap<>(); + map.put("event.hostname", "rlp_11"); + map.put("event.appname", "rlp_11"); + map.put("event.delay", "1000"); + map.put("target.hostname", "127.0.0.1"); + map.put("target.port", "12345"); + map.put("prometheus.endpoint", "127.0.0.1:8080"); + return map; + } +} diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties new file mode 100644 index 0000000..a92dad6 --- /dev/null +++ b/src/test/resources/connectiontest.properties @@ -0,0 +1,17 @@ +# Hostname used in RELP event +event.hostname=rlp_11 +# Appname used in RELP event +event.appname=rlp_11 +# Delay between sending events, in milliseconds +event.delay=1000 + +# RELP Server target address +target.hostname=127.0.0.1 +# Relp Server target port +target.port=12345 + +# RELP reconnect interval +relp.reconnectinterval=1000 + +# Prometheus endpoint port +prometheus.endpoint=127.0.0.1:8080 From 3d4dc6e3b5f7e0f8037385aab74fd543d14784ed Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:53:04 +0200 Subject: [PATCH 02/14] Some minor fixes --- src/main/java/com/teragrep/rlp_11/Main.java | 3 ++- src/main/java/com/teragrep/rlp_11/RelpProbe.java | 9 ++++++--- .../teragrep/rlp_11/RelpProbeConfiguration.java | 16 ++++++++-------- .../java/com/teragrep/rlp_11/ConnectionTest.java | 5 +++++ .../rlp_11/InvalidConfigValidationTest.java | 15 +++++++++------ src/test/resources/connectiontest.properties | 5 ++--- 6 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index f98885f..f9bf13a 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -78,8 +78,9 @@ public static void main(final String[] args) { RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); Thread shutdownHook = new Thread(() -> { - LOGGER.info("Shutting down..."); + LOGGER.info("Stopping RelpProbe.."); relpProbe.stop(); + LOGGER.info("Shutting down."); }); Runtime.getRuntime().addShutdownHook(shutdownHook); LOGGER diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 8f9dc29..377333c 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -93,7 +93,7 @@ public void start() { relpBatch.insert(record); boolean allSent = false; - while (!allSent) { + while (!allSent && stayRunning) { try { relpConnection.commit(relpBatch); } @@ -115,7 +115,10 @@ public void start() { LOGGER.warn("Sleep interrupted: <{}>", e.getMessage()); } } - + LOGGER.info("Disconnecting.."); + disconnect(); + LOGGER.info("Disconnected."); + latch.countDown(); } private void connect() { @@ -161,7 +164,6 @@ private void disconnect() { } public void stop() { - disconnect(); stayRunning = false; try { if (!latch.await(5L, TimeUnit.SECONDS)) { @@ -171,5 +173,6 @@ public void stop() { catch (InterruptedException e) { throw new RuntimeException(e); } + LOGGER.info("RelpProbe stopped."); } } diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java index 6adda51..bbcf1fa 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java @@ -130,29 +130,29 @@ public void validate() throws RelpProbeConfigurationError { throw new RelpProbeConfigurationError("Missing property"); } - String reconnectInterval = config.get("relp.reconnectinterval"); + String reconnectInterval = config.get("target.reconnectinterval"); if (reconnectInterval == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); + LOGGER.error("Missing property"); + throw new RelpProbeConfigurationError("Missing property"); } try { int reconnectIntervalInt = Integer.parseInt(reconnectInterval); if (reconnectIntervalInt <= 0) { LOGGER .error( - "Invalid property, property, expected > 0, received <[{}]>", + "Invalid property, property, expected > 0, received <[{}]>", reconnectIntervalInt ); throw new RelpProbeConfigurationError( - "Invalid property, expected > 0, received <[" + reconnectInterval + "Invalid property, expected > 0, received <[" + reconnectInterval + "]>" ); } } catch (NumberFormatException e) { - LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); throw new RelpProbeConfigurationError( - "Invalid property received, not a number: <" + e.getMessage() + ">" + "Invalid property received, not a number: <" + e.getMessage() + ">" ); } } @@ -182,6 +182,6 @@ public String getPrometheusEndpoint() { } public int getReconnectInterval() { - return Integer.parseInt(config.get("relp.reconnectinterval")); + return Integer.parseInt(config.get("target.reconnectinterval")); } } diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 42f0ee0..7242110 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -59,6 +59,8 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; @@ -76,6 +78,7 @@ public class ConnectionTest { private EventLoop eventLoop; private ExecutorService executorService; private final List records = new ArrayList<>(); + private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionTest.class); @BeforeEach public void StartServer() { @@ -131,5 +134,7 @@ public void run() { timer.schedule(task, 5000L); relpProbe.start(); + + LOGGER.info("Got records: {}", records); } } diff --git a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java index 5bafae4..6b015ae 100644 --- a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java +++ b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java @@ -167,31 +167,33 @@ public void testNonNumericTargetPort() { @Test public void testMissingReconnectInterval() { Map map = getDefaultMap(); - map.remove("relp.reconnectinterval"); + map.remove("target.reconnectinterval"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); + Assertions.assertEquals("Missing property", e.getMessage()); } @Test public void testZeroReconnectInterval() { Map map = getDefaultMap(); - map.put("relp.reconnectinterval", "0"); + map.put("target.reconnectinterval", "0"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); Assertions - .assertEquals("Invalid property, expected > 0, received <[0]>", e.getMessage()); + .assertEquals( + "Invalid property, expected > 0, received <[0]>", e.getMessage() + ); } @Test public void testNonNumericReconnectInterval() { Map map = getDefaultMap(); - map.put("relp.reconnectinterval", "not a number"); + map.put("target.reconnectinterval", "not a number"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); Assertions .assertEquals( - "Invalid property received, not a number: ", + "Invalid property received, not a number: ", e.getMessage() ); } @@ -213,6 +215,7 @@ private Map getDefaultMap() { map.put("event.delay", "1000"); map.put("target.hostname", "127.0.0.1"); map.put("target.port", "12345"); + map.put("target.reconnectinterval", "1000"); map.put("prometheus.endpoint", "127.0.0.1:8080"); return map; } diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties index a92dad6..ed8f4b2 100644 --- a/src/test/resources/connectiontest.properties +++ b/src/test/resources/connectiontest.properties @@ -9,9 +9,8 @@ event.delay=1000 target.hostname=127.0.0.1 # Relp Server target port target.port=12345 - -# RELP reconnect interval -relp.reconnectinterval=1000 +# RELP Server reconnect interval +target.reconnectinterval=1000 # Prometheus endpoint port prometheus.endpoint=127.0.0.1:8080 From b8e027a2c54598f5a5b1bdeec18163379a462dcc Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:15:08 +0200 Subject: [PATCH 03/14] Change slf4j simple to log4j2, some logging tweaks --- pom.xml | 14 ++++++++--- .../java/com/teragrep/rlp_11/RelpProbe.java | 11 ++++++-- src/main/resources/log4j2.xml | 16 ++++++++++++ .../com/teragrep/rlp_11/ConnectionTest.java | 25 ++++++++++++++++--- .../rlp_11/InvalidConfigValidationTest.java | 2 +- 5 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/log4j2.xml diff --git a/pom.xml b/pom.xml index 5019ef4..1109388 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ 17 1.11.3 5.11.3 + 2.24.1 17 17 UTF-8 @@ -85,9 +86,14 @@ ${slf4j.version} - org.slf4j - slf4j-simple - ${slf4j.version} + org.apache.logging.log4j + log4j-core + ${log4j2.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j2.version} @@ -483,6 +489,8 @@ src/main/assembly/jar-with-dependencies.xml src/test/resources/*.properties + + src/main/resources/log4j2.xml README.adoc diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 377333c..bebbe11 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -95,6 +95,7 @@ public void start() { boolean allSent = false; while (!allSent && stayRunning) { try { + LOGGER.debug("Committing Relpbatch"); relpConnection.commit(relpBatch); } catch (IllegalStateException | IOException | java.util.concurrent.TimeoutException e) { @@ -102,28 +103,30 @@ public void start() { relpConnection.tearDown(); connected = false; } + LOGGER.debug("Verifying Transaction"); allSent = relpBatch.verifyTransactionAll(); if (!allSent) { + LOGGER.warn("Transactions failed, retrying"); relpBatch.retryAllFailed(); reconnect(); } } try { + LOGGER.debug("Sleeping before sending next event"); Thread.sleep(eventDelay); } catch (InterruptedException e) { LOGGER.warn("Sleep interrupted: <{}>", e.getMessage()); } } - LOGGER.info("Disconnecting.."); disconnect(); - LOGGER.info("Disconnected."); latch.countDown(); } private void connect() { while (!connected && stayRunning) { try { + LOGGER.info("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); } catch (TimeoutException | IOException e) { @@ -135,6 +138,7 @@ private void connect() { } if (!connected) { try { + LOGGER.info("Sleeping for <[{}]>ms before reconnecting", config.getReconnectInterval()); Thread.sleep(config.getReconnectInterval()); } catch (InterruptedException e) { @@ -151,9 +155,11 @@ private void reconnect() { private void disconnect() { if (!connected) { + LOGGER.debug("No need to disconnect, not connected"); return; } try { + LOGGER.info("Disconnecting.."); relpConnection.disconnect(); } catch (IOException | TimeoutException e) { @@ -164,6 +170,7 @@ private void disconnect() { } public void stop() { + LOGGER.debug("Stop called"); stayRunning = false; try { if (!latch.await(5L, TimeUnit.SECONDS)) { diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..959d7dc --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 7242110..4dc0791 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -81,8 +81,10 @@ public class ConnectionTest { private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionTest.class); @BeforeEach - public void StartServer() { - executorService = Executors.newFixedThreadPool(1); + public void startServer() { + LOGGER.info("Creating SingleThreadExecutor"); + executorService = Executors.newSingleThreadExecutor(); + LOGGER.info("Creating consumer"); Consumer syslogConsumer = new Consumer<>() { @Override @@ -92,30 +94,45 @@ public synchronized void accept(FrameContext frameContext) { } } }; + + LOGGER.info("Creating FrameDelegateSuplpier"); Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate(syslogConsumer); + LOGGER.info("Creating EventLoopFactory"); EventLoopFactory eventLoopFactory = new EventLoopFactory(); + LOGGER.info("Craeting eventLoopp"); eventLoop = Assertions.assertDoesNotThrow(eventLoopFactory::create); + LOGGER.info("Creating eventLoopThread"); eventLoopThread = new Thread(eventLoop); + LOGGER.info("Starting eventLoppThread"); eventLoopThread.start(); + + LOGGER.info("Creating ServerFactory"); ServerFactory serverFactory = new ServerFactory( eventLoop, executorService, new PlainFactory(), new FrameDelegationClockFactory(frameDelegateSupplier) ); + + LOGGER.info("Creating Server"); Assertions.assertDoesNotThrow(() -> serverFactory.create(serverPort)); + LOGGER.info("Leaving startServer"); } @AfterEach - public void StopServer() { + public void stopServer() { + LOGGER.info("Stopping server"); eventLoop.stop(); + LOGGER.info("Joining server"); Assertions.assertDoesNotThrow(() -> eventLoopThread.join()); + LOGGER.info("Shutting down executorService"); executorService.shutdown(); + LOGGER.info("Clearing records"); records.clear(); } @Test - public void ConnectToServerTest() { + public void connectToServerTest() { RelpProbeConfiguration relpProbeConfiguration = Assertions .assertDoesNotThrow( () -> new RelpProbeConfiguration( diff --git a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java index 6b015ae..2d83a8f 100644 --- a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java +++ b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java @@ -55,7 +55,7 @@ public class InvalidConfigValidationTest { // event.hostname tests @Test - public void TestMissingEventHostname() { + public void testMissingEventHostname() { Map map = getDefaultMap(); map.remove("event.hostname"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); From 882ac75204ad06b1a30fdca4977b10a6f7d526a8 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:09:28 +0200 Subject: [PATCH 04/14] Fixes server --- src/main/java/com/teragrep/rlp_11/Main.java | 5 +- .../java/com/teragrep/rlp_11/RelpProbe.java | 2 + .../com/teragrep/rlp_11/ConnectionTest.java | 60 +++++++------------ 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index f9bf13a..2b67ee0 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -60,13 +60,13 @@ public static void main(final String[] args) { PathConfiguration pathConfiguration = new PathConfiguration( System.getProperty("configurationPath", "etc/rlp_11.properties") ); - Map map; + Map map = null; try { map = pathConfiguration.asMap(); } catch (ConfigurationException e) { LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage(), e); - return; + System.exit(1); } RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); try { @@ -74,6 +74,7 @@ public static void main(final String[] args) { } catch (RelpProbeConfigurationError e) { LOGGER.error("Failed to validate config: <{}>", e.getMessage(), e); + System.exit(1); } RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index bebbe11..24389e9 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -128,6 +128,7 @@ private void connect() { try { LOGGER.info("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); + LOGGER.info("Connected."); } catch (TimeoutException | IOException e) { LOGGER @@ -166,6 +167,7 @@ private void disconnect() { LOGGER.warn("Failed to disconnect: <{}>", e.getMessage()); } relpConnection.tearDown(); + LOGGER.info("Disconnected."); connected = false; } diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 4dc0791..80fa4cd 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -49,11 +49,10 @@ import com.teragrep.net_01.channel.socket.PlainFactory; import com.teragrep.net_01.eventloop.EventLoop; import com.teragrep.net_01.eventloop.EventLoopFactory; +import com.teragrep.net_01.server.Server; import com.teragrep.net_01.server.ServerFactory; import com.teragrep.rlp_03.frame.FrameDelegationClockFactory; -import com.teragrep.rlp_03.frame.RelpFrame; import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate; -import com.teragrep.rlp_03.frame.delegate.FrameContext; import com.teragrep.rlp_03.frame.delegate.FrameDelegate; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -66,68 +65,55 @@ import java.util.List; import java.util.Timer; import java.util.TimerTask; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.function.Consumer; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; public class ConnectionTest { - private static final int serverPort = 12345; + private final int serverPort = 12345; private Thread eventLoopThread; private EventLoop eventLoop; - private ExecutorService executorService; + private ThreadPoolExecutor threadPoolExecutor; private final List records = new ArrayList<>(); private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionTest.class); + private Server server; @BeforeEach public void startServer() { - LOGGER.info("Creating SingleThreadExecutor"); - executorService = Executors.newSingleThreadExecutor(); - LOGGER.info("Creating consumer"); - Consumer syslogConsumer = new Consumer<>() { - - @Override - public synchronized void accept(FrameContext frameContext) { - try (RelpFrame relpFrame = frameContext.relpFrame()) { - records.add(relpFrame.payload().toString()); - } - } - }; - - LOGGER.info("Creating FrameDelegateSuplpier"); - Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate(syslogConsumer); - LOGGER.info("Creating EventLoopFactory"); EventLoopFactory eventLoopFactory = new EventLoopFactory(); - LOGGER.info("Craeting eventLoopp"); eventLoop = Assertions.assertDoesNotThrow(eventLoopFactory::create); - LOGGER.info("Creating eventLoopThread"); + eventLoopThread = new Thread(eventLoop); - LOGGER.info("Starting eventLoppThread"); eventLoopThread.start(); - LOGGER.info("Creating ServerFactory"); + Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate( + frameContext -> records.add(frameContext.relpFrame().payload().toString()) + ); + + threadPoolExecutor = new ThreadPoolExecutor( + 1, + 1, + Long.MAX_VALUE, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>() + ); ServerFactory serverFactory = new ServerFactory( eventLoop, - executorService, + threadPoolExecutor, new PlainFactory(), new FrameDelegationClockFactory(frameDelegateSupplier) ); - - LOGGER.info("Creating Server"); - Assertions.assertDoesNotThrow(() -> serverFactory.create(serverPort)); - LOGGER.info("Leaving startServer"); + server = Assertions.assertDoesNotThrow(() -> serverFactory.create(serverPort)); } @AfterEach public void stopServer() { - LOGGER.info("Stopping server"); eventLoop.stop(); - LOGGER.info("Joining server"); + threadPoolExecutor.shutdown(); Assertions.assertDoesNotThrow(() -> eventLoopThread.join()); - LOGGER.info("Shutting down executorService"); - executorService.shutdown(); - LOGGER.info("Clearing records"); + Assertions.assertDoesNotThrow(server::close); records.clear(); } From f63986345c16abf9b6f8d2661d56d382d1921de8 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:29:03 +0200 Subject: [PATCH 05/14] Adds json formatting to events, fixes checkstyle stuff --- pom.xml | 13 ++++++++ src/main/java/com/teragrep/rlp_11/Main.java | 8 ++--- .../java/com/teragrep/rlp_11/RelpProbe.java | 31 ++++++++++++++----- .../rlp_11/RelpProbeConfiguration.java | 24 +++++++------- .../rlp_11/RelpProbeConfigurationError.java | 2 +- src/test/resources/connectiontest.properties | 10 +++--- 6 files changed, 60 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index 1109388..4eea39c 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,8 @@ -SNAPSHOT 0.0.1-SNAPSHOT 4.2.28 + 1.1.7 + 2.1.3 17 1.11.3 5.11.3 @@ -95,6 +97,17 @@ log4j-slf4j2-impl ${log4j2.version} + + + jakarta.json + jakarta.json-api + ${jakarta.json.version} + + + org.eclipse.parsson + parsson + ${eclipse.parsson.version} + com.teragrep diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index 2b67ee0..a5a41de 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -57,7 +57,7 @@ public class Main { private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); public static void main(final String[] args) { - PathConfiguration pathConfiguration = new PathConfiguration( + final PathConfiguration pathConfiguration = new PathConfiguration( System.getProperty("configurationPath", "etc/rlp_11.properties") ); Map map = null; @@ -68,7 +68,7 @@ public static void main(final String[] args) { LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage(), e); System.exit(1); } - RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); + final RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); try { relpProbeConfiguration.validate(); } @@ -77,8 +77,8 @@ public static void main(final String[] args) { System.exit(1); } - RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); - Thread shutdownHook = new Thread(() -> { + final RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); + final Thread shutdownHook = new Thread(() -> { LOGGER.info("Stopping RelpProbe.."); relpProbe.stop(); LOGGER.info("Shutting down."); diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 24389e9..c1eaeca 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -54,40 +54,57 @@ import org.slf4j.LoggerFactory; import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.concurrent.CountDownLatch; import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import jakarta.json.Json; +import jakarta.json.JsonObject; public class RelpProbe { + private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); private final RelpProbeConfiguration config; private boolean stayRunning = true; private RelpConnection relpConnection; private final CountDownLatch latch = new CountDownLatch(1); - private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); private boolean connected = false; - public RelpProbe(RelpProbeConfiguration config) { + public RelpProbe(final RelpProbeConfiguration config) { this.config = config; } public void start() { + String origin; + try { + origin = InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) { + origin = "localhost"; + LOGGER.warn("Could not get hostname, using <{}> instead", origin); + } relpConnection = new RelpConnection(); connect(); - int eventDelay = config.getEventDelay(); + final int eventDelay = config.getEventDelay(); while (stayRunning) { - RelpBatch relpBatch = new RelpBatch(); - Instant timestamp = Instant.now(); - byte[] record = new SyslogMessage() + final RelpBatch relpBatch = new RelpBatch(); + final Instant timestamp = Instant.now(); + final JsonObject event = Json + .createObjectBuilder() + .add("origin", origin) + .add("timestamp", timestamp.getEpochSecond() + "." + timestamp.getNano()) + .build(); + final byte[] record = new SyslogMessage() .withTimestamp(timestamp.toEpochMilli()) .withAppName(config.getEventAppname()) .withHostname(config.getEventHostname()) .withFacility(Facility.USER) .withSeverity(Severity.INFORMATIONAL) - .withMsg(timestamp.getEpochSecond() + "." + timestamp.getNano()) + .withMsg(event.toString()) .toRfc5424SyslogMessage() .getBytes(StandardCharsets.UTF_8); relpBatch.insert(record); diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java index bbcf1fa..5f066b1 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java @@ -53,9 +53,10 @@ public class RelpProbeConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbeConfiguration.class); + private static final int MAXIMUM_PORT = 65535; private final Map config; - public RelpProbeConfiguration(Map config) { + public RelpProbeConfiguration(final Map config) { this.config = config; } @@ -74,13 +75,13 @@ public void validate() throws RelpProbeConfigurationError { throw new RelpProbeConfigurationError("Missing property"); } - String eventDelay = config.get("event.delay"); + final String eventDelay = config.get("event.delay"); if (eventDelay == null) { LOGGER.error("Missing property"); throw new RelpProbeConfigurationError("Missing property"); } try { - int eventDelayInt = Integer.parseInt(eventDelay); + final int eventDelayInt = Integer.parseInt(eventDelay); if (eventDelayInt <= 0) { LOGGER.error("Invalid property, expected > 0, received <[{}]>", eventDelay); throw new RelpProbeConfigurationError( @@ -100,21 +101,22 @@ public void validate() throws RelpProbeConfigurationError { throw new RelpProbeConfigurationError("Missing property"); } - String targetPort = config.get("target.port"); + final String targetPort = config.get("target.port"); if (targetPort == null) { LOGGER.error("Missing property"); throw new RelpProbeConfigurationError("Missing property"); } try { - int targetPortInt = Integer.parseInt(targetPort); - if (targetPortInt <= 0 || targetPortInt > 65535) { + final int targetPortInt = Integer.parseInt(targetPort); + if (targetPortInt <= 0 || targetPortInt > MAXIMUM_PORT) { LOGGER .error( - "Invalid property, expected between 1 and 65535, received <[{}]>", - targetPort + "Invalid property, expected between 1 and {}, received <[{}]>", + MAXIMUM_PORT, targetPort ); throw new RelpProbeConfigurationError( - "Invalid property, expected between 1 and 65535, received <[" + targetPort + "]>" + "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" + + targetPort + "]>" ); } } @@ -130,13 +132,13 @@ public void validate() throws RelpProbeConfigurationError { throw new RelpProbeConfigurationError("Missing property"); } - String reconnectInterval = config.get("target.reconnectinterval"); + final String reconnectInterval = config.get("target.reconnectinterval"); if (reconnectInterval == null) { LOGGER.error("Missing property"); throw new RelpProbeConfigurationError("Missing property"); } try { - int reconnectIntervalInt = Integer.parseInt(reconnectInterval); + final int reconnectIntervalInt = Integer.parseInt(reconnectInterval); if (reconnectIntervalInt <= 0) { LOGGER .error( diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java index f0c966d..ffc8741 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java @@ -47,7 +47,7 @@ public class RelpProbeConfigurationError extends RuntimeException { - public RelpProbeConfigurationError(String s) { + public RelpProbeConfigurationError(final String s) { super(s); } } diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties index ed8f4b2..2e86a33 100644 --- a/src/test/resources/connectiontest.properties +++ b/src/test/resources/connectiontest.properties @@ -1,9 +1,12 @@ -# Hostname used in RELP event -event.hostname=rlp_11 # Appname used in RELP event event.appname=rlp_11 # Delay between sending events, in milliseconds event.delay=1000 +# Hostname used in RELP event +event.hostname=rlp_11 + +# Prometheus endpoint port +prometheus.endpoint=127.0.0.1:8080 # RELP Server target address target.hostname=127.0.0.1 @@ -11,6 +14,3 @@ target.hostname=127.0.0.1 target.port=12345 # RELP Server reconnect interval target.reconnectinterval=1000 - -# Prometheus endpoint port -prometheus.endpoint=127.0.0.1:8080 From 577e5072aebf7a6906ba52f91f5ad4ba8f66e180 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:47:50 +0200 Subject: [PATCH 06/14] Adds some sort of Metrics printing --- pom.xml | 10 +- .../java/com/teragrep/rlp_11/Metrics.java | 78 +++++++++++ .../java/com/teragrep/rlp_11/RelpProbe.java | 50 ++++++- .../rlp_11/RelpProbeConfiguration.java | 126 ++++++++---------- .../com/teragrep/rlp_11/ConnectionTest.java | 15 +-- .../rlp_11/InvalidConfigValidationTest.java | 47 ++++++- src/test/resources/connectiontest.properties | 2 +- 7 files changed, 238 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/teragrep/rlp_11/Metrics.java diff --git a/pom.xml b/pom.xml index 4eea39c..1cce21f 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ -SNAPSHOT 0.0.1-SNAPSHOT 4.2.28 + 11.0.24 1.1.7 2.1.3 17 @@ -81,6 +82,12 @@ simpleclient_hotspot ${prometheus.version} + + + org.eclipse.jetty + jetty-servlet + ${eclipse.jetty.version} + org.slf4j @@ -186,7 +193,8 @@ - + + diff --git a/src/main/java/com/teragrep/rlp_11/Metrics.java b/src/main/java/com/teragrep/rlp_11/Metrics.java new file mode 100644 index 0000000..c922522 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Metrics.java @@ -0,0 +1,78 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.SlidingWindowReservoir; +import com.codahale.metrics.Timer; + +import static com.codahale.metrics.MetricRegistry.name; + +public class Metrics { + + public final Counter records; + public final Counter resends; + public final Counter connects; + public final Counter disconnects; + public final Counter retriedConnects; + public final Timer sendLatency; + public final Timer connectLatency; + public final MetricRegistry metricRegistry; + + public Metrics(final String name) { + this.metricRegistry = new MetricRegistry(); + this.records = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "records")); + this.resends = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "resends")); + this.connects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "connects")); + this.disconnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "disconnects")); + this.retriedConnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "retriedConnects")); + this.sendLatency = metricRegistry + .timer(name(Metrics.class, "<[" + name + "]>", "sendLatency"), () -> new Timer(new SlidingWindowReservoir(10000))); + this.connectLatency = metricRegistry + .timer(name(Metrics.class, "<[" + name + "]>", "connectLatency"), () -> new Timer(new SlidingWindowReservoir(10000))); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index c1eaeca..dd70373 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -45,11 +45,15 @@ */ package com.teragrep.rlp_11; +import com.codahale.metrics.Slf4jReporter; +import com.codahale.metrics.Timer; +import com.codahale.metrics.jmx.JmxReporter; import com.teragrep.rlo_14.Facility; import com.teragrep.rlo_14.Severity; import com.teragrep.rlo_14.SyslogMessage; import com.teragrep.rlp_01.RelpBatch; import com.teragrep.rlp_01.RelpConnection; +import org.eclipse.jetty.server.Server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,12 +77,41 @@ public class RelpProbe { private RelpConnection relpConnection; private final CountDownLatch latch = new CountDownLatch(1); private boolean connected = false; + public final Metrics metrics; + private final JmxReporter jmxReporter; + private final Slf4jReporter slf4jReporter; + private final Server jettyServer; public RelpProbe(final RelpProbeConfiguration config) { + this(config, new Metrics(config.getTargetHostname() + ":" + config.getTargetPort())); + } + + public RelpProbe(final RelpProbeConfiguration config, final Metrics metrics) { + this( + config, + metrics, + JmxReporter.forRegistry(metrics.metricRegistry).build(), + Slf4jReporter.forRegistry(metrics.metricRegistry).outputTo(LoggerFactory.getLogger(RelpProbe.class)).convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS).build(), new Server(config.getPrometheusPort()) + ); + } + + public RelpProbe( + final RelpProbeConfiguration config, + final Metrics metrics, + JmxReporter jmxReporter, + Slf4jReporter slf4jReporter, + Server jettyServer + ) { this.config = config; + this.metrics = metrics; + this.jmxReporter = jmxReporter; + this.slf4jReporter = slf4jReporter; + this.jettyServer = jettyServer; } public void start() { + this.jmxReporter.start(); + this.slf4jReporter.start(1, TimeUnit.MINUTES); String origin; try { origin = InetAddress.getLocalHost().getHostName(); @@ -111,9 +144,10 @@ public void start() { boolean allSent = false; while (!allSent && stayRunning) { - try { + try (final Timer.Context context = metrics.sendLatency.time()) { LOGGER.debug("Committing Relpbatch"); relpConnection.commit(relpBatch); + metrics.records.inc(); } catch (IllegalStateException | IOException | java.util.concurrent.TimeoutException e) { LOGGER.warn("Failed to commit: <{}>", e.getMessage()); @@ -124,6 +158,7 @@ public void start() { allSent = relpBatch.verifyTransactionAll(); if (!allSent) { LOGGER.warn("Transactions failed, retrying"); + metrics.resends.inc(); relpBatch.retryAllFailed(); reconnect(); } @@ -138,14 +173,23 @@ public void start() { } disconnect(); latch.countDown(); + slf4jReporter.close(); + jmxReporter.close(); + try { + jettyServer.stop(); + } + catch (Exception e) { + throw new RuntimeException(e); + } } private void connect() { while (!connected && stayRunning) { - try { + try (final Timer.Context context = metrics.connectLatency.time()) { LOGGER.info("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); LOGGER.info("Connected."); + metrics.connects.inc(); } catch (TimeoutException | IOException e) { LOGGER @@ -158,6 +202,7 @@ private void connect() { try { LOGGER.info("Sleeping for <[{}]>ms before reconnecting", config.getReconnectInterval()); Thread.sleep(config.getReconnectInterval()); + metrics.retriedConnects.inc(); } catch (InterruptedException e) { LOGGER.warn("Sleep was interrupted: <{}>", e.getMessage()); @@ -179,6 +224,7 @@ private void disconnect() { try { LOGGER.info("Disconnecting.."); relpConnection.disconnect(); + metrics.disconnects.inc(); } catch (IOException | TimeoutException e) { LOGGER.warn("Failed to disconnect: <{}>", e.getMessage()); diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java index 5f066b1..122b11d 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java @@ -65,96 +65,76 @@ public void validate() throws RelpProbeConfigurationError { LOGGER.debug("Validating the following configuration: {}", config); } - if (config.get("event.hostname") == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); - } + getAndVerifyStringProperty("event.hostname"); + getAndVerifyStringProperty("event.appname"); - if (config.get("event.appname") == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); + int eventDelay = getAndVerifyNumberProperty("event.delay"); + if (eventDelay <= 0) { + LOGGER.error("Invalid property, expected > 0, received <[{}]>", eventDelay); + throw new RelpProbeConfigurationError( + "Invalid property, expected > 0, received <[" + eventDelay + "]>" + ); } - final String eventDelay = config.get("event.delay"); - if (eventDelay == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); - } - try { - final int eventDelayInt = Integer.parseInt(eventDelay); - if (eventDelayInt <= 0) { - LOGGER.error("Invalid property, expected > 0, received <[{}]>", eventDelay); - throw new RelpProbeConfigurationError( - "Invalid property, expected > 0, received <[" + eventDelay + "]>" - ); - } - } - catch (NumberFormatException e) { - LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + getAndVerifyStringProperty("target.hostname"); + + int targetPort = getAndVerifyNumberProperty("target.port"); + if (targetPort <= 0 || targetPort > MAXIMUM_PORT) { + LOGGER + .error( + "Invalid property, expected between 1 and {}, received <[{}]>", MAXIMUM_PORT, + targetPort + ); throw new RelpProbeConfigurationError( - "Invalid property received, not a number: <" + e.getMessage() + ">" + "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" + + targetPort + "]>" ); } - if (config.get("target.hostname") == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); + int prometheusPort = getAndVerifyNumberProperty("prometheus.port"); + if (prometheusPort <= 0 || prometheusPort > MAXIMUM_PORT) { + LOGGER + .error( + "Invalid property, expected between 1 and {}, received <[{}]>", + MAXIMUM_PORT, prometheusPort + ); + throw new RelpProbeConfigurationError( + "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" + + prometheusPort + "]>" + ); } - final String targetPort = config.get("target.port"); - if (targetPort == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); - } - try { - final int targetPortInt = Integer.parseInt(targetPort); - if (targetPortInt <= 0 || targetPortInt > MAXIMUM_PORT) { - LOGGER - .error( - "Invalid property, expected between 1 and {}, received <[{}]>", - MAXIMUM_PORT, targetPort - ); - throw new RelpProbeConfigurationError( - "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" - + targetPort + "]>" - ); - } - } - catch (NumberFormatException e) { - LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + int reconnectInterval = getAndVerifyNumberProperty("target.reconnectinterval"); + if (reconnectInterval <= 0) { + LOGGER + .error( + "Invalid property, property, expected > 0, received <[{}]>", + reconnectInterval + ); throw new RelpProbeConfigurationError( - "Invalid property received, not a number: <" + e.getMessage() + ">" + "Invalid property, expected > 0, received <[" + reconnectInterval + "]>" ); } + } - if (config.get("prometheus.endpoint") == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); + private String getAndVerifyStringProperty(String name) { + String property = config.get(name); + if (property == null) { + LOGGER.error("Missing <{}> property", name); + throw new RelpProbeConfigurationError("Missing <" + name + "> property"); } + return property; + } - final String reconnectInterval = config.get("target.reconnectinterval"); - if (reconnectInterval == null) { - LOGGER.error("Missing property"); - throw new RelpProbeConfigurationError("Missing property"); - } + private int getAndVerifyNumberProperty(String name) { + String property = getAndVerifyStringProperty(name); try { - final int reconnectIntervalInt = Integer.parseInt(reconnectInterval); - if (reconnectIntervalInt <= 0) { - LOGGER - .error( - "Invalid property, property, expected > 0, received <[{}]>", - reconnectIntervalInt - ); - throw new RelpProbeConfigurationError( - "Invalid property, expected > 0, received <[" + reconnectInterval - + "]>" - ); - } + return Integer.parseInt(property); } catch (NumberFormatException e) { - LOGGER.error("Invalid property received, not a number: <{}>", e.getMessage()); + LOGGER.error("Invalid <{}> property received, not a number: <{}>", name, e.getMessage()); throw new RelpProbeConfigurationError( - "Invalid property received, not a number: <" + e.getMessage() + ">" + "Invalid <" + name + "> property received, not a number: <" + e.getMessage() + ">" ); } } @@ -179,8 +159,8 @@ public int getTargetPort() { return Integer.parseInt(config.get("target.port")); } - public String getPrometheusEndpoint() { - return config.get("prometheus.endpoint"); + public int getPrometheusPort() { + return Integer.parseInt(config.get("prometheus.port")); } public int getReconnectInterval() { diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 80fa4cd..28bf92c 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -58,8 +58,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; @@ -77,7 +75,6 @@ public class ConnectionTest { private EventLoop eventLoop; private ThreadPoolExecutor threadPoolExecutor; private final List records = new ArrayList<>(); - private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionTest.class); private Server server; @BeforeEach @@ -88,9 +85,11 @@ public void startServer() { eventLoopThread = new Thread(eventLoop); eventLoopThread.start(); - Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate( - frameContext -> records.add(frameContext.relpFrame().payload().toString()) - ); + Supplier frameDelegateSupplier = () -> new DefaultFrameDelegate((frameContext) -> { + // Adds random latency before finishing and acking the event + Assertions.assertDoesNotThrow(() -> Thread.sleep((long) (Math.random() * 500))); + records.add(frameContext.relpFrame().payload().toString()); + }); threadPoolExecutor = new ThreadPoolExecutor( 1, @@ -134,10 +133,8 @@ public void run() { } }; Timer timer = new Timer("Timer"); - timer.schedule(task, 5000L); + timer.schedule(task, 10000L); relpProbe.start(); - - LOGGER.info("Got records: {}", records); } } diff --git a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java index 2d83a8f..0c54c10 100644 --- a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java +++ b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java @@ -117,7 +117,7 @@ public void testMissingTargetHostname() { // target.port tests @Test - public void testMissingPort() { + public void testMissingTargetPort() { Map map = getDefaultMap(); map.remove("target.port"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); @@ -202,10 +202,49 @@ public void testNonNumericReconnectInterval() { @Test public void testMissingPrometheusEndpoint() { Map map = getDefaultMap(); - map.remove("prometheus.endpoint"); + map.remove("prometheus.port"); RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); + Assertions.assertEquals("Missing property", e.getMessage()); + } + + @Test + public void testTooSmallPrometheusPort() { + Map map = getDefaultMap(); + map.put("prometheus.port", "0"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property, expected between 1 and 65535, received <[0]>", + e.getMessage() + ); + } + + @Test + public void testTooHighPrometheusPort() { + Map map = getDefaultMap(); + map.put("prometheus.port", "65536"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property, expected between 1 and 65535, received <[65536]>", + e.getMessage() + ); + } + + @Test + public void testNonNumericPrometheusPort() { + Map map = getDefaultMap(); + map.put("prometheus.port", "not a number"); + RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); + Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); + Assertions + .assertEquals( + "Invalid property received, not a number: ", + e.getMessage() + ); } private Map getDefaultMap() { @@ -216,7 +255,7 @@ private Map getDefaultMap() { map.put("target.hostname", "127.0.0.1"); map.put("target.port", "12345"); map.put("target.reconnectinterval", "1000"); - map.put("prometheus.endpoint", "127.0.0.1:8080"); + map.put("prometheus.port", "8080"); return map; } } diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties index 2e86a33..01384c9 100644 --- a/src/test/resources/connectiontest.properties +++ b/src/test/resources/connectiontest.properties @@ -6,7 +6,7 @@ event.delay=1000 event.hostname=rlp_11 # Prometheus endpoint port -prometheus.endpoint=127.0.0.1:8080 +prometheus.port=8080 # RELP Server target address target.hostname=127.0.0.1 From a7cfab26a0767bdfc6684712d19d9bb641ca2faa Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:58:57 +0200 Subject: [PATCH 07/14] Adds two extra error logging calls, a todo note --- src/main/java/com/teragrep/rlp_11/Metrics.java | 1 + src/main/java/com/teragrep/rlp_11/RelpProbe.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main/java/com/teragrep/rlp_11/Metrics.java b/src/main/java/com/teragrep/rlp_11/Metrics.java index c922522..8adaccd 100644 --- a/src/main/java/com/teragrep/rlp_11/Metrics.java +++ b/src/main/java/com/teragrep/rlp_11/Metrics.java @@ -70,6 +70,7 @@ public Metrics(final String name) { this.connects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "connects")); this.disconnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "disconnects")); this.retriedConnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "retriedConnects")); + // TODO: Configurable window? this.sendLatency = metricRegistry .timer(name(Metrics.class, "<[" + name + "]>", "sendLatency"), () -> new Timer(new SlidingWindowReservoir(10000))); this.connectLatency = metricRegistry diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index dd70373..6116d9e 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -239,10 +239,12 @@ public void stop() { stayRunning = false; try { if (!latch.await(5L, TimeUnit.SECONDS)) { + LOGGER.error("Timed out while waiting for probe to shutdown."); throw new RuntimeException("Timed out while waiting for probe to shutdown."); } } catch (InterruptedException e) { + LOGGER.error("Interrupted while waiting for latch countdown"); throw new RuntimeException(e); } LOGGER.info("RelpProbe stopped."); From 9b3ac390577bea310aaa647efaa9ab0c16d0a70d Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:05:45 +0200 Subject: [PATCH 08/14] Re-enable IllegalCatch but add SuppressionCommentFilter to allow disabling it momentarily --- pom.xml | 5 +++-- src/main/java/com/teragrep/rlp_11/RelpProbe.java | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1cce21f..624dea0 100644 --- a/pom.xml +++ b/pom.xml @@ -193,8 +193,7 @@ - - + @@ -231,6 +230,8 @@ + + diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 6116d9e..76e6da0 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -178,9 +178,11 @@ public void start() { try { jettyServer.stop(); } + //CHECKSTYLE:OFF catch (Exception e) { throw new RuntimeException(e); } + //CHECKSTYLE:ON } private void connect() { From f3d1afb228641b1c3cf08a768485e0f90b10942c Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:44:32 +0200 Subject: [PATCH 09/14] First batch of easy changes --- src/main/java/com/teragrep/rlp_11/Main.java | 14 +++++------ .../java/com/teragrep/rlp_11/RelpProbe.java | 24 ++++++++++--------- .../com/teragrep/rlp_11/ConnectionTest.java | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index a5a41de..06eb2e2 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -56,7 +56,7 @@ public class Main { private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); - public static void main(final String[] args) { + public static void main(final String[] args) throws ConfigurationException { final PathConfiguration pathConfiguration = new PathConfiguration( System.getProperty("configurationPath", "etc/rlp_11.properties") ); @@ -65,23 +65,23 @@ public static void main(final String[] args) { map = pathConfiguration.asMap(); } catch (ConfigurationException e) { - LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage(), e); - System.exit(1); + LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage()); + throw e; } final RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); try { relpProbeConfiguration.validate(); } catch (RelpProbeConfigurationError e) { - LOGGER.error("Failed to validate config: <{}>", e.getMessage(), e); - System.exit(1); + LOGGER.error("Failed to validate config: <{}>", e.getMessage()); + throw e; } final RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); final Thread shutdownHook = new Thread(() -> { - LOGGER.info("Stopping RelpProbe.."); + LOGGER.debug("Stopping RelpProbe.."); relpProbe.stop(); - LOGGER.info("Shutting down."); + LOGGER.debug("Shutting down."); }); Runtime.getRuntime().addShutdownHook(shutdownHook); LOGGER diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 76e6da0..017156c 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -66,6 +66,8 @@ import java.time.Instant; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; + import jakarta.json.Json; import jakarta.json.JsonObject; @@ -73,7 +75,7 @@ public class RelpProbe { private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); private final RelpProbeConfiguration config; - private boolean stayRunning = true; + private AtomicBoolean stayRunning = new AtomicBoolean(true); private RelpConnection relpConnection; private final CountDownLatch latch = new CountDownLatch(1); private boolean connected = false; @@ -123,7 +125,7 @@ public void start() { relpConnection = new RelpConnection(); connect(); final int eventDelay = config.getEventDelay(); - while (stayRunning) { + while (stayRunning.get()) { final RelpBatch relpBatch = new RelpBatch(); final Instant timestamp = Instant.now(); final JsonObject event = Json @@ -143,7 +145,7 @@ public void start() { relpBatch.insert(record); boolean allSent = false; - while (!allSent && stayRunning) { + while (!allSent && stayRunning.get()) { try (final Timer.Context context = metrics.sendLatency.time()) { LOGGER.debug("Committing Relpbatch"); relpConnection.commit(relpBatch); @@ -186,11 +188,11 @@ public void start() { } private void connect() { - while (!connected && stayRunning) { + while (!connected && stayRunning.get()) { try (final Timer.Context context = metrics.connectLatency.time()) { - LOGGER.info("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); + LOGGER.debug("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); - LOGGER.info("Connected."); + LOGGER.debug("Connected."); metrics.connects.inc(); } catch (TimeoutException | IOException e) { @@ -202,7 +204,7 @@ private void connect() { } if (!connected) { try { - LOGGER.info("Sleeping for <[{}]>ms before reconnecting", config.getReconnectInterval()); + LOGGER.debug("Sleeping for <[{}]>ms before reconnecting", config.getReconnectInterval()); Thread.sleep(config.getReconnectInterval()); metrics.retriedConnects.inc(); } @@ -224,7 +226,7 @@ private void disconnect() { return; } try { - LOGGER.info("Disconnecting.."); + LOGGER.debug("Disconnecting.."); relpConnection.disconnect(); metrics.disconnects.inc(); } @@ -232,13 +234,13 @@ private void disconnect() { LOGGER.warn("Failed to disconnect: <{}>", e.getMessage()); } relpConnection.tearDown(); - LOGGER.info("Disconnected."); + LOGGER.debug("Disconnected."); connected = false; } public void stop() { LOGGER.debug("Stop called"); - stayRunning = false; + stayRunning.set(false); try { if (!latch.await(5L, TimeUnit.SECONDS)) { LOGGER.error("Timed out while waiting for probe to shutdown."); @@ -249,6 +251,6 @@ public void stop() { LOGGER.error("Interrupted while waiting for latch countdown"); throw new RuntimeException(e); } - LOGGER.info("RelpProbe stopped."); + LOGGER.debug("RelpProbe stopped."); } } diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 28bf92c..db9974a 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -133,7 +133,7 @@ public void run() { } }; Timer timer = new Timer("Timer"); - timer.schedule(task, 10000L); + timer.schedule(task, 10_000); relpProbe.start(); } From 51162ead8cd28d9c5152d6d012a0675a056713b0 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:16:52 +0200 Subject: [PATCH 10/14] Refactor configuration management, split start to more components --- .../ConfigurationException.java} | 6 +- .../EventConfiguration.java} | 65 +++-- .../EventConfigurationBuilder.java | 62 +++++ .../Configuration/MetricsConfiguration.java | 79 ++++++ .../MetricsConfigurationBuilder.java | 61 ++++ .../PrometheusConfiguration.java | 69 +++++ .../PrometheusConfigurationBuilder.java | 60 ++++ .../Configuration/TargetConfiguration.java | 90 ++++++ .../TargetConfigurationBuilder.java | 62 +++++ src/main/java/com/teragrep/rlp_11/Main.java | 44 +-- .../java/com/teragrep/rlp_11/RelpProbe.java | 170 +++++++----- .../rlp_11/RelpProbeConfiguration.java | 169 ------------ .../com/teragrep/rlp_11/ConnectionTest.java | 29 +- .../rlp_11/InvalidConfigValidationTest.java | 261 ------------------ src/test/resources/connectiontest.properties | 5 + 15 files changed, 675 insertions(+), 557 deletions(-) rename src/main/java/com/teragrep/rlp_11/{RelpProbeConfigurationError.java => Configuration/ConfigurationException.java} (92%) rename src/main/java/com/teragrep/rlp_11/{Metrics.java => Configuration/EventConfiguration.java} (55%) create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java delete mode 100644 src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java delete mode 100644 src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java b/src/main/java/com/teragrep/rlp_11/Configuration/ConfigurationException.java similarity index 92% rename from src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java rename to src/main/java/com/teragrep/rlp_11/Configuration/ConfigurationException.java index ffc8741..69daa51 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfigurationError.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/ConfigurationException.java @@ -43,11 +43,11 @@ * Teragrep, the applicable Commercial License may apply to this file if you as * a licensee so wish it. */ -package com.teragrep.rlp_11; +package com.teragrep.rlp_11.Configuration; -public class RelpProbeConfigurationError extends RuntimeException { +public class ConfigurationException extends RuntimeException { - public RelpProbeConfigurationError(final String s) { + public ConfigurationException(final String s) { super(s); } } diff --git a/src/main/java/com/teragrep/rlp_11/Metrics.java b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java similarity index 55% rename from src/main/java/com/teragrep/rlp_11/Metrics.java rename to src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java index 8adaccd..c2cc30d 100644 --- a/src/main/java/com/teragrep/rlp_11/Metrics.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java @@ -43,37 +43,48 @@ * Teragrep, the applicable Commercial License may apply to this file if you as * a licensee so wish it. */ -package com.teragrep.rlp_11; +package com.teragrep.rlp_11.Configuration; -import com.codahale.metrics.Counter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.SlidingWindowReservoir; -import com.codahale.metrics.Timer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import static com.codahale.metrics.MetricRegistry.name; +public class EventConfiguration { -public class Metrics { + private static final Logger LOGGER = LoggerFactory.getLogger(EventConfiguration.class); + private final String appname; + private final String hostname; + private final int delay; - public final Counter records; - public final Counter resends; - public final Counter connects; - public final Counter disconnects; - public final Counter retriedConnects; - public final Timer sendLatency; - public final Timer connectLatency; - public final MetricRegistry metricRegistry; + public EventConfiguration(final String appname, final String hostname, final int delay) { + this.appname = appname; + this.hostname = hostname; + this.delay = delay; + } + + public String appname() { + if (appname == null) { + final String errorMessage = "Appname is null"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return appname; + } + + public String hostname() { + if (appname == null) { + final String errorMessage = "Hostname is null"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return hostname; + } - public Metrics(final String name) { - this.metricRegistry = new MetricRegistry(); - this.records = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "records")); - this.resends = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "resends")); - this.connects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "connects")); - this.disconnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "disconnects")); - this.retriedConnects = metricRegistry.counter(name(Metrics.class, "<[" + name + "]>", "retriedConnects")); - // TODO: Configurable window? - this.sendLatency = metricRegistry - .timer(name(Metrics.class, "<[" + name + "]>", "sendLatency"), () -> new Timer(new SlidingWindowReservoir(10000))); - this.connectLatency = metricRegistry - .timer(name(Metrics.class, "<[" + name + "]>", "connectLatency"), () -> new Timer(new SlidingWindowReservoir(10000))); + public int delay() { + if (delay <= 0) { + final String errorMessage = "Delay too small, expected to be >0"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return delay; } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java new file mode 100644 index 0000000..41086f6 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java @@ -0,0 +1,62 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import java.util.Map; + +public final class EventConfigurationBuilder { + + private EventConfigurationBuilder() { + + } + + public static EventConfiguration build(final Map config) { + final String appname = config.get("event.appname"); + final String hostname = config.get("event.hostname"); + final int delay = Integer.parseInt(config.get("event.delay")); + return new EventConfiguration(appname, hostname, delay); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java new file mode 100644 index 0000000..b8b808c --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java @@ -0,0 +1,79 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MetricsConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfiguration.class); + private final String name; + private final int window; + + public MetricsConfiguration(final String name, final int window) { + this.name = name; + this.window = window; + } + + public String name() { + if (name == null) { + final String errorMessage = "Name is null"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return name; + } + + public int window() { + if (window <= 0) { + final String errorMessage = "Window too small, expected to be >0"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return window; + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java new file mode 100644 index 0000000..2b55572 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java @@ -0,0 +1,61 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import java.util.Map; + +public final class MetricsConfigurationBuilder { + + private MetricsConfigurationBuilder() { + + } + + public static MetricsConfiguration build(final Map config) { + final String name = config.get("metrics.name"); + final int window = Integer.parseInt(config.get("metrics.window")); + return new MetricsConfiguration(name, window); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java new file mode 100644 index 0000000..19c1450 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java @@ -0,0 +1,69 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PrometheusConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfiguration.class); + + private final int port; + + public PrometheusConfiguration(final int port) { + this.port = port; + } + + public int port() { + if (port < 1 || port > 65535) { + final String errorMessage = "Port is in invalid range, expected between 1 and 65535"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return port; + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java new file mode 100644 index 0000000..ad047ef --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java @@ -0,0 +1,60 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import java.util.Map; + +public final class PrometheusConfigurationBuilder { + + private PrometheusConfigurationBuilder() { + + } + + public static PrometheusConfiguration build(final Map config) { + final int port = Integer.parseInt(config.get("prometheus.port")); + return new PrometheusConfiguration(port); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java new file mode 100644 index 0000000..c38e0d6 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java @@ -0,0 +1,90 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TargetConfiguration { + + private static final Logger LOGGER = LoggerFactory.getLogger(TargetConfiguration.class); + private final String hostname; + private final int port; + private final int reconnectInterval; + + public TargetConfiguration(final String hostname, final int port, final int reconnectInterval) { + this.hostname = hostname; + this.port = port; + this.reconnectInterval = reconnectInterval; + } + + public String hostname() { + if (hostname == null) { + final String errorMessage = "Hostname is null"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return hostname; + } + + public int port() { + if (port < 1 || port > 65535) { + final String errorMessage = "Port is in invalid range, expected between 1 and 65535"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return port; + } + + public int reconnectInterval() { + if (reconnectInterval <= 0) { + final String errorMessage = "Reconnect interval too small, expected to be >0"; + LOGGER.error(errorMessage); + throw new ConfigurationException(errorMessage); + } + return reconnectInterval; + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java new file mode 100644 index 0000000..f433926 --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java @@ -0,0 +1,62 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import java.util.Map; + +public final class TargetConfigurationBuilder { + + private TargetConfigurationBuilder() { + + } + + public static TargetConfiguration build(final Map config) { + final String hostname = config.get("target.hostname"); + final int port = Integer.parseInt(config.get("target.port")); + final int reconnectInterval = Integer.parseInt(config.get("target.reconnectinterval")); + return new TargetConfiguration(hostname, port, reconnectInterval); + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index 06eb2e2..7c63436 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -45,8 +45,15 @@ */ package com.teragrep.rlp_11; -import com.teragrep.cnf_01.ConfigurationException; import com.teragrep.cnf_01.PathConfiguration; +import com.teragrep.rlp_11.Configuration.EventConfiguration; +import com.teragrep.rlp_11.Configuration.EventConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.MetricsConfiguration; +import com.teragrep.rlp_11.Configuration.MetricsConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; +import com.teragrep.rlp_11.Configuration.PrometheusConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.TargetConfiguration; +import com.teragrep.rlp_11.Configuration.TargetConfigurationBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,43 +63,40 @@ public class Main { private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); - public static void main(final String[] args) throws ConfigurationException { + public static void main(final String[] args) throws com.teragrep.cnf_01.ConfigurationException { final PathConfiguration pathConfiguration = new PathConfiguration( System.getProperty("configurationPath", "etc/rlp_11.properties") ); - Map map = null; + final Map map; try { map = pathConfiguration.asMap(); } - catch (ConfigurationException e) { + catch (com.teragrep.cnf_01.ConfigurationException e) { LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage()); throw e; } - final RelpProbeConfiguration relpProbeConfiguration = new RelpProbeConfiguration(map); - try { - relpProbeConfiguration.validate(); - } - catch (RelpProbeConfigurationError e) { - LOGGER.error("Failed to validate config: <{}>", e.getMessage()); - throw e; - } + final PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + final EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + final TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + final MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); - final RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); + final RelpProbe relpProbe = new RelpProbe( + targetConfiguration, + eventConfiguration, + prometheusConfiguration, + metricsConfiguration + ); final Thread shutdownHook = new Thread(() -> { LOGGER.debug("Stopping RelpProbe.."); relpProbe.stop(); LOGGER.debug("Shutting down."); }); Runtime.getRuntime().addShutdownHook(shutdownHook); + LOGGER.info("Sending events to <[{}:{}]>", targetConfiguration.hostname(), targetConfiguration.port()); LOGGER .info( - "Sending events to <[{}:{}]>", relpProbeConfiguration.getTargetHostname(), - relpProbeConfiguration.getTargetPort() - ); - LOGGER - .info( - "Using hostname <[{}]> and appname <[{}]> for the events.", - relpProbeConfiguration.getEventHostname(), relpProbeConfiguration.getEventAppname() + "Using hostname <[{}]> and appname <[{}]> for the events.", eventConfiguration.hostname(), + eventConfiguration.appname() ); relpProbe.start(); } diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 017156c..3df53b3 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -45,7 +45,10 @@ */ package com.teragrep.rlp_11; +import com.codahale.metrics.Counter; +import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Slf4jReporter; +import com.codahale.metrics.SlidingWindowReservoir; import com.codahale.metrics.Timer; import com.codahale.metrics.jmx.JmxReporter; import com.teragrep.rlo_14.Facility; @@ -53,6 +56,10 @@ import com.teragrep.rlo_14.SyslogMessage; import com.teragrep.rlp_01.RelpBatch; import com.teragrep.rlp_01.RelpConnection; +import com.teragrep.rlp_11.Configuration.EventConfiguration; +import com.teragrep.rlp_11.Configuration.MetricsConfiguration; +import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; +import com.teragrep.rlp_11.Configuration.TargetConfiguration; import org.eclipse.jetty.server.Server; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,47 +78,44 @@ import jakarta.json.Json; import jakarta.json.JsonObject; +import static com.codahale.metrics.MetricRegistry.name; + public class RelpProbe { private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); - private final RelpProbeConfiguration config; - private AtomicBoolean stayRunning = new AtomicBoolean(true); + private final TargetConfiguration targetConfiguration; + private final EventConfiguration eventConfiguration; + private final PrometheusConfiguration prometheusConfiguration; + private final MetricsConfiguration metricsConfiguration; + private final AtomicBoolean stayRunning = new AtomicBoolean(true); private RelpConnection relpConnection; private final CountDownLatch latch = new CountDownLatch(1); private boolean connected = false; - public final Metrics metrics; - private final JmxReporter jmxReporter; - private final Slf4jReporter slf4jReporter; - private final Server jettyServer; - - public RelpProbe(final RelpProbeConfiguration config) { - this(config, new Metrics(config.getTargetHostname() + ":" + config.getTargetPort())); - } - - public RelpProbe(final RelpProbeConfiguration config, final Metrics metrics) { - this( - config, - metrics, - JmxReporter.forRegistry(metrics.metricRegistry).build(), - Slf4jReporter.forRegistry(metrics.metricRegistry).outputTo(LoggerFactory.getLogger(RelpProbe.class)).convertRatesTo(TimeUnit.SECONDS).convertDurationsTo(TimeUnit.MILLISECONDS).build(), new Server(config.getPrometheusPort()) - ); - } + private Counter records; + private Counter resends; + private Counter connects; + private Counter disconnects; + private Counter retriedConnects; + private Timer sendLatency; + private Timer connectLatency; + private JmxReporter jmxReporter; + private Slf4jReporter slf4jReporter; + private Server jettyServer; public RelpProbe( - final RelpProbeConfiguration config, - final Metrics metrics, - JmxReporter jmxReporter, - Slf4jReporter slf4jReporter, - Server jettyServer + final TargetConfiguration targetConfiguration, + final EventConfiguration eventConfiguration, + final PrometheusConfiguration prometheusConfiguration, + final MetricsConfiguration metricsConfiguration ) { - this.config = config; - this.metrics = metrics; - this.jmxReporter = jmxReporter; - this.slf4jReporter = slf4jReporter; - this.jettyServer = jettyServer; + this.targetConfiguration = targetConfiguration; + this.eventConfiguration = eventConfiguration; + this.prometheusConfiguration = prometheusConfiguration; + this.metricsConfiguration = metricsConfiguration; } public void start() { + createMetrics(metricsConfiguration.name()); this.jmxReporter.start(); this.slf4jReporter.start(1, TimeUnit.MINUTES); String origin; @@ -124,32 +128,16 @@ public void start() { } relpConnection = new RelpConnection(); connect(); - final int eventDelay = config.getEventDelay(); while (stayRunning.get()) { final RelpBatch relpBatch = new RelpBatch(); - final Instant timestamp = Instant.now(); - final JsonObject event = Json - .createObjectBuilder() - .add("origin", origin) - .add("timestamp", timestamp.getEpochSecond() + "." + timestamp.getNano()) - .build(); - final byte[] record = new SyslogMessage() - .withTimestamp(timestamp.toEpochMilli()) - .withAppName(config.getEventAppname()) - .withHostname(config.getEventHostname()) - .withFacility(Facility.USER) - .withSeverity(Severity.INFORMATIONAL) - .withMsg(event.toString()) - .toRfc5424SyslogMessage() - .getBytes(StandardCharsets.UTF_8); - relpBatch.insert(record); + relpBatch.insert(createPayload(origin)); boolean allSent = false; while (!allSent && stayRunning.get()) { - try (final Timer.Context context = metrics.sendLatency.time()) { + try (final Timer.Context context = sendLatency.time()) { LOGGER.debug("Committing Relpbatch"); relpConnection.commit(relpBatch); - metrics.records.inc(); + records.inc(); } catch (IllegalStateException | IOException | java.util.concurrent.TimeoutException e) { LOGGER.warn("Failed to commit: <{}>", e.getMessage()); @@ -160,14 +148,14 @@ public void start() { allSent = relpBatch.verifyTransactionAll(); if (!allSent) { LOGGER.warn("Transactions failed, retrying"); - metrics.resends.inc(); + resends.inc(); relpBatch.retryAllFailed(); reconnect(); } } try { LOGGER.debug("Sleeping before sending next event"); - Thread.sleep(eventDelay); + Thread.sleep(eventConfiguration.delay()); } catch (InterruptedException e) { LOGGER.warn("Sleep interrupted: <{}>", e.getMessage()); @@ -175,38 +163,29 @@ public void start() { } disconnect(); latch.countDown(); - slf4jReporter.close(); - jmxReporter.close(); - try { - jettyServer.stop(); - } - //CHECKSTYLE:OFF - catch (Exception e) { - throw new RuntimeException(e); - } - //CHECKSTYLE:ON + teardownMetrics(); } private void connect() { while (!connected && stayRunning.get()) { - try (final Timer.Context context = metrics.connectLatency.time()) { - LOGGER.debug("Connecting to <[{}:{}]>", config.getTargetHostname(), config.getTargetPort()); - connected = relpConnection.connect(config.getTargetHostname(), config.getTargetPort()); + try (final Timer.Context context = connectLatency.time()) { + LOGGER.debug("Connecting to <[{}:{}]>", targetConfiguration.hostname(), targetConfiguration.port()); + connected = relpConnection.connect(targetConfiguration.hostname(), targetConfiguration.port()); LOGGER.debug("Connected."); - metrics.connects.inc(); + connects.inc(); } catch (TimeoutException | IOException e) { LOGGER .warn( - "Failed to connect to <[{}:{}]>: <{}>", config.getTargetHostname(), - config.getTargetPort(), e.getMessage() + "Failed to connect to <[{}:{}]>: <{}>", targetConfiguration.hostname(), + targetConfiguration.port(), e.getMessage() ); } if (!connected) { try { - LOGGER.debug("Sleeping for <[{}]>ms before reconnecting", config.getReconnectInterval()); - Thread.sleep(config.getReconnectInterval()); - metrics.retriedConnects.inc(); + LOGGER.debug("Sleeping for <[{}]>ms before reconnecting", targetConfiguration.reconnectInterval()); + Thread.sleep(targetConfiguration.reconnectInterval()); + retriedConnects.inc(); } catch (InterruptedException e) { LOGGER.warn("Sleep was interrupted: <{}>", e.getMessage()); @@ -228,7 +207,7 @@ private void disconnect() { try { LOGGER.debug("Disconnecting.."); relpConnection.disconnect(); - metrics.disconnects.inc(); + disconnects.inc(); } catch (IOException | TimeoutException e) { LOGGER.warn("Failed to disconnect: <{}>", e.getMessage()); @@ -253,4 +232,55 @@ public void stop() { } LOGGER.debug("RelpProbe stopped."); } + + private byte[] createPayload(final String origin) { + final Instant timestamp = Instant.now(); + final JsonObject event = Json + .createObjectBuilder() + .add("origin", origin) + .add("timestamp", timestamp.getEpochSecond() + "." + timestamp.getNano()) + .build(); + return new SyslogMessage() + .withTimestamp(timestamp.toEpochMilli()) + .withAppName(eventConfiguration.appname()) + .withHostname(eventConfiguration.hostname()) + .withFacility(Facility.USER) + .withSeverity(Severity.INFORMATIONAL) + .withMsg(event.toString()) + .toRfc5424SyslogMessage() + .getBytes(StandardCharsets.UTF_8); + } + + private void createMetrics(final String name) { + final MetricRegistry metricRegistry = new MetricRegistry(); + this.records = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "records")); + this.resends = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "resends")); + this.connects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "connects")); + this.disconnects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "disconnects")); + this.retriedConnects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "retriedConnects")); + // TODO: Configurable window? + this.sendLatency = metricRegistry + .timer(name(RelpProbe.class, "<[" + name + "]>", "sendLatency"), () -> new Timer(new SlidingWindowReservoir(metricsConfiguration.window()))); + this.connectLatency = metricRegistry + .timer(name(RelpProbe.class, "<[" + name + "]>", "connectLatency"), () -> new Timer(new SlidingWindowReservoir(metricsConfiguration.window()))); + jmxReporter = JmxReporter.forRegistry(metricRegistry).build(); + slf4jReporter = Slf4jReporter + .forRegistry(metricRegistry) + .outputTo(LoggerFactory.getLogger(RelpProbe.class)) + .build(); + jettyServer = new Server(prometheusConfiguration.port()); + } + + private void teardownMetrics() { + slf4jReporter.close(); + jmxReporter.close(); + try { + jettyServer.stop(); + } + //CHECKSTYLE:OFF + catch (Exception e) { + throw new RuntimeException(e); + } + //CHECKSTYLE:ON + } } diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java b/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java deleted file mode 100644 index 122b11d..0000000 --- a/src/main/java/com/teragrep/rlp_11/RelpProbeConfiguration.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * RELP Commit Latency Probe RLP-11 - * Copyright (C) 2024 Suomen Kanuuna Oy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * - * Additional permission under GNU Affero General Public License version 3 - * section 7 - * - * If you modify this Program, or any covered work, by linking or combining it - * with other code, such other code is not for that reason alone subject to any - * of the requirements of the GNU Affero GPL version 3 as long as this Program - * is the same Program as licensed from Suomen Kanuuna Oy without any additional - * modifications. - * - * Supplemented terms under GNU Affero General Public License version 3 - * section 7 - * - * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified - * versions must be marked as "Modified version of" The Program. - * - * Names of the licensors and authors may not be used for publicity purposes. - * - * No rights are granted for use of trade names, trademarks, or service marks - * which are in The Program if any. - * - * Licensee must indemnify licensors and authors for any liability that these - * contractual assumptions impose on licensors and authors. - * - * To the extent this program is licensed as part of the Commercial versions of - * Teragrep, the applicable Commercial License may apply to this file if you as - * a licensee so wish it. - */ -package com.teragrep.rlp_11; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -public class RelpProbeConfiguration { - - private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbeConfiguration.class); - private static final int MAXIMUM_PORT = 65535; - private final Map config; - - public RelpProbeConfiguration(final Map config) { - this.config = config; - } - - public void validate() throws RelpProbeConfigurationError { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Validating the following configuration: {}", config); - } - - getAndVerifyStringProperty("event.hostname"); - getAndVerifyStringProperty("event.appname"); - - int eventDelay = getAndVerifyNumberProperty("event.delay"); - if (eventDelay <= 0) { - LOGGER.error("Invalid property, expected > 0, received <[{}]>", eventDelay); - throw new RelpProbeConfigurationError( - "Invalid property, expected > 0, received <[" + eventDelay + "]>" - ); - } - - getAndVerifyStringProperty("target.hostname"); - - int targetPort = getAndVerifyNumberProperty("target.port"); - if (targetPort <= 0 || targetPort > MAXIMUM_PORT) { - LOGGER - .error( - "Invalid property, expected between 1 and {}, received <[{}]>", MAXIMUM_PORT, - targetPort - ); - throw new RelpProbeConfigurationError( - "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" - + targetPort + "]>" - ); - } - - int prometheusPort = getAndVerifyNumberProperty("prometheus.port"); - if (prometheusPort <= 0 || prometheusPort > MAXIMUM_PORT) { - LOGGER - .error( - "Invalid property, expected between 1 and {}, received <[{}]>", - MAXIMUM_PORT, prometheusPort - ); - throw new RelpProbeConfigurationError( - "Invalid property, expected between 1 and " + MAXIMUM_PORT + ", received <[" - + prometheusPort + "]>" - ); - } - - int reconnectInterval = getAndVerifyNumberProperty("target.reconnectinterval"); - if (reconnectInterval <= 0) { - LOGGER - .error( - "Invalid property, property, expected > 0, received <[{}]>", - reconnectInterval - ); - throw new RelpProbeConfigurationError( - "Invalid property, expected > 0, received <[" + reconnectInterval + "]>" - ); - } - } - - private String getAndVerifyStringProperty(String name) { - String property = config.get(name); - if (property == null) { - LOGGER.error("Missing <{}> property", name); - throw new RelpProbeConfigurationError("Missing <" + name + "> property"); - } - return property; - } - - private int getAndVerifyNumberProperty(String name) { - String property = getAndVerifyStringProperty(name); - try { - return Integer.parseInt(property); - } - catch (NumberFormatException e) { - LOGGER.error("Invalid <{}> property received, not a number: <{}>", name, e.getMessage()); - throw new RelpProbeConfigurationError( - "Invalid <" + name + "> property received, not a number: <" + e.getMessage() + ">" - ); - } - } - - public String getEventHostname() { - return config.get("event.hostname"); - } - - public String getEventAppname() { - return config.get("event.appname"); - } - - public int getEventDelay() { - return Integer.parseInt(config.get("event.delay")); - } - - public String getTargetHostname() { - return config.get("target.hostname"); - } - - public int getTargetPort() { - return Integer.parseInt(config.get("target.port")); - } - - public int getPrometheusPort() { - return Integer.parseInt(config.get("prometheus.port")); - } - - public int getReconnectInterval() { - return Integer.parseInt(config.get("target.reconnectinterval")); - } -} diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index db9974a..b8e4c23 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -54,6 +54,14 @@ import com.teragrep.rlp_03.frame.FrameDelegationClockFactory; import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate; import com.teragrep.rlp_03.frame.delegate.FrameDelegate; +import com.teragrep.rlp_11.Configuration.EventConfiguration; +import com.teragrep.rlp_11.Configuration.EventConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.MetricsConfiguration; +import com.teragrep.rlp_11.Configuration.MetricsConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; +import com.teragrep.rlp_11.Configuration.PrometheusConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.TargetConfiguration; +import com.teragrep.rlp_11.Configuration.TargetConfigurationBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -61,6 +69,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.LinkedBlockingQueue; @@ -118,13 +127,19 @@ public void stopServer() { @Test public void connectToServerTest() { - RelpProbeConfiguration relpProbeConfiguration = Assertions - .assertDoesNotThrow( - () -> new RelpProbeConfiguration( - new PathConfiguration("src/test/resources/connectiontest.properties").asMap() - ) - ); - RelpProbe relpProbe = new RelpProbe(relpProbeConfiguration); + Map map = Assertions + .assertDoesNotThrow(() -> new PathConfiguration("src/test/resources/connectiontest.properties").asMap()); + final PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + final EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + final TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + final MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + + RelpProbe relpProbe = new RelpProbe( + targetConfiguration, + eventConfiguration, + prometheusConfiguration, + metricsConfiguration + ); TimerTask task = new TimerTask() { diff --git a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java b/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java deleted file mode 100644 index 0c54c10..0000000 --- a/src/test/java/com/teragrep/rlp_11/InvalidConfigValidationTest.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * RELP Commit Latency Probe RLP-11 - * Copyright (C) 2024 Suomen Kanuuna Oy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * - * Additional permission under GNU Affero General Public License version 3 - * section 7 - * - * If you modify this Program, or any covered work, by linking or combining it - * with other code, such other code is not for that reason alone subject to any - * of the requirements of the GNU Affero GPL version 3 as long as this Program - * is the same Program as licensed from Suomen Kanuuna Oy without any additional - * modifications. - * - * Supplemented terms under GNU Affero General Public License version 3 - * section 7 - * - * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified - * versions must be marked as "Modified version of" The Program. - * - * Names of the licensors and authors may not be used for publicity purposes. - * - * No rights are granted for use of trade names, trademarks, or service marks - * which are in The Program if any. - * - * Licensee must indemnify licensors and authors for any liability that these - * contractual assumptions impose on licensors and authors. - * - * To the extent this program is licensed as part of the Commercial versions of - * Teragrep, the applicable Commercial License may apply to this file if you as - * a licensee so wish it. - */ -package com.teragrep.rlp_11; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.Map; - -public class InvalidConfigValidationTest { - - // event.hostname tests - @Test - public void testMissingEventHostname() { - Map map = getDefaultMap(); - map.remove("event.hostname"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - // event.appname tests - @Test - public void testMissingAppname() { - Map map = getDefaultMap(); - map.remove("event.appname"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - // event.delay tests - @Test - public void testMissingEventDelay() { - Map map = getDefaultMap(); - map.remove("event.delay"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - @Test - public void testZeroEventDelay() { - Map map = getDefaultMap(); - map.put("event.delay", "0"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Invalid property, expected > 0, received <[0]>", e.getMessage()); - } - - @Test - public void testNonNumericEventDelay() { - Map map = getDefaultMap(); - map.put("event.delay", "not a number"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property received, not a number: ", - e.getMessage() - ); - } - - // target.hostname tests - @Test - public void testMissingTargetHostname() { - Map map = getDefaultMap(); - map.remove("target.hostname"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - // target.port tests - @Test - public void testMissingTargetPort() { - Map map = getDefaultMap(); - map.remove("target.port"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - @Test - public void testTooSmallTargetPort() { - Map map = getDefaultMap(); - map.put("target.port", "0"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property, expected between 1 and 65535, received <[0]>", e.getMessage() - ); - } - - @Test - public void testTooHighTargetPort() { - Map map = getDefaultMap(); - map.put("target.port", "65536"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property, expected between 1 and 65535, received <[65536]>", - e.getMessage() - ); - } - - @Test - public void testNonNumericTargetPort() { - Map map = getDefaultMap(); - map.put("target.port", "not a number"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property received, not a number: ", - e.getMessage() - ); - } - - // relp.reconnectinterval tests - @Test - public void testMissingReconnectInterval() { - Map map = getDefaultMap(); - map.remove("target.reconnectinterval"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - @Test - public void testZeroReconnectInterval() { - Map map = getDefaultMap(); - map.put("target.reconnectinterval", "0"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property, expected > 0, received <[0]>", e.getMessage() - ); - } - - @Test - public void testNonNumericReconnectInterval() { - Map map = getDefaultMap(); - map.put("target.reconnectinterval", "not a number"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property received, not a number: ", - e.getMessage() - ); - } - - // prometheus.endport tests - @Test - public void testMissingPrometheusEndpoint() { - Map map = getDefaultMap(); - map.remove("prometheus.port"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions.assertEquals("Missing property", e.getMessage()); - } - - @Test - public void testTooSmallPrometheusPort() { - Map map = getDefaultMap(); - map.put("prometheus.port", "0"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property, expected between 1 and 65535, received <[0]>", - e.getMessage() - ); - } - - @Test - public void testTooHighPrometheusPort() { - Map map = getDefaultMap(); - map.put("prometheus.port", "65536"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property, expected between 1 and 65535, received <[65536]>", - e.getMessage() - ); - } - - @Test - public void testNonNumericPrometheusPort() { - Map map = getDefaultMap(); - map.put("prometheus.port", "not a number"); - RelpProbeConfiguration configuration = new RelpProbeConfiguration(map); - Exception e = Assertions.assertThrowsExactly(RelpProbeConfigurationError.class, configuration::validate); - Assertions - .assertEquals( - "Invalid property received, not a number: ", - e.getMessage() - ); - } - - private Map getDefaultMap() { - Map map = new HashMap<>(); - map.put("event.hostname", "rlp_11"); - map.put("event.appname", "rlp_11"); - map.put("event.delay", "1000"); - map.put("target.hostname", "127.0.0.1"); - map.put("target.port", "12345"); - map.put("target.reconnectinterval", "1000"); - map.put("prometheus.port", "8080"); - return map; - } -} diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties index 01384c9..9719305 100644 --- a/src/test/resources/connectiontest.properties +++ b/src/test/resources/connectiontest.properties @@ -5,6 +5,11 @@ event.delay=1000 # Hostname used in RELP event event.hostname=rlp_11 +# Metrics reporting name. Arbitrary string, only used for reporting purposes +metrics.name=target +# Metrics window size +metrics.window=10000 + # Prometheus endpoint port prometheus.port=8080 From 6af67623d6a56925fd627a48a8f6675b3904dc16 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:24:29 +0200 Subject: [PATCH 11/14] Adds some tests for configurations --- .../Configuration/EventConfiguration.java | 31 ++-- .../EventConfigurationBuilder.java | 6 +- .../IntConfigurationBuilder.java | 68 ++++++++ .../Configuration/MetricsConfiguration.java | 10 +- .../MetricsConfigurationBuilder.java | 2 +- .../PrometheusConfiguration.java | 9 +- .../PrometheusConfigurationBuilder.java | 2 +- .../Configuration/TargetConfiguration.java | 23 +-- .../TargetConfigurationBuilder.java | 10 +- .../Configuration/EventConfigurationTest.java | 125 +++++++++++++++ .../MetricsConfigurationTest.java | 108 +++++++++++++ .../PrometheusConfigurationTest.java | 99 ++++++++++++ .../TargetConfigurationTest.java | 147 ++++++++++++++++++ .../com/teragrep/rlp_11/ConnectionTest.java | 2 +- src/test/resources/missing.properties | 0 15 files changed, 599 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java create mode 100644 src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java create mode 100644 src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java create mode 100644 src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java create mode 100644 src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java create mode 100644 src/test/resources/missing.properties diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java index c2cc30d..312858c 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java @@ -51,39 +51,36 @@ public class EventConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(EventConfiguration.class); - private final String appname; private final String hostname; + private final String appname; private final int delay; - public EventConfiguration(final String appname, final String hostname, final int delay) { - this.appname = appname; + public EventConfiguration(final String hostname, final String appname, final int delay) { this.hostname = hostname; + this.appname = appname; this.delay = delay; } - public String appname() { - if (appname == null) { - final String errorMessage = "Appname is null"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + public String hostname() { + if (hostname == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } - return appname; + return hostname; } - public String hostname() { + public String appname() { if (appname == null) { - final String errorMessage = "Hostname is null"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } - return hostname; + return appname; } public int delay() { if (delay <= 0) { - final String errorMessage = "Delay too small, expected to be >0"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER.error("Configuration failure: <[{}]> too small, expected to be >0", delay); + throw new ConfigurationException("Invalid value for received"); } return delay; } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java index 41086f6..6e850a5 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java @@ -54,9 +54,9 @@ private EventConfigurationBuilder() { } public static EventConfiguration build(final Map config) { - final String appname = config.get("event.appname"); final String hostname = config.get("event.hostname"); - final int delay = Integer.parseInt(config.get("event.delay")); - return new EventConfiguration(appname, hostname, delay); + final String appname = config.get("event.appname"); + final int delay = IntConfigurationBuilder.get("event.delay", config.get("event.delay")); + return new EventConfiguration(hostname, appname, delay); } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java new file mode 100644 index 0000000..2030cfc --- /dev/null +++ b/src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java @@ -0,0 +1,68 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class IntConfigurationBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(IntConfigurationBuilder.class); + + private IntConfigurationBuilder() { + + } + + public static int get(final String name, final String value) { + try { + return Integer.parseInt(value); + } + catch (NumberFormatException e) { + LOGGER.error("Configuration failure: Invalid value for <{}> received: <{}>", name, e.getMessage()); + throw new ConfigurationException("Invalid value for <" + name + "> received: <" + e.getMessage() + ">"); + } + } +} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java index b8b808c..94b90b9 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java @@ -61,18 +61,16 @@ public MetricsConfiguration(final String name, final int window) { public String name() { if (name == null) { - final String errorMessage = "Name is null"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } return name; } public int window() { if (window <= 0) { - final String errorMessage = "Window too small, expected to be >0"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER.error("Configuration failure: <[{}]> too small, expected to be >0", window); + throw new ConfigurationException("Invalid value for received"); } return window; } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java index 2b55572..b00690d 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java @@ -55,7 +55,7 @@ private MetricsConfigurationBuilder() { public static MetricsConfiguration build(final Map config) { final String name = config.get("metrics.name"); - final int window = Integer.parseInt(config.get("metrics.window")); + final int window = IntConfigurationBuilder.get("metrics.window", config.get("metrics.window")); return new MetricsConfiguration(name, window); } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java index 19c1450..da8aaae 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java @@ -60,9 +60,12 @@ public PrometheusConfiguration(final int port) { public int port() { if (port < 1 || port > 65535) { - final String errorMessage = "Port is in invalid range, expected between 1 and 65535"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER + .error( + "Configuration failure: <[{}]> is in invalid range, expected between 1 and 65535", + port + ); + throw new ConfigurationException("Invalid value for received"); } return port; } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java index ad047ef..2897ec5 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java @@ -54,7 +54,7 @@ private PrometheusConfigurationBuilder() { } public static PrometheusConfiguration build(final Map config) { - final int port = Integer.parseInt(config.get("prometheus.port")); + final int port = IntConfigurationBuilder.get("prometheus.port", config.get("prometheus.port")); return new PrometheusConfiguration(port); } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java index c38e0d6..d619d38 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java @@ -63,27 +63,32 @@ public TargetConfiguration(final String hostname, final int port, final int reco public String hostname() { if (hostname == null) { - final String errorMessage = "Hostname is null"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } return hostname; } public int port() { if (port < 1 || port > 65535) { - final String errorMessage = "Port is in invalid range, expected between 1 and 65535"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER + .error( + "Configuration failure: <[{}]> is in invalid range, expected between 1 and 65535", + port + ); + throw new ConfigurationException("Invalid value for received"); } return port; } public int reconnectInterval() { if (reconnectInterval <= 0) { - final String errorMessage = "Reconnect interval too small, expected to be >0"; - LOGGER.error(errorMessage); - throw new ConfigurationException(errorMessage); + LOGGER + .error( + "Configuration failure: <[{}]> too small, expected to be >0", + reconnectInterval + ); + throw new ConfigurationException("Invalid value for received"); } return reconnectInterval; } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java index f433926..da0f961 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java @@ -45,18 +45,24 @@ */ package com.teragrep.rlp_11.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Map; public final class TargetConfigurationBuilder { + private static final Logger LOGGER = LoggerFactory.getLogger(TargetConfigurationBuilder.class); + private TargetConfigurationBuilder() { } public static TargetConfiguration build(final Map config) { final String hostname = config.get("target.hostname"); - final int port = Integer.parseInt(config.get("target.port")); - final int reconnectInterval = Integer.parseInt(config.get("target.reconnectinterval")); + final int port = IntConfigurationBuilder.get("target.port", config.get("target.port")); + final int reconnectInterval = IntConfigurationBuilder + .get("target.reconnectinterval", config.get("target.reconnectinterval")); return new TargetConfiguration(hostname, port, reconnectInterval); } } diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java new file mode 100644 index 0000000..d9852f4 --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java @@ -0,0 +1,125 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class EventConfigurationTest { + + // event.hostname + @Test + public void testNonNullHostname() { + Map map = baseConfig(); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertEquals("my-hostname", eventConfiguration.hostname()); + } + + @Test + public void testNullHostname() { + Map map = baseConfig(); + map.remove("event.hostname"); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::hostname); + } + + // event.appname + @Test + public void testNonNullAppname() { + Map map = baseConfig(); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertEquals("my-appname", eventConfiguration.appname()); + } + + @Test + public void testNullAppname() { + Map map = baseConfig(); + map.remove("event.appname"); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::appname); + } + + // event.delay + @Test + public void testGoodDelay() { + Map map = baseConfig(); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertEquals(15000, eventConfiguration.delay()); + } + + @Test + public void testNullDelay() { + Map map = baseConfig(); + map.remove("event.delay"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> EventConfigurationBuilder.build(map)); + } + + @Test + public void testTooSmallDelay() { + Map map = baseConfig(); + map.put("event.delay", "0"); + EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::delay); + } + + @Test + public void testNonNumericDelay() { + Map map = baseConfig(); + map.put("event.delay", "not a number"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> EventConfigurationBuilder.build(map)); + } + + private Map baseConfig() { + Map map = new HashMap<>(); + map.put("event.hostname", "my-hostname"); + map.put("event.appname", "my-appname"); + map.put("event.delay", "15000"); + return map; + } +} diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java new file mode 100644 index 0000000..9ae9dcf --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java @@ -0,0 +1,108 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class MetricsConfigurationTest { + + // metrics.name + @Test + public void testNonNullName() { + Map map = baseConfig(); + MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + Assertions.assertEquals("target-name", metricsConfiguration.name()); + } + + @Test + public void testNullName() { + Map map = baseConfig(); + map.remove("metrics.name"); + MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, metricsConfiguration::name); + } + + // metrics.window + @Test + public void testGoodWindow() { + Map map = baseConfig(); + MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + Assertions.assertEquals(1337, metricsConfiguration.window()); + } + + @Test + public void testNullWindow() { + Map map = baseConfig(); + map.remove("metrics.window"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> MetricsConfigurationBuilder.build(map)); + } + + @Test + public void testTooSmallWindow() { + Map map = baseConfig(); + map.put("metrics.window", "0"); + MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, metricsConfiguration::window); + } + + @Test + public void testNonNumericWindow() { + Map map = baseConfig(); + map.put("metrics.window", "Not a number here"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> MetricsConfigurationBuilder.build(map)); + } + + private Map baseConfig() { + Map map = new HashMap<>(); + map.put("metrics.name", "target-name"); + map.put("metrics.window", "1337"); + return map; + } +} diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java new file mode 100644 index 0000000..9e498c3 --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java @@ -0,0 +1,99 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class PrometheusConfigurationTest { + + // prometheus.port + @Test + public void testGoodPort() { + Map map = baseConfig(); + PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + Assertions.assertEquals(8080, prometheusConfiguration.port()); + } + + @Test + public void testNullPort() { + Map map = baseConfig(); + map.remove("prometheus.port"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> PrometheusConfigurationBuilder.build(map)); + } + + @Test + public void testTooSmallPort() { + Map map = baseConfig(); + map.put("prometheus.port", "0"); + PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, prometheusConfiguration::port); + } + + @Test + public void testTooHighPort() { + Map map = baseConfig(); + map.put("prometheus.port", "65536"); + PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, prometheusConfiguration::port); + } + + @Test + public void testNonNumericport() { + Map map = baseConfig(); + map.put("prometheus.port", "not a number"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> PrometheusConfigurationBuilder.build(map)); + } + + private Map baseConfig() { + Map map = new HashMap<>(); + map.put("prometheus.port", "8080"); + return map; + } +} diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java new file mode 100644 index 0000000..980254f --- /dev/null +++ b/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java @@ -0,0 +1,147 @@ +/* + * RELP Commit Latency Probe RLP-11 + * Copyright (C) 2024 Suomen Kanuuna Oy + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * + * Additional permission under GNU Affero General Public License version 3 + * section 7 + * + * If you modify this Program, or any covered work, by linking or combining it + * with other code, such other code is not for that reason alone subject to any + * of the requirements of the GNU Affero GPL version 3 as long as this Program + * is the same Program as licensed from Suomen Kanuuna Oy without any additional + * modifications. + * + * Supplemented terms under GNU Affero General Public License version 3 + * section 7 + * + * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified + * versions must be marked as "Modified version of" The Program. + * + * Names of the licensors and authors may not be used for publicity purposes. + * + * No rights are granted for use of trade names, trademarks, or service marks + * which are in The Program if any. + * + * Licensee must indemnify licensors and authors for any liability that these + * contractual assumptions impose on licensors and authors. + * + * To the extent this program is licensed as part of the Commercial versions of + * Teragrep, the applicable Commercial License may apply to this file if you as + * a licensee so wish it. + */ +package com.teragrep.rlp_11.Configuration; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class TargetConfigurationTest { + + // target.hostname + @Test + public void testNonNullHostname() { + Map map = baseConfig(); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertEquals("target-hostname", targetConfiguration.hostname()); + } + + @Test + public void testNullHostname() { + Map map = baseConfig(); + map.remove("target.hostname"); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::hostname); + } + + // target.port + @Test + public void testGoodPort() { + Map map = baseConfig(); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertEquals(601, targetConfiguration.port()); + } + + @Test + public void testNullPort() { + Map map = baseConfig(); + map.remove("target.port"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + } + + @Test + public void testTooSmallPort() { + Map map = baseConfig(); + map.put("target.port", "0"); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::port); + } + + @Test + public void testTooHighPort() { + Map map = baseConfig(); + map.put("target.port", "65536"); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::port); + } + + @Test + public void testNonNumericPort() { + Map map = baseConfig(); + map.put("target.port", "not a number"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + } + + // target.reconnectinterval + @Test + public void testGoodReconnectInterval() { + Map map = baseConfig(); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertEquals(15000, targetConfiguration.reconnectInterval()); + } + + @Test + public void testNullReconnectInterval() { + Map map = baseConfig(); + map.remove("target.reconnectinterval"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + } + + @Test + public void testTooSmallReconnectInterval() { + Map map = baseConfig(); + map.put("target.reconnectinterval", "0"); + TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::reconnectInterval); + } + + @Test + public void testNonNumericReconnectInterval() { + Map map = baseConfig(); + map.put("target.reconnectinterval", "not a number"); + Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + } + + private Map baseConfig() { + Map map = new HashMap<>(); + map.put("target.hostname", "target-hostname"); + map.put("target.port", "601"); + map.put("target.reconnectinterval", "15000"); + return map; + } +} diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index b8e4c23..4caf448 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -148,7 +148,7 @@ public void run() { } }; Timer timer = new Timer("Timer"); - timer.schedule(task, 10_000); + timer.schedule(task, 5_000L); relpProbe.start(); } diff --git a/src/test/resources/missing.properties b/src/test/resources/missing.properties new file mode 100644 index 0000000..e69de29 From f755a71389e108e12a622134ae7c0f7c817ddbf8 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 15:27:35 +0200 Subject: [PATCH 12/14] Remove unusued variables, fix logger name --- .../rlp_11/Configuration/PrometheusConfiguration.java | 2 +- .../rlp_11/Configuration/TargetConfigurationBuilder.java | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java index da8aaae..34772f4 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java @@ -50,7 +50,7 @@ public class PrometheusConfiguration { - private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfiguration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PrometheusConfiguration.class); private final int port; diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java index da0f961..f60e9f6 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java @@ -45,15 +45,10 @@ */ package com.teragrep.rlp_11.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Map; public final class TargetConfigurationBuilder { - private static final Logger LOGGER = LoggerFactory.getLogger(TargetConfigurationBuilder.class); - private TargetConfigurationBuilder() { } From 0c094e2408a73afcc9ed3f5781225ce33d0e61ae Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:49:30 +0200 Subject: [PATCH 13/14] Refactor configurations --- .../Configuration/MetricsConfiguration.java | 24 ++++++-- .../MetricsConfigurationBuilder.java | 61 ------------------- ...onBuilder.java => ProbeConfiguration.java} | 28 ++++++--- .../PrometheusConfiguration.java | 22 +++++-- .../PrometheusConfigurationBuilder.java | 60 ------------------ ...guration.java => RecordConfiguration.java} | 34 ++++------- .../Configuration/TargetConfiguration.java | 39 +++++++++--- src/main/java/com/teragrep/rlp_11/Main.java | 45 +++++++++----- ...urationBuilder.java => RecordFactory.java} | 43 ++++++++++--- .../java/com/teragrep/rlp_11/RelpProbe.java | 56 ++++------------- .../MetricsConfigurationTest.java | 14 +++-- .../ProbeConfigurationTest.java} | 46 +++++++++++--- .../PrometheusConfigurationTest.java | 14 +++-- ...Test.java => RecordConfigurationTest.java} | 49 +++------------ .../TargetConfigurationTest.java | 26 ++++---- .../com/teragrep/rlp_11/ConnectionTest.java | 20 +++--- src/test/resources/connectiontest.properties | 15 ++--- src/test/resources/missing.properties | 1 + 18 files changed, 275 insertions(+), 322 deletions(-) delete mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java rename src/main/java/com/teragrep/rlp_11/Configuration/{IntConfigurationBuilder.java => ProbeConfiguration.java} (72%) delete mode 100644 src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java rename src/main/java/com/teragrep/rlp_11/Configuration/{EventConfiguration.java => RecordConfiguration.java} (74%) rename src/main/java/com/teragrep/rlp_11/{Configuration/EventConfigurationBuilder.java => RecordFactory.java} (59%) rename src/{main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java => test/java/com/teragrep/rlp_11/Configuration/ProbeConfigurationTest.java} (56%) rename src/test/java/com/teragrep/rlp_11/Configuration/{EventConfigurationTest.java => RecordConfigurationTest.java} (64%) diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java index 94b90b9..c096a1b 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfiguration.java @@ -48,18 +48,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; + public class MetricsConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(MetricsConfiguration.class); - private final String name; - private final int window; + private final Map config; - public MetricsConfiguration(final String name, final int window) { - this.name = name; - this.window = window; + public MetricsConfiguration(final Map config) { + this.config = config; } public String name() { + final String name = config.get("metrics.name"); if (name == null) { LOGGER.error("Configuration failure: is null"); throw new ConfigurationException("Invalid value for received"); @@ -68,6 +69,19 @@ public String name() { } public int window() { + final String windowString = config.get("metrics.window"); + if (windowString == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); + } + final int window; + try { + window = Integer.parseInt(windowString); + } + catch (NumberFormatException e) { + LOGGER.error("Configuration failure: Invalid value for : <{}>", e.getMessage()); + throw e; + } if (window <= 0) { LOGGER.error("Configuration failure: <[{}]> too small, expected to be >0", window); throw new ConfigurationException("Invalid value for received"); diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java deleted file mode 100644 index b00690d..0000000 --- a/src/main/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationBuilder.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * RELP Commit Latency Probe RLP-11 - * Copyright (C) 2024 Suomen Kanuuna Oy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * - * Additional permission under GNU Affero General Public License version 3 - * section 7 - * - * If you modify this Program, or any covered work, by linking or combining it - * with other code, such other code is not for that reason alone subject to any - * of the requirements of the GNU Affero GPL version 3 as long as this Program - * is the same Program as licensed from Suomen Kanuuna Oy without any additional - * modifications. - * - * Supplemented terms under GNU Affero General Public License version 3 - * section 7 - * - * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified - * versions must be marked as "Modified version of" The Program. - * - * Names of the licensors and authors may not be used for publicity purposes. - * - * No rights are granted for use of trade names, trademarks, or service marks - * which are in The Program if any. - * - * Licensee must indemnify licensors and authors for any liability that these - * contractual assumptions impose on licensors and authors. - * - * To the extent this program is licensed as part of the Commercial versions of - * Teragrep, the applicable Commercial License may apply to this file if you as - * a licensee so wish it. - */ -package com.teragrep.rlp_11.Configuration; - -import java.util.Map; - -public final class MetricsConfigurationBuilder { - - private MetricsConfigurationBuilder() { - - } - - public static MetricsConfiguration build(final Map config) { - final String name = config.get("metrics.name"); - final int window = IntConfigurationBuilder.get("metrics.window", config.get("metrics.window")); - return new MetricsConfiguration(name, window); - } -} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/ProbeConfiguration.java similarity index 72% rename from src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java rename to src/main/java/com/teragrep/rlp_11/Configuration/ProbeConfiguration.java index 2030cfc..83315ec 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/IntConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/ProbeConfiguration.java @@ -48,21 +48,35 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class IntConfigurationBuilder { +import java.util.Map; - private static final Logger LOGGER = LoggerFactory.getLogger(IntConfigurationBuilder.class); +public class ProbeConfiguration { - private IntConfigurationBuilder() { + private static final Logger LOGGER = LoggerFactory.getLogger(ProbeConfiguration.class); + private final Map config; + public ProbeConfiguration(final Map config) { + this.config = config; } - public static int get(final String name, final String value) { + public int interval() { + final String intervalString = config.get("probe.interval"); + if (intervalString == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); + } + final int interval; try { - return Integer.parseInt(value); + interval = Integer.parseInt(intervalString); } catch (NumberFormatException e) { - LOGGER.error("Configuration failure: Invalid value for <{}> received: <{}>", name, e.getMessage()); - throw new ConfigurationException("Invalid value for <" + name + "> received: <" + e.getMessage() + ">"); + LOGGER.error("Configuration failure: Invalid value for : <{}>", e.getMessage()); + throw e; + } + if (interval <= 0) { + LOGGER.error("Configuration failure: <[{}]> too small, expected to be >0", interval); + throw new ConfigurationException("Invalid value for received"); } + return interval; } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java index 34772f4..817b987 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfiguration.java @@ -48,17 +48,31 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; + public class PrometheusConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(PrometheusConfiguration.class); + private final Map config; - private final int port; - - public PrometheusConfiguration(final int port) { - this.port = port; + public PrometheusConfiguration(final Map config) { + this.config = config; } public int port() { + final String portString = config.get("prometheus.port"); + if (portString == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); + } + final int port; + try { + port = Integer.parseInt(portString); + } + catch (NumberFormatException e) { + LOGGER.error("Configuration failure: Invalid value for : <{}>", e.getMessage()); + throw e; + } if (port < 1 || port > 65535) { LOGGER .error( diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java deleted file mode 100644 index 2897ec5..0000000 --- a/src/main/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationBuilder.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * RELP Commit Latency Probe RLP-11 - * Copyright (C) 2024 Suomen Kanuuna Oy - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * - * Additional permission under GNU Affero General Public License version 3 - * section 7 - * - * If you modify this Program, or any covered work, by linking or combining it - * with other code, such other code is not for that reason alone subject to any - * of the requirements of the GNU Affero GPL version 3 as long as this Program - * is the same Program as licensed from Suomen Kanuuna Oy without any additional - * modifications. - * - * Supplemented terms under GNU Affero General Public License version 3 - * section 7 - * - * Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified - * versions must be marked as "Modified version of" The Program. - * - * Names of the licensors and authors may not be used for publicity purposes. - * - * No rights are granted for use of trade names, trademarks, or service marks - * which are in The Program if any. - * - * Licensee must indemnify licensors and authors for any liability that these - * contractual assumptions impose on licensors and authors. - * - * To the extent this program is licensed as part of the Commercial versions of - * Teragrep, the applicable Commercial License may apply to this file if you as - * a licensee so wish it. - */ -package com.teragrep.rlp_11.Configuration; - -import java.util.Map; - -public final class PrometheusConfigurationBuilder { - - private PrometheusConfigurationBuilder() { - - } - - public static PrometheusConfiguration build(final Map config) { - final int port = IntConfigurationBuilder.get("prometheus.port", config.get("prometheus.port")); - return new PrometheusConfiguration(port); - } -} diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/RecordConfiguration.java similarity index 74% rename from src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java rename to src/main/java/com/teragrep/rlp_11/Configuration/RecordConfiguration.java index 312858c..9d3cfc6 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/RecordConfiguration.java @@ -48,40 +48,32 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class EventConfiguration { +import java.util.Map; - private static final Logger LOGGER = LoggerFactory.getLogger(EventConfiguration.class); - private final String hostname; - private final String appname; - private final int delay; +public class RecordConfiguration { - public EventConfiguration(final String hostname, final String appname, final int delay) { - this.hostname = hostname; - this.appname = appname; - this.delay = delay; + private static final Logger LOGGER = LoggerFactory.getLogger(RecordConfiguration.class); + private final Map config; + + public RecordConfiguration(final Map config) { + this.config = config; } public String hostname() { + final String hostname = config.get("record.hostname"); if (hostname == null) { - LOGGER.error("Configuration failure: is null"); - throw new ConfigurationException("Invalid value for received"); + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } return hostname; } public String appname() { + final String appname = config.get("record.appname"); if (appname == null) { - LOGGER.error("Configuration failure: is null"); - throw new ConfigurationException("Invalid value for received"); + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); } return appname; } - - public int delay() { - if (delay <= 0) { - LOGGER.error("Configuration failure: <[{}]> too small, expected to be >0", delay); - throw new ConfigurationException("Invalid value for received"); - } - return delay; - } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java index d619d38..ac2ee11 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java +++ b/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfiguration.java @@ -48,20 +48,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Map; + public class TargetConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(TargetConfiguration.class); - private final String hostname; - private final int port; - private final int reconnectInterval; + private final Map config; - public TargetConfiguration(final String hostname, final int port, final int reconnectInterval) { - this.hostname = hostname; - this.port = port; - this.reconnectInterval = reconnectInterval; + public TargetConfiguration(final Map config) { + this.config = config; } public String hostname() { + final String hostname = config.get("target.hostname"); if (hostname == null) { LOGGER.error("Configuration failure: is null"); throw new ConfigurationException("Invalid value for received"); @@ -70,6 +69,19 @@ public String hostname() { } public int port() { + final String portString = config.get("target.port"); + if (portString == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); + } + final int port; + try { + port = Integer.parseInt(portString); + } + catch (NumberFormatException e) { + LOGGER.error("Configuration failure: Invalid value for : <{}>", e.getMessage()); + throw e; + } if (port < 1 || port > 65535) { LOGGER .error( @@ -82,6 +94,19 @@ public int port() { } public int reconnectInterval() { + final String reconnectIntervalString = config.get("target.reconnectinterval"); + if (reconnectIntervalString == null) { + LOGGER.error("Configuration failure: is null"); + throw new ConfigurationException("Invalid value for received"); + } + final int reconnectInterval; + try { + reconnectInterval = Integer.parseInt(reconnectIntervalString); + } + catch (NumberFormatException e) { + LOGGER.error("Configuration failure: Invalid value for : <{}>", e.getMessage()); + throw e; + } if (reconnectInterval <= 0) { LOGGER .error( diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index 7c63436..6092cf2 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -46,17 +46,16 @@ package com.teragrep.rlp_11; import com.teragrep.cnf_01.PathConfiguration; -import com.teragrep.rlp_11.Configuration.EventConfiguration; -import com.teragrep.rlp_11.Configuration.EventConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.ProbeConfiguration; +import com.teragrep.rlp_11.Configuration.RecordConfiguration; import com.teragrep.rlp_11.Configuration.MetricsConfiguration; -import com.teragrep.rlp_11.Configuration.MetricsConfigurationBuilder; import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; -import com.teragrep.rlp_11.Configuration.PrometheusConfigurationBuilder; import com.teragrep.rlp_11.Configuration.TargetConfiguration; -import com.teragrep.rlp_11.Configuration.TargetConfigurationBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Map; public class Main { @@ -75,16 +74,22 @@ public static void main(final String[] args) throws com.teragrep.cnf_01.Configur LOGGER.error("Failed to create PathConfiguration: <{}>", e.getMessage()); throw e; } - final PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); - final EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); - final TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); - final MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); - + final PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); + final RecordConfiguration recordConfiguration = new RecordConfiguration(map); + final TargetConfiguration targetConfiguration = new TargetConfiguration(map); + final MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); + final RecordFactory recordFactory = new RecordFactory( + getHostname(), + recordConfiguration.hostname(), + recordConfiguration.appname() + ); + final ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); final RelpProbe relpProbe = new RelpProbe( targetConfiguration, - eventConfiguration, + probeConfiguration, prometheusConfiguration, - metricsConfiguration + metricsConfiguration, + recordFactory ); final Thread shutdownHook = new Thread(() -> { LOGGER.debug("Stopping RelpProbe.."); @@ -95,9 +100,21 @@ public static void main(final String[] args) throws com.teragrep.cnf_01.Configur LOGGER.info("Sending events to <[{}:{}]>", targetConfiguration.hostname(), targetConfiguration.port()); LOGGER .info( - "Using hostname <[{}]> and appname <[{}]> for the events.", eventConfiguration.hostname(), - eventConfiguration.appname() + "Using hostname <[{}]> and appname <[{}]> for the events.", recordConfiguration.hostname(), + recordConfiguration.appname() ); relpProbe.start(); } + + private static String getHostname() { + String origin; + try { + origin = InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) { + origin = "localhost"; + LOGGER.warn("Could not get hostname, using <{}> instead", origin); + } + return origin; + } } diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java b/src/main/java/com/teragrep/rlp_11/RecordFactory.java similarity index 59% rename from src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java rename to src/main/java/com/teragrep/rlp_11/RecordFactory.java index 6e850a5..07cc514 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/EventConfigurationBuilder.java +++ b/src/main/java/com/teragrep/rlp_11/RecordFactory.java @@ -43,20 +43,45 @@ * Teragrep, the applicable Commercial License may apply to this file if you as * a licensee so wish it. */ -package com.teragrep.rlp_11.Configuration; +package com.teragrep.rlp_11; -import java.util.Map; +import com.teragrep.rlo_14.Facility; +import com.teragrep.rlo_14.Severity; +import com.teragrep.rlo_14.SyslogMessage; +import jakarta.json.Json; +import jakarta.json.JsonObject; -public final class EventConfigurationBuilder { +import java.nio.charset.StandardCharsets; +import java.time.Instant; - private EventConfigurationBuilder() { +public class RecordFactory { + private final String origin; + private final String hostname; + private final String appname; + + public RecordFactory(final String origin, final String hostname, final String appname) { + this.origin = origin; + this.hostname = hostname; + this.appname = appname; } - public static EventConfiguration build(final Map config) { - final String hostname = config.get("event.hostname"); - final String appname = config.get("event.appname"); - final int delay = IntConfigurationBuilder.get("event.delay", config.get("event.delay")); - return new EventConfiguration(hostname, appname, delay); + public byte[] createRecord() { + final Instant timestamp = Instant.now(); + final String timestampString = timestamp.getEpochSecond() + "." + timestamp.getNano(); + final JsonObject event = Json + .createObjectBuilder() + .add("origin", origin) + .add("timestamp", timestampString) + .build(); + return new SyslogMessage() + .withTimestamp(timestamp.toEpochMilli()) + .withAppName(appname) + .withHostname(hostname) + .withFacility(Facility.USER) + .withSeverity(Severity.INFORMATIONAL) + .withMsg(event.toString()) + .toRfc5424SyslogMessage() + .getBytes(StandardCharsets.UTF_8); } } diff --git a/src/main/java/com/teragrep/rlp_11/RelpProbe.java b/src/main/java/com/teragrep/rlp_11/RelpProbe.java index 3df53b3..277138d 100644 --- a/src/main/java/com/teragrep/rlp_11/RelpProbe.java +++ b/src/main/java/com/teragrep/rlp_11/RelpProbe.java @@ -51,12 +51,9 @@ import com.codahale.metrics.SlidingWindowReservoir; import com.codahale.metrics.Timer; import com.codahale.metrics.jmx.JmxReporter; -import com.teragrep.rlo_14.Facility; -import com.teragrep.rlo_14.Severity; -import com.teragrep.rlo_14.SyslogMessage; import com.teragrep.rlp_01.RelpBatch; import com.teragrep.rlp_01.RelpConnection; -import com.teragrep.rlp_11.Configuration.EventConfiguration; +import com.teragrep.rlp_11.Configuration.ProbeConfiguration; import com.teragrep.rlp_11.Configuration.MetricsConfiguration; import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; import com.teragrep.rlp_11.Configuration.TargetConfiguration; @@ -65,28 +62,22 @@ import org.slf4j.LoggerFactory; import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.util.concurrent.CountDownLatch; -import java.nio.charset.StandardCharsets; -import java.time.Instant; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; -import jakarta.json.Json; -import jakarta.json.JsonObject; - import static com.codahale.metrics.MetricRegistry.name; public class RelpProbe { private static final Logger LOGGER = LoggerFactory.getLogger(RelpProbe.class); private final TargetConfiguration targetConfiguration; - private final EventConfiguration eventConfiguration; + private final RecordFactory recordFactory; private final PrometheusConfiguration prometheusConfiguration; private final MetricsConfiguration metricsConfiguration; + private final ProbeConfiguration probeConfiguration; private final AtomicBoolean stayRunning = new AtomicBoolean(true); private RelpConnection relpConnection; private final CountDownLatch latch = new CountDownLatch(1); @@ -104,12 +95,14 @@ public class RelpProbe { public RelpProbe( final TargetConfiguration targetConfiguration, - final EventConfiguration eventConfiguration, + final ProbeConfiguration probeConfiguration, final PrometheusConfiguration prometheusConfiguration, - final MetricsConfiguration metricsConfiguration + final MetricsConfiguration metricsConfiguration, + final RecordFactory recordFactory ) { this.targetConfiguration = targetConfiguration; - this.eventConfiguration = eventConfiguration; + this.probeConfiguration = probeConfiguration; + this.recordFactory = recordFactory; this.prometheusConfiguration = prometheusConfiguration; this.metricsConfiguration = metricsConfiguration; } @@ -118,19 +111,11 @@ public void start() { createMetrics(metricsConfiguration.name()); this.jmxReporter.start(); this.slf4jReporter.start(1, TimeUnit.MINUTES); - String origin; - try { - origin = InetAddress.getLocalHost().getHostName(); - } - catch (UnknownHostException e) { - origin = "localhost"; - LOGGER.warn("Could not get hostname, using <{}> instead", origin); - } relpConnection = new RelpConnection(); connect(); while (stayRunning.get()) { final RelpBatch relpBatch = new RelpBatch(); - relpBatch.insert(createPayload(origin)); + relpBatch.insert(recordFactory.createRecord()); boolean allSent = false; while (!allSent && stayRunning.get()) { @@ -155,7 +140,7 @@ public void start() { } try { LOGGER.debug("Sleeping before sending next event"); - Thread.sleep(eventConfiguration.delay()); + Thread.sleep(probeConfiguration.interval()); } catch (InterruptedException e) { LOGGER.warn("Sleep interrupted: <{}>", e.getMessage()); @@ -233,24 +218,6 @@ public void stop() { LOGGER.debug("RelpProbe stopped."); } - private byte[] createPayload(final String origin) { - final Instant timestamp = Instant.now(); - final JsonObject event = Json - .createObjectBuilder() - .add("origin", origin) - .add("timestamp", timestamp.getEpochSecond() + "." + timestamp.getNano()) - .build(); - return new SyslogMessage() - .withTimestamp(timestamp.toEpochMilli()) - .withAppName(eventConfiguration.appname()) - .withHostname(eventConfiguration.hostname()) - .withFacility(Facility.USER) - .withSeverity(Severity.INFORMATIONAL) - .withMsg(event.toString()) - .toRfc5424SyslogMessage() - .getBytes(StandardCharsets.UTF_8); - } - private void createMetrics(final String name) { final MetricRegistry metricRegistry = new MetricRegistry(); this.records = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "records")); @@ -258,7 +225,6 @@ private void createMetrics(final String name) { this.connects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "connects")); this.disconnects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "disconnects")); this.retriedConnects = metricRegistry.counter(name(RelpProbe.class, "<[" + name + "]>", "retriedConnects")); - // TODO: Configurable window? this.sendLatency = metricRegistry .timer(name(RelpProbe.class, "<[" + name + "]>", "sendLatency"), () -> new Timer(new SlidingWindowReservoir(metricsConfiguration.window()))); this.connectLatency = metricRegistry @@ -272,8 +238,8 @@ private void createMetrics(final String name) { } private void teardownMetrics() { - slf4jReporter.close(); jmxReporter.close(); + slf4jReporter.close(); try { jettyServer.stop(); } diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java index 9ae9dcf..aee9f41 100644 --- a/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java +++ b/src/test/java/com/teragrep/rlp_11/Configuration/MetricsConfigurationTest.java @@ -57,7 +57,7 @@ public class MetricsConfigurationTest { @Test public void testNonNullName() { Map map = baseConfig(); - MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); Assertions.assertEquals("target-name", metricsConfiguration.name()); } @@ -65,7 +65,7 @@ public void testNonNullName() { public void testNullName() { Map map = baseConfig(); map.remove("metrics.name"); - MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, metricsConfiguration::name); } @@ -73,7 +73,7 @@ public void testNullName() { @Test public void testGoodWindow() { Map map = baseConfig(); - MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); Assertions.assertEquals(1337, metricsConfiguration.window()); } @@ -81,14 +81,15 @@ public void testGoodWindow() { public void testNullWindow() { Map map = baseConfig(); map.remove("metrics.window"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> MetricsConfigurationBuilder.build(map)); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, metricsConfiguration::window); } @Test public void testTooSmallWindow() { Map map = baseConfig(); map.put("metrics.window", "0"); - MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, metricsConfiguration::window); } @@ -96,7 +97,8 @@ public void testTooSmallWindow() { public void testNonNumericWindow() { Map map = baseConfig(); map.put("metrics.window", "Not a number here"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> MetricsConfigurationBuilder.build(map)); + MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); + Assertions.assertThrowsExactly(NumberFormatException.class, metricsConfiguration::window); } private Map baseConfig() { diff --git a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java b/src/test/java/com/teragrep/rlp_11/Configuration/ProbeConfigurationTest.java similarity index 56% rename from src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java rename to src/test/java/com/teragrep/rlp_11/Configuration/ProbeConfigurationTest.java index f60e9f6..b7b0276 100644 --- a/src/main/java/com/teragrep/rlp_11/Configuration/TargetConfigurationBuilder.java +++ b/src/test/java/com/teragrep/rlp_11/Configuration/ProbeConfigurationTest.java @@ -45,19 +45,49 @@ */ package com.teragrep.rlp_11.Configuration; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; import java.util.Map; -public final class TargetConfigurationBuilder { +public class ProbeConfigurationTest { + + // probe.interval + @Test + public void testGoodInterval() { + Map map = baseConfig(); + ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); + Assertions.assertEquals(12500, probeConfiguration.interval()); + } + + @Test + public void testNullInterval() { + Map map = baseConfig(); + map.remove("probe.interval"); + ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, probeConfiguration::interval); + } - private TargetConfigurationBuilder() { + @Test + public void testTooSmallInterval() { + Map map = baseConfig(); + map.put("probe.interval", "0"); + ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, probeConfiguration::interval); + } + @Test + public void testNonNumericInterval() { + Map map = baseConfig(); + map.put("probe.interval", "not a number"); + ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); + Assertions.assertThrowsExactly(NumberFormatException.class, probeConfiguration::interval); } - public static TargetConfiguration build(final Map config) { - final String hostname = config.get("target.hostname"); - final int port = IntConfigurationBuilder.get("target.port", config.get("target.port")); - final int reconnectInterval = IntConfigurationBuilder - .get("target.reconnectinterval", config.get("target.reconnectinterval")); - return new TargetConfiguration(hostname, port, reconnectInterval); + private Map baseConfig() { + Map map = new HashMap<>(); + map.put("probe.interval", "12500"); + return map; } } diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java index 9e498c3..008e6f4 100644 --- a/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java +++ b/src/test/java/com/teragrep/rlp_11/Configuration/PrometheusConfigurationTest.java @@ -57,7 +57,7 @@ public class PrometheusConfigurationTest { @Test public void testGoodPort() { Map map = baseConfig(); - PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); Assertions.assertEquals(8080, prometheusConfiguration.port()); } @@ -65,14 +65,15 @@ public void testGoodPort() { public void testNullPort() { Map map = baseConfig(); map.remove("prometheus.port"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> PrometheusConfigurationBuilder.build(map)); + PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, prometheusConfiguration::port); } @Test public void testTooSmallPort() { Map map = baseConfig(); map.put("prometheus.port", "0"); - PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, prometheusConfiguration::port); } @@ -80,15 +81,16 @@ public void testTooSmallPort() { public void testTooHighPort() { Map map = baseConfig(); map.put("prometheus.port", "65536"); - PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); + PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, prometheusConfiguration::port); } @Test - public void testNonNumericport() { + public void testNonNumericPort() { Map map = baseConfig(); map.put("prometheus.port", "not a number"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> PrometheusConfigurationBuilder.build(map)); + PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); + Assertions.assertThrowsExactly(NumberFormatException.class, prometheusConfiguration::port); } private Map baseConfig() { diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/RecordConfigurationTest.java similarity index 64% rename from src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java rename to src/test/java/com/teragrep/rlp_11/Configuration/RecordConfigurationTest.java index d9852f4..ee53329 100644 --- a/src/test/java/com/teragrep/rlp_11/Configuration/EventConfigurationTest.java +++ b/src/test/java/com/teragrep/rlp_11/Configuration/RecordConfigurationTest.java @@ -51,21 +51,21 @@ import java.util.HashMap; import java.util.Map; -public class EventConfigurationTest { +public class RecordConfigurationTest { // event.hostname @Test public void testNonNullHostname() { Map map = baseConfig(); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + RecordConfiguration eventConfiguration = new RecordConfiguration(map); Assertions.assertEquals("my-hostname", eventConfiguration.hostname()); } @Test public void testNullHostname() { Map map = baseConfig(); - map.remove("event.hostname"); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + map.remove("record.hostname"); + RecordConfiguration eventConfiguration = new RecordConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::hostname); } @@ -73,53 +73,22 @@ public void testNullHostname() { @Test public void testNonNullAppname() { Map map = baseConfig(); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + RecordConfiguration eventConfiguration = new RecordConfiguration(map); Assertions.assertEquals("my-appname", eventConfiguration.appname()); } @Test public void testNullAppname() { Map map = baseConfig(); - map.remove("event.appname"); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); + map.remove("record.appname"); + RecordConfiguration eventConfiguration = new RecordConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::appname); } - // event.delay - @Test - public void testGoodDelay() { - Map map = baseConfig(); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); - Assertions.assertEquals(15000, eventConfiguration.delay()); - } - - @Test - public void testNullDelay() { - Map map = baseConfig(); - map.remove("event.delay"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> EventConfigurationBuilder.build(map)); - } - - @Test - public void testTooSmallDelay() { - Map map = baseConfig(); - map.put("event.delay", "0"); - EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); - Assertions.assertThrowsExactly(ConfigurationException.class, eventConfiguration::delay); - } - - @Test - public void testNonNumericDelay() { - Map map = baseConfig(); - map.put("event.delay", "not a number"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> EventConfigurationBuilder.build(map)); - } - private Map baseConfig() { Map map = new HashMap<>(); - map.put("event.hostname", "my-hostname"); - map.put("event.appname", "my-appname"); - map.put("event.delay", "15000"); + map.put("record.hostname", "my-hostname"); + map.put("record.appname", "my-appname"); return map; } } diff --git a/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java b/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java index 980254f..9fe0693 100644 --- a/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java +++ b/src/test/java/com/teragrep/rlp_11/Configuration/TargetConfigurationTest.java @@ -57,7 +57,7 @@ public class TargetConfigurationTest { @Test public void testNonNullHostname() { Map map = baseConfig(); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertEquals("target-hostname", targetConfiguration.hostname()); } @@ -65,7 +65,7 @@ public void testNonNullHostname() { public void testNullHostname() { Map map = baseConfig(); map.remove("target.hostname"); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::hostname); } @@ -73,7 +73,7 @@ public void testNullHostname() { @Test public void testGoodPort() { Map map = baseConfig(); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertEquals(601, targetConfiguration.port()); } @@ -81,14 +81,15 @@ public void testGoodPort() { public void testNullPort() { Map map = baseConfig(); map.remove("target.port"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::port); } @Test public void testTooSmallPort() { Map map = baseConfig(); map.put("target.port", "0"); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::port); } @@ -96,7 +97,7 @@ public void testTooSmallPort() { public void testTooHighPort() { Map map = baseConfig(); map.put("target.port", "65536"); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::port); } @@ -104,14 +105,15 @@ public void testTooHighPort() { public void testNonNumericPort() { Map map = baseConfig(); map.put("target.port", "not a number"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); + Assertions.assertThrowsExactly(NumberFormatException.class, targetConfiguration::port); } // target.reconnectinterval @Test public void testGoodReconnectInterval() { Map map = baseConfig(); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertEquals(15000, targetConfiguration.reconnectInterval()); } @@ -119,14 +121,15 @@ public void testGoodReconnectInterval() { public void testNullReconnectInterval() { Map map = baseConfig(); map.remove("target.reconnectinterval"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); + Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::reconnectInterval); } @Test public void testTooSmallReconnectInterval() { Map map = baseConfig(); map.put("target.reconnectinterval", "0"); - TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); Assertions.assertThrowsExactly(ConfigurationException.class, targetConfiguration::reconnectInterval); } @@ -134,7 +137,8 @@ public void testTooSmallReconnectInterval() { public void testNonNumericReconnectInterval() { Map map = baseConfig(); map.put("target.reconnectinterval", "not a number"); - Assertions.assertThrowsExactly(ConfigurationException.class, () -> TargetConfigurationBuilder.build(map)); + TargetConfiguration targetConfiguration = new TargetConfiguration(map); + Assertions.assertThrowsExactly(NumberFormatException.class, targetConfiguration::reconnectInterval); } private Map baseConfig() { diff --git a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java index 4caf448..d9fd278 100644 --- a/src/test/java/com/teragrep/rlp_11/ConnectionTest.java +++ b/src/test/java/com/teragrep/rlp_11/ConnectionTest.java @@ -54,14 +54,10 @@ import com.teragrep.rlp_03.frame.FrameDelegationClockFactory; import com.teragrep.rlp_03.frame.delegate.DefaultFrameDelegate; import com.teragrep.rlp_03.frame.delegate.FrameDelegate; -import com.teragrep.rlp_11.Configuration.EventConfiguration; -import com.teragrep.rlp_11.Configuration.EventConfigurationBuilder; +import com.teragrep.rlp_11.Configuration.ProbeConfiguration; import com.teragrep.rlp_11.Configuration.MetricsConfiguration; -import com.teragrep.rlp_11.Configuration.MetricsConfigurationBuilder; import com.teragrep.rlp_11.Configuration.PrometheusConfiguration; -import com.teragrep.rlp_11.Configuration.PrometheusConfigurationBuilder; import com.teragrep.rlp_11.Configuration.TargetConfiguration; -import com.teragrep.rlp_11.Configuration.TargetConfigurationBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -129,16 +125,18 @@ public void stopServer() { public void connectToServerTest() { Map map = Assertions .assertDoesNotThrow(() -> new PathConfiguration("src/test/resources/connectiontest.properties").asMap()); - final PrometheusConfiguration prometheusConfiguration = PrometheusConfigurationBuilder.build(map); - final EventConfiguration eventConfiguration = EventConfigurationBuilder.build(map); - final TargetConfiguration targetConfiguration = TargetConfigurationBuilder.build(map); - final MetricsConfiguration metricsConfiguration = MetricsConfigurationBuilder.build(map); + final PrometheusConfiguration prometheusConfiguration = new PrometheusConfiguration(map); + final ProbeConfiguration probeConfiguration = new ProbeConfiguration(map); + final RecordFactory recordFactory = new RecordFactory("localhost", "rlp_11", "rlp_11"); + final TargetConfiguration targetConfiguration = new TargetConfiguration(map); + final MetricsConfiguration metricsConfiguration = new MetricsConfiguration(map); RelpProbe relpProbe = new RelpProbe( targetConfiguration, - eventConfiguration, + probeConfiguration, prometheusConfiguration, - metricsConfiguration + metricsConfiguration, + recordFactory ); TimerTask task = new TimerTask() { diff --git a/src/test/resources/connectiontest.properties b/src/test/resources/connectiontest.properties index 9719305..079c639 100644 --- a/src/test/resources/connectiontest.properties +++ b/src/test/resources/connectiontest.properties @@ -1,18 +1,19 @@ -# Appname used in RELP event -event.appname=rlp_11 -# Delay between sending events, in milliseconds -event.delay=1000 -# Hostname used in RELP event -event.hostname=rlp_11 - # Metrics reporting name. Arbitrary string, only used for reporting purposes metrics.name=target # Metrics window size metrics.window=10000 +# Delay between sending events, in milliseconds +probe.interval=1000 + # Prometheus endpoint port prometheus.port=8080 +# Appname used in RELP record +record.appname=rlp_11 +# Hostname used in RELP record +record.hostname=rlp_11 + # RELP Server target address target.hostname=127.0.0.1 # Relp Server target port diff --git a/src/test/resources/missing.properties b/src/test/resources/missing.properties index e69de29..8b13789 100644 --- a/src/test/resources/missing.properties +++ b/src/test/resources/missing.properties @@ -0,0 +1 @@ + From 3d4ac6613d09aeb894f694a16700419868cc7825 Mon Sep 17 00:00:00 2001 From: StrongestNumber9 <16169054+StrongestNumber9@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:52:49 +0200 Subject: [PATCH 14/14] Minor debugging print tweak --- src/main/java/com/teragrep/rlp_11/Main.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/teragrep/rlp_11/Main.java b/src/main/java/com/teragrep/rlp_11/Main.java index 6092cf2..503e377 100644 --- a/src/main/java/com/teragrep/rlp_11/Main.java +++ b/src/main/java/com/teragrep/rlp_11/Main.java @@ -97,10 +97,14 @@ public static void main(final String[] args) throws com.teragrep.cnf_01.Configur LOGGER.debug("Shutting down."); }); Runtime.getRuntime().addShutdownHook(shutdownHook); - LOGGER.info("Sending events to <[{}:{}]>", targetConfiguration.hostname(), targetConfiguration.port()); LOGGER .info( - "Using hostname <[{}]> and appname <[{}]> for the events.", recordConfiguration.hostname(), + "Sending records to <[{}:{}]> every <[{}]> milliseconds", targetConfiguration.hostname(), + targetConfiguration.port(), probeConfiguration.interval() + ); + LOGGER + .info( + "Using hostname <[{}]> and appname <[{}]> for the records.", recordConfiguration.hostname(), recordConfiguration.appname() ); relpProbe.start();