summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Cogoluègnes <acogoluegnes@gmail.com>2021-01-12 18:46:49 +0100
committerArnaud Cogoluègnes <acogoluegnes@gmail.com>2021-01-12 18:46:49 +0100
commitb3b77897cd3495fb35abeae278d3c231f23aadf5 (patch)
treebaeaa415f4db358679ec69421b3b11275e0b3f2f
parent788354d99f288726b852aa10976e76c3def53aef (diff)
downloadrabbitmq-server-git-b3b77897cd3495fb35abeae278d3c231f23aadf5.tar.gz
Start test suite for stream prometheus
-rw-r--r--deps/rabbitmq_stream_prometheus/src/collectors/prometheus_rabbitmq_stream_collector.erl60
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE.erl72
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.gitignore3
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java117
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.jarbin0 -> 50710 bytes
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.properties2
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/wrapper.iml6
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/Makefile14
-rwxr-xr-xdeps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw310
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw.cmd182
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/pom.xml143
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/PrometheusHttpTest.java202
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/TestUtils.java209
-rw-r--r--deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/resources/logback-test.xml13
14 files changed, 1316 insertions, 17 deletions
diff --git a/deps/rabbitmq_stream_prometheus/src/collectors/prometheus_rabbitmq_stream_collector.erl b/deps/rabbitmq_stream_prometheus/src/collectors/prometheus_rabbitmq_stream_collector.erl
index e4033912ff..3e1590a46c 100644
--- a/deps/rabbitmq_stream_prometheus/src/collectors/prometheus_rabbitmq_stream_collector.erl
+++ b/deps/rabbitmq_stream_prometheus/src/collectors/prometheus_rabbitmq_stream_collector.erl
@@ -21,6 +21,7 @@
collect_metrics/2]).
-include_lib("prometheus/include/prometheus.hrl").
+-include_lib("rabbit_common/include/rabbit.hrl").
-include_lib("rabbitmq_stream/include/rabbit_stream_metrics.hrl").
-behaviour(prometheus_collector).
@@ -31,24 +32,31 @@
{?TABLE_PUBLISHER,
[{2,
undefined,
- producers_messages_published_total,
+ publishers,
+ gauge,
+ "Number of publishers",
+ publishers},
+ {2,
+ undefined,
+ publishers_messages_published_total,
counter,
"Total number of messages published to streams",
published},
{2,
undefined,
- producers_messages_confirmed_total,
+ publishers_messages_confirmed_total,
counter,
"Total number of messages confirmed",
confirmed},
{2,
undefined,
- producers_messages_errored_total,
+ publishers_messages_errored_total,
counter,
"Total number of messages errored",
errored}]},
{?TABLE_CONSUMER,
- [{2,
+ [{2, undefined, consumers, gauge, "Number of consumers", consumers},
+ {2,
undefined,
consumers_messages_consumed_total,
counter,
@@ -77,22 +85,24 @@ collect(PerObjectMetrics, Callback) ->
ok.
get_data(?TABLE_PUBLISHER = Table, false) ->
- {Table, A1, A2, A3} =
- ets:foldl(fun({_, Props}, {T, A1, A2, A3}) ->
+ {Table, A1, A2, A3, A4} =
+ ets:foldl(fun({_, Props}, {T, A1, A2, A3, A4}) ->
{T,
- sum(proplists:get_value(published, Props), A1),
- sum(proplists:get_value(confirmed, Props), A2),
- sum(proplists:get_value(errored, Props), A3)}
+ A1 + 1,
+ sum(proplists:get_value(published, Props), A2),
+ sum(proplists:get_value(confirmed, Props), A3),
+ sum(proplists:get_value(errored, Props), A4)}
end,
empty(Table), Table),
- [{Table, [{published, A1}, {confirmed, A2}, {errored, A3}]}];
+ [{Table,
+ [{publishers, A1}, {published, A2}, {confirmed, A3}, {errored, A4}]}];
get_data(?TABLE_CONSUMER = Table, false) ->
- {Table, A1} =
- ets:foldl(fun({_, Props}, {T, A1}) ->
- {T, sum(proplists:get_value(consumed, Props), A1)}
+ {Table, A1, A2} =
+ ets:foldl(fun({_, Props}, {T, A1, A2}) ->
+ {T, A1 + 1, sum(proplists:get_value(consumed, Props), A2)}
end,
empty(Table), Table),
- [{Table, [{consumed, A1}]}];
+ [{Table, [{consumers, A1}, {consumed, A2}]}];
get_data(Table, _) ->
ets:tab2list(Table).
@@ -117,7 +127,23 @@ mf(Callback, Contents, Data) ->
|| {Index, Conversion, Name, Type, Help, Key} <- Contents].
collect_metrics(_Name, {Type, Fun, Items}) ->
- [metric(Type, [], Fun(Item)) || Item <- Items].
+ [metric(Type, labels(Item), Fun(Item)) || Item <- Items].
+
+labels(Item) ->
+ label(element(1, Item)).
+
+label(#resource{virtual_host = VHost,
+ kind = queue,
+ name = Name}) ->
+ [{vhost, VHost}, {queue, Name}];
+label({Resource, Connection, Id}) ->
+ label(Resource) ++ label(Connection) ++ label(Id);
+label(P) when is_pid(P) ->
+ [{connection, P}];
+label(Id) when is_integer(Id) ->
+ [{id, Id}];
+label(_) ->
+ [].
metric(counter, Labels, Value) ->
emit_counter_metric_if_defined(Labels, Value);
@@ -145,9 +171,9 @@ emit_gauge_metric_if_defined(Labels, Value) ->
end.
empty(T) when T == ?TABLE_CONSUMER ->
- {T, 0};
+ {T, 0, 0};
empty(T) when T == ?TABLE_PUBLISHER ->
- {T, 0, 0, 0}.
+ {T, 0, 0, 0, 0}.
sum(undefined, B) ->
B;
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE.erl b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE.erl
new file mode 100644
index 0000000000..d4a15fe893
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE.erl
@@ -0,0 +1,72 @@
+%% This Source Code Form is subject to the terms of the Mozilla Public
+%% License, v. 2.0. If a copy of the MPL was not distributed with this
+%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
+%%
+%% Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
+%%
+
+-module(prometheus_http_SUITE).
+
+-compile(export_all).
+
+all() ->
+ [{group, non_parallel_tests}].
+
+groups() ->
+ [{non_parallel_tests, [], [stream_prometheus]}].
+
+%% -------------------------------------------------------------------
+%% Testsuite setup/teardown.
+%% -------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ rabbit_ct_helpers:log_environment(),
+ Config1 =
+ rabbit_ct_helpers:set_config(Config,
+ [{rmq_nodename_suffix, ?MODULE}]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [fun(StepConfig) ->
+ rabbit_ct_helpers:merge_app_env(StepConfig,
+ {rabbit,
+ [{collect_statistics_interval,
+ 500}]})
+ end]
+ ++ rabbit_ct_broker_helpers:setup_steps()
+ ++ rabbit_ct_client_helpers:setup_steps()).
+
+end_per_suite(Config) ->
+ rabbit_ct_helpers:run_teardown_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps()
+ ++ rabbit_ct_broker_helpers:teardown_steps()).
+
+init_per_group(_, Config) ->
+ Config.
+
+end_per_group(_, Config) ->
+ Config.
+
+init_per_testcase(Testcase, Config) ->
+ rabbit_ct_helpers:testcase_started(Config, Testcase).
+
+end_per_testcase(Testcase, Config) ->
+ rabbit_ct_helpers:testcase_finished(Config, Testcase).
+
+%% -------------------------------------------------------------------
+%% Testcases.
+%% -------------------------------------------------------------------
+
+stream_prometheus(Config) ->
+ StreamPortNode = get_stream_port(Config),
+ PrometheusPortNode = get_prometheus_port(Config),
+ DataDir = rabbit_ct_helpers:get_config(Config, data_dir),
+ MakeResult =
+ rabbit_ct_helpers:make(Config, DataDir,
+ ["tests", {"STREAM_PORT=~b", [StreamPortNode]},
+ {"PROMETHEUS_PORT=~b", [PrometheusPortNode]}]),
+ {ok, _} = MakeResult.
+
+get_stream_port(Config) ->
+ rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_stream).
+
+get_prometheus_port(Config) ->
+ proplists:get_value(prometheus_port, Config, 15692).
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.gitignore b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.gitignore
new file mode 100644
index 0000000000..4c70cdb707
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.gitignore
@@ -0,0 +1,3 @@
+/build/
+/lib/
+/target/
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000000..b901097f2d
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.jar b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..2cc7d4a55c
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.jar
Binary files differ
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.properties b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..642d572ce9
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/wrapper.iml b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/wrapper.iml
new file mode 100644
index 0000000000..abfc464b06
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/.mvn/wrapper/wrapper.iml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4">
+ <component name="MavenCustomPomFilePath">
+ <option name="mavenPomFileUrl" value="file://$MODULE_DIR$/maven-wrapper.properties" />
+ </component>
+</module> \ No newline at end of file
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/Makefile b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/Makefile
new file mode 100644
index 0000000000..16677504bc
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/Makefile
@@ -0,0 +1,14 @@
+export PATH :=$(CURDIR):$(PATH)
+HOSTNAME := $(shell hostname)
+MVN_FLAGS += -Dstream.port=$(STREAM_PORT) \
+ -Dmanagement.port=$(MANAGEMENT_PORT)
+
+.PHONY: tests clean
+
+tests:
+ # Note: to run a single test
+ # @mvnw -q $(MVN_FLAGS) -Dtest=StreamTest#metadataOnClusterShouldReturnLeaderAndReplicas test
+ @mvnw -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B $(MVN_FLAGS) test
+
+clean:
+ @mvnw clean
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw
new file mode 100755
index 0000000000..41c0f0c23d
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw.cmd b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw.cmd
new file mode 100644
index 0000000000..86115719e5
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/pom.xml b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/pom.xml
new file mode 100644
index 0000000000..354a3f1c3a
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.rabbitmq.stream</groupId>
+ <artifactId>rabbitmq-stream-prometheus-tests</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <licenses>
+ <license>
+ <name>MPL 2.0</name>
+ <url>https://www.mozilla.org/en-US/MPL/2.0/</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <developers>
+ <developer>
+ <email>info@rabbitmq.com</email>
+ <name>Team RabbitMQ</name>
+ <organization>VMware, Inc. or its affiliates.</organization>
+ <organizationUrl>https://rabbitmq.com</organizationUrl>
+ </developer>
+ </developers>
+
+ <properties>
+ <stream-client.version>0.1.0-SNAPSHOT</stream-client.version>
+ <proton-j.version>0.33.7</proton-j.version>
+ <junit.jupiter.version>5.7.0</junit.jupiter.version>
+ <assertj.version>3.18.1</assertj.version>
+ <okhttp.version>4.9.0</okhttp.version>
+ <logback.version>1.2.3</logback.version>
+ <maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
+ <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
+ <spotless.version>2.2.0</spotless.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>com.rabbitmq</groupId>
+ <artifactId>stream-client</artifactId>
+ <version>${stream-client.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>proton-j</artifactId>
+ <version>${proton-j.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit.jupiter.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit.jupiter.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${okhttp.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven.compiler.plugin.version}</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <compilerArgs>
+ <arg>-Xlint:deprecation</arg>
+ <arg>-Xlint:unchecked</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven-surefire-plugin.version}</version>
+ </plugin>
+
+ <plugin>
+ <groupId>com.diffplug.spotless</groupId>
+ <artifactId>spotless-maven-plugin</artifactId>
+ <version>${spotless.version}</version>
+ <configuration>
+ <java>
+ <googleJavaFormat>
+ <version>1.9</version>
+ <style>GOOGLE</style>
+ </googleJavaFormat>
+ </java>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+ <repositories>
+
+ <repository>
+ <id>ossrh</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <snapshots><enabled>true</enabled></snapshots>
+ <releases><enabled>false</enabled></releases>
+ </repository>
+
+ </repositories>
+
+</project> \ No newline at end of file
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/PrometheusHttpTest.java b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/PrometheusHttpTest.java
new file mode 100644
index 0000000000..34bdd72e97
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/PrometheusHttpTest.java
@@ -0,0 +1,202 @@
+// The contents of this file are subject to the Mozilla Public License
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License
+// at https://www.mozilla.org/en-US/MPL/2.0/
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and
+// limitations under the License.
+//
+// The Original Code is RabbitMQ.
+//
+// The Initial Developer of the Original Code is Pivotal Software, Inc.
+// Copyright (c) 2020 VMware, Inc. or its affiliates. All rights reserved.
+//
+
+package com.rabbitmq.stream;
+
+import com.rabbitmq.stream.TestUtils.ClientFactory;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.BinaryOperator;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(TestUtils.StreamTestInfrastructureExtension.class)
+public class PrometheusHttpTest {
+
+ static OkHttpClient httpClient = new OkHttpClient.Builder().build();
+ ClientFactory cf;
+ String stream;
+
+ static String get(String endpoint) throws IOException {
+ return get(httpClient, endpoint);
+ }
+
+ static String get(OkHttpClient client, String endpoint) throws IOException {
+ Request request = new Request.Builder().url(url(endpoint)).build();
+ try (Response response = client.newCall(request).execute()) {
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ ResponseBody body = response.body();
+ return body == null ? "" : body.string();
+ }
+ }
+
+ static String url(String endpoint) {
+ return "http://localhost:" + TestUtils.prometheusPort() + "/metrics" + endpoint;
+ }
+
+ static Metrics metrics() throws IOException {
+ return parseMetrics(get(""));
+ }
+
+ static Metrics parseMetrics(String content) throws IOException {
+ Metrics metrics = new Metrics();
+ try (BufferedReader reader = new BufferedReader(new StringReader(content))) {
+ String line;
+ String type = null, name = null;
+ Metric metric = null;
+ while ((line = reader.readLine()) != null) {
+ if (line.trim().isEmpty() || !line.contains("rabbitmq_stream_")) {
+ continue;
+ }
+ if (line.startsWith("# TYPE ")) {
+ String[] nameType = line.replace("# TYPE ", "").split(" ");
+ name = nameType[0];
+ type = nameType[1];
+ } else if (line.startsWith("# HELP ")) {
+ String help = line.replace("# HELP ", "").replace(name + " ", "");
+ metric = new Metric(name, type, help);
+ metrics.add(metric);
+ } else if (line.startsWith(name)) {
+ Map<String, String> labels = Collections.emptyMap();
+ if (line.contains("{")) {
+ String l = line.substring(line.indexOf("{"), line.indexOf("}"));
+ labels = Arrays.stream(l.split(",")).map(label -> label.trim().split("="))
+ .collect(() -> new HashMap<>(),
+ (acc, keyValue) -> acc.put(keyValue[0], keyValue[1].replace("\"", "")),
+ (BiConsumer<Map<String, String>, Map<String, String>>) (stringStringHashMap, stringStringHashMap2) -> stringStringHashMap.putAll(stringStringHashMap2));
+
+ }
+ int value;
+ try {
+ value = Integer.valueOf(line.split(" ")[1]);
+ } catch (NumberFormatException e) {
+ value = 0;
+ }
+ metric.add(new MetricValue(value, labels));
+ } else {
+ throw new IllegalStateException("Cannot parse line: " + line);
+ }
+ }
+ }
+
+ return metrics;
+ }
+
+ @Test
+ void aggregatedMetricsWithNoConnectionShouldReturnZero() throws Exception {
+ Metrics metrics = metrics();
+ System.out.println(metrics);
+ }
+
+ static class MetricValue {
+
+ private final int value;
+ private final Map<String, String> labels;
+
+ MetricValue(int value, Map<String, String> labels) {
+ this.value = value;
+ this.labels = labels == null ? Collections.emptyMap() : labels;
+ }
+
+ @Override
+ public String toString() {
+ return "MetricValue{" +
+ "value=" + value +
+ ", labels=" + labels +
+ '}';
+ }
+ }
+
+ static class Metric {
+
+ private final String name;
+ private final String type;
+ private final String help;
+ private final List<MetricValue> values = new ArrayList<>();
+
+ Metric(String name, String type, String help) {
+ this.name = name;
+ this.type = type;
+ this.help = help;
+ }
+
+ void add(MetricValue value) {
+ values.add(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Metric metric = (Metric) o;
+ return name.equals(metric.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public String toString() {
+ return "Metric{" +
+ "name='" + name + '\'' +
+ ", type='" + type + '\'' +
+ ", help='" + help + '\'' +
+ ", values=" + values +
+ '}';
+ }
+ }
+
+ static class Metrics {
+
+ private final Map<String, Metric> metrics = new HashMap<>();
+
+ void add(Metric metric) {
+ this.metrics.put(metric.name, metric);
+ }
+
+ Metric get(String name) {
+ return metrics.get(name);
+ }
+
+ @Override
+ public String toString() {
+ return "Metrics{" +
+ "metrics=" + metrics +
+ '}';
+ }
+ }
+}
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/TestUtils.java b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/TestUtils.java
new file mode 100644
index 0000000000..08f005f815
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/java/com/rabbitmq/stream/TestUtils.java
@@ -0,0 +1,209 @@
+// The contents of this file are subject to the Mozilla Public License
+// Version 2.0 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License
+// at https://www.mozilla.org/en-US/MPL/2.0/
+//
+// Software distributed under the License is distributed on an "AS IS"
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+// the License for the specific language governing rights and
+// limitations under the License.
+//
+// The Original Code is RabbitMQ.
+//
+// The Initial Developer of the Original Code is Pivotal Software, Inc.
+// Copyright (c) 2020-2021 VMware, Inc. or its affiliates. All rights reserved.
+//
+
+package com.rabbitmq.stream;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import com.rabbitmq.stream.impl.Client;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.time.Duration;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import okhttp3.Authenticator;
+import okhttp3.Credentials;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+public class TestUtils {
+
+ static int streamPort() {
+ String port = System.getProperty("stream.port", "5555");
+ return Integer.valueOf(port);
+ }
+
+ static int prometheusPort() {
+ String port = System.getProperty("prometheus.port", "15692");
+ return Integer.valueOf(port);
+ }
+
+ static void waitUntil(CallableBooleanSupplier condition) throws Exception {
+ waitAtMost(Duration.ofSeconds(10), condition);
+ }
+
+ static void waitAtMost(Duration duration, CallableBooleanSupplier condition) throws Exception {
+ if (condition.getAsBoolean()) {
+ return;
+ }
+ int waitTime = 100;
+ int waitedTime = 0;
+ long timeoutInMs = duration.toMillis();
+ while (waitedTime <= timeoutInMs) {
+ Thread.sleep(waitTime);
+ if (condition.getAsBoolean()) {
+ return;
+ }
+ waitedTime += waitTime;
+ }
+ fail("Waited " + duration.getSeconds() + " second(s), condition never got true");
+ }
+
+ @FunctionalInterface
+ interface CallableBooleanSupplier {
+ boolean getAsBoolean() throws Exception;
+ }
+
+ static class StreamTestInfrastructureExtension
+ implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback {
+
+ private static final ExtensionContext.Namespace NAMESPACE =
+ ExtensionContext.Namespace.create(StreamTestInfrastructureExtension.class);
+
+ private static ExtensionContext.Store store(ExtensionContext extensionContext) {
+ return extensionContext.getRoot().getStore(NAMESPACE);
+ }
+
+ private static EventLoopGroup eventLoopGroup(ExtensionContext context) {
+ return (EventLoopGroup) store(context).get("nettyEventLoopGroup");
+ }
+
+ @Override
+ public void beforeAll(ExtensionContext context) {
+ store(context).put("nettyEventLoopGroup", new NioEventLoopGroup());
+ }
+
+ @Override
+ public void beforeEach(ExtensionContext context) throws Exception {
+ try {
+ Field streamField =
+ context.getTestInstance().get().getClass().getDeclaredField("eventLoopGroup");
+ streamField.setAccessible(true);
+ streamField.set(context.getTestInstance().get(), eventLoopGroup(context));
+ } catch (NoSuchFieldException e) {
+
+ }
+ try {
+ Field streamField = context.getTestInstance().get().getClass().getDeclaredField("stream");
+ streamField.setAccessible(true);
+ String stream = streamName(context);
+ streamField.set(context.getTestInstance().get(), stream);
+ Client client =
+ new Client(
+ new Client.ClientParameters()
+ .eventLoopGroup(eventLoopGroup(context))
+ .port(streamPort()));
+ Client.Response response = client.create(stream);
+ assertThat(response.isOk()).isTrue();
+ client.close();
+ store(context).put("testMethodStream", stream);
+ } catch (NoSuchFieldException e) {
+
+ }
+
+ for (Field declaredField : context.getTestInstance().get().getClass().getDeclaredFields()) {
+ if (declaredField.getType().equals(ClientFactory.class)) {
+ declaredField.setAccessible(true);
+ ClientFactory clientFactory = new ClientFactory(eventLoopGroup(context));
+ declaredField.set(context.getTestInstance().get(), clientFactory);
+ store(context).put("testClientFactory", clientFactory);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void afterEach(ExtensionContext context) throws Exception {
+ try {
+ Field streamField = context.getTestInstance().get().getClass().getDeclaredField("stream");
+ streamField.setAccessible(true);
+ String stream = (String) streamField.get(context.getTestInstance().get());
+ Client client =
+ new Client(
+ new Client.ClientParameters()
+ .eventLoopGroup(eventLoopGroup(context))
+ .port(streamPort()));
+ Client.Response response = client.delete(stream);
+ assertThat(response.isOk()).isTrue();
+ client.close();
+ store(context).remove("testMethodStream");
+ } catch (NoSuchFieldException e) {
+
+ }
+
+ ClientFactory clientFactory = (ClientFactory) store(context).get("testClientFactory");
+ if (clientFactory != null) {
+ clientFactory.close();
+ }
+ }
+
+ @Override
+ public void afterAll(ExtensionContext context) throws Exception {
+ EventLoopGroup eventLoopGroup = eventLoopGroup(context);
+ eventLoopGroup.shutdownGracefully(1, 10, SECONDS).get(10, SECONDS);
+ }
+ }
+
+ static String streamName(TestInfo info) {
+ return streamName(info.getTestClass().get(), info.getTestMethod().get());
+ }
+
+ private static String streamName(ExtensionContext context) {
+ return streamName(context.getTestInstance().get().getClass(), context.getTestMethod().get());
+ }
+
+ private static String streamName(Class<?> testClass, Method testMethod) {
+ String uuid = UUID.randomUUID().toString();
+ return String.format(
+ "%s_%s%s",
+ testClass.getSimpleName(), testMethod.getName(), uuid.substring(uuid.length() / 2));
+ }
+
+ static class ClientFactory {
+
+ private final EventLoopGroup eventLoopGroup;
+ private final Set<Client> clients = ConcurrentHashMap.newKeySet();
+
+ public ClientFactory(EventLoopGroup eventLoopGroup) {
+ this.eventLoopGroup = eventLoopGroup;
+ }
+
+ public Client get() {
+ return get(new Client.ClientParameters());
+ }
+
+ public Client get(Client.ClientParameters parameters) {
+ Client client = new Client(parameters.eventLoopGroup(eventLoopGroup).port(streamPort()));
+ clients.add(client);
+ return client;
+ }
+
+ private void close() {
+ for (Client c : clients) {
+ c.close();
+ }
+ }
+ }
+}
diff --git a/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/resources/logback-test.xml b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..45d598991d
--- /dev/null
+++ b/deps/rabbitmq_stream_prometheus/test/prometheus_http_SUITE_data/src/test/resources/logback-test.xml
@@ -0,0 +1,13 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="com.rabbitmq.stream" level="info" />
+
+ <root level="info">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration> \ No newline at end of file