Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test Cases for JMX -> Prom Exporter Regexps #14155

Merged
merged 47 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
86c32bc
Test cases for Server Metrics
suddendust Oct 3, 2024
bde0d23
Merge branch 'master' of github.com:apache/pinot into jmx_prom_metric…
suddendust Oct 3, 2024
51127e2
Removed hardcoded metrics
suddendust Oct 4, 2024
417a8a6
WIP
suddendust Oct 4, 2024
f85d7c8
WIP
suddendust Oct 4, 2024
af4a3d2
controllerMeterTest working
suddendust Oct 5, 2024
1f58846
WIP
suddendust Oct 6, 2024
836db84
WIP
suddendust Oct 13, 2024
d938a47
WIP
suddendust Oct 14, 2024
18f23e1
Finalise BrokerJMXToPromMetricsTest.java
suddendust Oct 14, 2024
4436fe6
WIP
suddendust Oct 14, 2024
4d2d7e1
WIP
suddendust Oct 15, 2024
37462ac
Controller gauge test
suddendust Oct 15, 2024
ea7b328
WIP
suddendust Oct 15, 2024
01d2aee
WIP
suddendust Oct 15, 2024
04e7c8e
Agent working
suddendust Oct 15, 2024
d8f11b9
WIP
suddendust Oct 16, 2024
d581be8
All test cases working
suddendust Oct 16, 2024
1b69b17
WIP
suddendust Oct 16, 2024
10c4831
Added MinionJMXToPromMetricsTest.java
suddendust Oct 16, 2024
759ec6c
Refactor
suddendust Oct 17, 2024
1bbfd75
Addressed comments
suddendust Oct 17, 2024
5b4e091
Rollback inadvertent changes
suddendust Oct 17, 2024
4b4a94d
Added a comment
suddendust Oct 17, 2024
e057f79
Add comment
suddendust Oct 17, 2024
4b756e0
Remove dependency
suddendust Oct 17, 2024
c0047a6
Address comments
suddendust Oct 18, 2024
7d1e854
WIP
suddendust Oct 18, 2024
a300a34
WIP
suddendust Oct 20, 2024
6dc98d8
WIP
suddendust Oct 20, 2024
1f20b20
WIP
suddendust Oct 20, 2024
eff9b92
WIP
suddendust Oct 20, 2024
6fdd037
WIP
suddendust Oct 20, 2024
0c460ec
Addressed comments
suddendust Oct 20, 2024
a62a113
Rearrange code
suddendust Oct 21, 2024
f17c4d1
Merge branch 'master' of https://github.com/apache/pinot into jmx_pro…
suddendust Oct 21, 2024
2daac0b
Separate tests for Yammer and Dropwizard metrics factory
suddendust Oct 22, 2024
5489639
Addressed comments
suddendust Oct 22, 2024
069962c
Added license header
suddendust Oct 22, 2024
52f23c2
Added license header
suddendust Oct 22, 2024
ee602cc
Skip dropwizard tests in maven
suddendust Oct 22, 2024
f3064f5
Remove `pinotMetricsFactory` from test config
suddendust Oct 22, 2024
4264af3
Remove testConfig.json
suddendust Oct 22, 2024
a9354eb
Remove inadvertent changes
suddendust Oct 22, 2024
46899f3
Remove testConfig.json
suddendust Oct 22, 2024
b25b665
License
suddendust Oct 22, 2024
2fcd382
Rename method from getConfigParentDir -> getConfigFile
suddendust Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ rules:
- pattern: "\"org\\.apache\\.pinot\\.common\\.metrics\"<type=\"ServerMetrics\", name=\"pinot\\.server\\.realtimeConsumptionExceptions\"><>(\\w+)"
name: "pinot_server_realtime_consumptionExceptions_$1"
cache: true
- pattern: "\"org\\.apache\\.pinot\\.common\\.metrics\"<type=\"ServerMetrics\", name=\"pinot\\.server\\.(([^.]+)\\.)?([^.]*)_(OFFLINE|REALTIME)\\-(.+)\\-(\\w+)\\.(invalidRealtimeRowsDropped|incompleteRealtimeRowsConsumed|rowsWithErrors|realtimeRowsFiltered|realtimeRowsConsumed|realtimeRowsFetched|streamConsumerCreateExceptions)\"><>(\\w+)"
- pattern: "\"org\\.apache\\.pinot\\.common\\.metrics\"<type=\"ServerMetrics\", name=\"pinot\\.server\\.(([^.]+)\\.)?([^.]*)_(OFFLINE|REALTIME)\\-(.+)\\-(\\w+)\\.(invalidRealtimeRowsDropped|incompleteRealtimeRowsConsumed|rowsWithErrors|realtimeRowsFiltered|realtimeRowsConsumed|realtimeRowsFetched|streamConsumerCreateExceptions|realtimeRowsSanitized)\"><>(\\w+)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we changing the config as part of the test PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I'll rollback this. It's just that certain metrics aren't getting exported right now -> So I'll have to create filters for these metrics in code now which I wanted to avoid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is caught by the tests, that is a good sign that the tests are working as expected. I think it is okay to have them in the same PR. Let's add the missing ones in the PR description

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it in the description

name: "pinot_server_$7_$8"
cache: true
labels:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/**
* 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.
*/

package org.apache.pinot.common.metrics;

import com.google.common.base.Objects;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.pinot.common.utils.SimpleHttpResponse;
import org.apache.pinot.common.utils.http.HttpClient;
import org.apache.pinot.spi.config.table.TableType;
import org.apache.pinot.spi.utils.builder.TableNameBuilder;
import org.testng.Assert;


public class PinotJMXToPromMetricsTest {

protected HttpClient _httpClient;

protected static final List<String> METER_TYPES =
List.of("Count", "FiveMinuteRate", "MeanRate", "OneMinuteRate", "FifteenMinuteRate");

protected static final List<String> TIMER_TYPES =
List.of("Count", "FiveMinuteRate", "Max", "999thPercentile", "95thPercentile", "75thPercentile", "98thPercentile",
"OneMinuteRate", "50thPercentile", "99thPercentile", "FifteenMinuteRate", "Mean", "StdDev", "MeanRate",
"Min");

protected static final String RAW_TABLE_NAME = "myTable";
protected static final String TABLE_NAME_WITH_TYPE =
TableNameBuilder.forType(TableType.REALTIME).tableNameWithType(RAW_TABLE_NAME);

protected static final String KAFKA_TOPIC = "myTopic";
protected static final String PARTITION_GROUP_ID = "partitionGroupId";
protected static final String CLIENT_ID =
String.format("%s-%s-%s", TABLE_NAME_WITH_TYPE, KAFKA_TOPIC, PARTITION_GROUP_ID);
protected static final String TABLE_STREAM_NAME = String.format("%s_%s", TABLE_NAME_WITH_TYPE, KAFKA_TOPIC);

protected static final List<String> EXPORTED_LABELS_FOR_TABLE_NAME_TABLE_TYPE =
List.of("table", "myTable", "tableType", "REALTIME");

protected static final List<String> EXPORTED_LABELS_FOR_CLIENT_ID =
List.of("partition", PARTITION_GROUP_ID, "table", RAW_TABLE_NAME, "tableType", TableType.REALTIME.toString(),
"topic", KAFKA_TOPIC);

protected void assertGaugeExportedCorrectly(String exportedGaugePrefix, String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
Assert.assertTrue(promMetrics.contains(
ServerJMXToPromMetricsTest.PromMetric.withName(exportedMetricPrefix + exportedGaugePrefix + "_" + "Value")));
}

protected void assertGaugeExportedCorrectly(String exportedGaugePrefix, List<String> labels,
String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
Assert.assertTrue(promMetrics.contains(ServerJMXToPromMetricsTest.PromMetric.withNameAndLabels(
exportedMetricPrefix + exportedGaugePrefix + "_" + "Value", labels)));
}

protected void assertTimerExportedCorrectly(String exportedTimerPrefix, String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
for (String meterType : TIMER_TYPES) {
Assert.assertTrue(promMetrics.contains(ServerJMXToPromMetricsTest.PromMetric.withName(
exportedMetricPrefix + exportedTimerPrefix + "_" + meterType)));
}
}

protected void assertTimerExportedCorrectly(String exportedTimerPrefix, List<String> labels,
String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
for (String meterType : METER_TYPES) {
Assert.assertTrue(promMetrics.contains(ServerJMXToPromMetricsTest.PromMetric.withNameAndLabels(
exportedMetricPrefix + exportedTimerPrefix + "_" + meterType, labels)));
}
}

protected void assertMeterExportedCorrectly(String exportedMeterPrefix, String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
for (String meterType : METER_TYPES) {
Assert.assertTrue(promMetrics.contains(ServerJMXToPromMetricsTest.PromMetric.withName(
exportedMetricPrefix + exportedMeterPrefix + "_" + meterType)));
}
}

protected void assertMeterExportedCorrectly(String exportedMeterPrefix, List<String> labels,
String exportedMetricPrefix)
throws IOException, URISyntaxException {
List<ServerJMXToPromMetricsTest.PromMetric> promMetrics =
parseExportedPromMetrics(getExportedPromMetrics().getResponse());
for (String meterType : METER_TYPES) {
Assert.assertTrue(promMetrics.contains(ServerJMXToPromMetricsTest.PromMetric.withNameAndLabels(
exportedMetricPrefix + exportedMeterPrefix + "_" + meterType, labels)));
}
}

protected List<ServerJMXToPromMetricsTest.PromMetric> parseExportedPromMetrics(String response)
throws IOException {

List<ServerJMXToPromMetricsTest.PromMetric> exportedPromMetrics = new ArrayList<>();

BufferedReader reader = new BufferedReader(new StringReader(response));
gortiz marked this conversation as resolved.
Show resolved Hide resolved

String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("pinot_")) {
exportedPromMetrics.add(ServerJMXToPromMetricsTest.PromMetric.fromExportedMetric(line));
}
}
reader.close();
return exportedPromMetrics;
}

protected SimpleHttpResponse getExportedPromMetrics()
throws IOException, URISyntaxException {
return _httpClient.sendGetRequest(new URI("http://localhost:9021/metrics"));
}

public static class PromMetric {
gortiz marked this conversation as resolved.
Show resolved Hide resolved
private final String _metricName;
private final Map<String, String> _labels;

public String getMetricName() {
return _metricName;
}

public Map<String, String> getLabels() {
return _labels;
}

private PromMetric(String metricName, Map<String, String> labels) {
_metricName = metricName;
_labels = labels;
}

public static PromMetric fromExportedMetric(String exportedMetric) {
int spaceIndex = exportedMetric.indexOf(' ');
String metricWithoutVal = exportedMetric.substring(0, spaceIndex);
int braceIndex = metricWithoutVal.indexOf('{');

if (braceIndex != -1) {
String metricName = metricWithoutVal.substring(0, braceIndex);
String labelsString = metricWithoutVal.substring(braceIndex + 1, metricWithoutVal.lastIndexOf('}'));
Map<String, String> labels = parseLabels(labelsString);
return new PromMetric(metricName, labels);
} else {
return new PromMetric(metricWithoutVal, new LinkedHashMap<>());
}
}

private static Map<String, String> parseLabels(String labelsString) {
return labelsString.isEmpty() ? new LinkedHashMap<>()
: java.util.Arrays.stream(labelsString.split(",")).map(kvPair -> kvPair.split("="))
.collect(Collectors.toMap(kv -> kv[0], kv -> removeQuotes(kv[1]), (v1, v2) -> v2, LinkedHashMap::new));
}

private static String removeQuotes(String value) {
return value.startsWith("\"") ? value.substring(1, value.length() - 1) : value;
}

public static PromMetric withName(String metricName) {
return new PromMetric(metricName, new LinkedHashMap<>());
}

public static PromMetric withNameAndLabels(String metricName, List<String> labels) {
Map<String, String> labelMap = new LinkedHashMap<>();
for (int i = 0; i < labels.size(); i += 2) {
labelMap.put(labels.get(i), labels.get(i + 1));
}
return new PromMetric(metricName, labelMap);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PromMetric that = (PromMetric) o;
return Objects.equal(_metricName, that._metricName) && Objects.equal(_labels, that._labels);
}

@Override
public int hashCode() {
return Objects.hashCode(_metricName, _labels);
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder(_metricName);
if (!_labels.isEmpty()) {
sb.append('{');
sb.append(_labels.entrySet().stream().map(e -> e.getKey() + "=\"" + e.getValue() + "\"")
.collect(Collectors.joining(",")));
sb.append('}');
}
return sb.toString();
}
}
}
Loading
Loading