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

Normalize metrics from measurements #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

nineinchnick
Copy link
Member

This PR extracts name and unit from measurements into another metrics table. Such metrics also have attributes, which allow the removal of prefixes and suffixes from metric names and make it easier to filter some metrics when building reports.

The denormalized measurement.name and measurement.unit columns are not removed, but the name format is changed from cluster-cpu_max to cpu {scope=cluster,aggregate=max}.

This change matches how other metric monitoring system stores data, using labels (Prometheus) or attributes (OpenTelemetry).

@cla-bot cla-bot bot added the cla-signed label Sep 14, 2022
@nineinchnick nineinchnick force-pushed the metric-attributes branch 3 times, most recently from 08b0527 to 12c9ec0 Compare September 14, 2022 08:25
@nineinchnick nineinchnick force-pushed the metric-attributes branch 2 times, most recently from 3a96397 to 337b6d8 Compare September 16, 2022 12:37
@nineinchnick
Copy link
Member Author

@przemekak @sopel39 @radek-starburst PTAL. There are breaking changes here but I tried to preserve some backward compatibility.

Copy link
Contributor

@radek-kondziolka radek-kondziolka left a comment

Choose a reason for hiding this comment

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

I like that change. I've added some comments and I think that before merge and release it we need to firstly make changes in our integrations.

@@ -89,11 +101,11 @@ public void testBenchmark()
@Test
public void testConcurrentBenchmark()
{
ImmutableList<String> concurrentQueryMeasurementName = ImmutableList.of("duration");
ImmutableList<String> concurrentBenchmarkMeasurementNames = ImmutableList.<String>builder()
List<Measurement> concurrentQueryMeasurement = ImmutableList.of(measurement("duration", "MILLISECONDS", 0.0, ImmutableMap.of("scope", "driver")));
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like a factory method. Maybe something like Measurement.of?

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, but I'd rather do this in a separate PR.

@@ -109,22 +145,21 @@ public boolean equals(Object o)
return false;
}
Measurement that = (Measurement) o;
return Objects.equals(name, that.name);
return metric.equals(that.metric);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why unit does not matter here? Hibernate strongly depends on correct equals / hashcode and it looks like two different object could be treated as same, od I miss something?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is why I switched to comparing metrics, to also account for the unit (and attributes). The name and unit properties that remain here are denormalized from the metric.

Measurement.measurement("prestoQuery-outputDataSize", "BYTES", 6900.0),
Measurement.measurement("prestoQuery-peakTotalMemoryReservation", "BYTES", 6800.0),
Measurement.measurement("prestoQuery-physicalWrittenDataSize", "BYTES", 462265065.0));
Measurement.measurement("analysisTime", "MILLISECONDS", 21.07, attributes),
Copy link
Member

Choose a reason for hiding this comment

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

this will break scripts (jupyther). I think it's fine, but needs to be announced

Copy link
Contributor

Choose a reason for hiding this comment

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

Not only scripts but our workflows as well.

Copy link
Member

Choose a reason for hiding this comment

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

You mean alerts?

@@ -150,8 +153,8 @@ private void addMeanMaxMeasurements(Map<String, double[]> loadedMetrics, List<Me
{
Optional<StatisticalSummary> statistics = getStats(loadedMetrics, metricName);
if (statistics.isPresent()) {
measurements.add(Measurement.measurement("cluster-" + metricName + "_max", unit, statistics.get().getMax()));
measurements.add(Measurement.measurement("cluster-" + metricName + "_mean", unit, statistics.get().getMean()));
measurements.add(Measurement.measurement(metricName, unit, statistics.get().getMax(), ImmutableMap.of("scope", "cluster", "aggregate", "max")));
Copy link
Member

Choose a reason for hiding this comment

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

METRIC_SCOPE instead of cluster?

@@ -150,8 +153,8 @@ private void addMeanMaxMeasurements(Map<String, double[]> loadedMetrics, List<Me
{
Optional<StatisticalSummary> statistics = getStats(loadedMetrics, metricName);
if (statistics.isPresent()) {
measurements.add(Measurement.measurement("cluster-" + metricName + "_max", unit, statistics.get().getMax()));
Copy link
Member

Choose a reason for hiding this comment

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

won't this make scripts harder, e.g: previously I could just select name in SQL query. Now I will have to join on attributes and do subquery. Seems complicated

@@ -123,7 +124,7 @@ private URI buildQueryInfoURI(String queryId)
private Measurement parseQueryStatistic(String name, Object statistic, Unit requiredUnit)
{
double value = UnitConverter.parseValueAsUnit(statistic.toString(), requiredUnit);
return measurement("prestoQuery-" + name, UnitConverter.format(requiredUnit), value);
return measurement(name, UnitConverter.format(requiredUnit), value, Collections.singletonMap("scope", "prestoQuery"));
Copy link
Member

Choose a reason for hiding this comment

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

prestoQuery -> query

@@ -33,7 +33,6 @@

Copy link
Member

Choose a reason for hiding this comment

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

please add description in commit message

"duration",
"MILLISECONDS",
measurable.getQueryDuration().toMillis(),
Collections.singletonMap("scope", "driver")));
Copy link
Member

Choose a reason for hiding this comment

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

use guava immutable collections (do we have guava as dependency?)

@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "metric_attributes", joinColumns = @JoinColumn(name = "metric_id"))
private Map<String, String> attributes = newHashMap();
Copy link
Member

Choose a reason for hiding this comment

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

This will probably make it harder to extract specific attributes for a measurement (min, max). This might be a problem when someone is writing a script.

Could we embed attributes somehow for a measurment?
It seems that measurement for a given type will have a fixed list of attributes, so maybe we don't need flexibility of extra metric_attributes table.

@@ -173,6 +173,8 @@ public void finishExecution(String uniqueName, String benchmarkSequenceId, Strin
private List<Measurement> normalizeMeasurements(List<FlatMeasurement> input)
{
// use a lookup map to avoid building a complex SQL query that compares attributes list
// acquire a lock to avoid adding multiple metrics with same name and same attributes
Copy link
Member

Choose a reason for hiding this comment

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

why would there be same metrics with same name and attributes created?

@sopel39
Copy link
Member

sopel39 commented Oct 4, 2022

@nineinchnick are you working on this? Is this required for benchmarking infra

@nineinchnick
Copy link
Member Author

@nineinchnick are you working on this? Is this required for benchmarking infra

I'm not, since it's not required. It would only make report queries a bit simpler, as it would have to parse metric names to split out prefixes.

Because this is a breaking change, I want to prepare responses to all the comments I got, but it's a low priority.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants