Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class RandomizedTimeSeriesIT extends AbstractEsqlIntegTestCase {
private static final Long TIME_RANGE_SECONDS = 3600L;
private static final String DATASTREAM_NAME = "tsit_ds";
private static final Integer SECONDS_IN_WINDOW = 60;
private List<XContentBuilder> documents = null;
private List<XContentBuilder> documents;
private TSDataGenerationHelper dataGenerationHelper;

List<List<Object>> consumeRows(EsqlQueryResponse resp) {
Expand Down Expand Up @@ -208,7 +208,21 @@ protected Collection<Class<? extends Plugin>> nodePlugins() {
record RateRange(Double lower, Double upper) implements Comparable<RateRange> {
@Override
public int compareTo(RateRange o) {
return this.lower.compareTo(o.lower);
// Compare first by lower bound, then by upper bound
int cmp = this.lower.compareTo(o.lower);
if (cmp == 0) {
return this.upper.compareTo(o.upper);
}
return cmp;
}

public int compareToFindingMax(RateRange o) {
// Compare first by upper bound, then by lower bound
int cmp = this.upper.compareTo(o.upper);
if (cmp == 0) {
return this.lower.compareTo(o.lower);
}
return cmp;
}
}

Expand Down Expand Up @@ -248,16 +262,16 @@ static RateStats calculateRateAggregation(
}
// TODO: Remove tolerances since we are already allowing a min-max range
return new RateRange(
counterGrowth / secondsInWindow * 0.95, // Add 5% tolerance to the lower bound
counterGrowth / (lastTs.toEpochMilli() / 1000 - firstTs.toEpochMilli() / 1000) * 1.2 // Add 20% tolerance to the upper bound
counterGrowth / secondsInWindow * 0.99, // Add 1% tolerance to the lower bound
1000.0 * counterGrowth / (lastTs.toEpochMilli() - firstTs.toEpochMilli()) * 1.01 // Add 1% tolerance to the upper bound
);
}).filter(Objects::nonNull).toList();
if (allRates.isEmpty()) {
return new RateStats(0L, null, null, null, new RateRange(0.0, 0.0));
}
return new RateStats(
(long) allRates.size(),
allRates.stream().max(RateRange::compareTo).orElseThrow(),
allRates.stream().max(RateRange::compareToFindingMax).orElseThrow(),
new RateRange(
allRates.stream().mapToDouble(r -> r.lower).average().orElseThrow(),
allRates.stream().mapToDouble(r -> r.upper).average().orElseThrow()
Expand Down Expand Up @@ -319,7 +333,7 @@ void checkWithin(Double actual, RateRange expected) {

void assertNoFailedWindows(List<String> failedWindows, List<List<Object>> rows) {
// TODO: WE have a 15% tolerance for failed windows. Must remove.
if (failedWindows.size() < 0.15 * rows.size()) {
if (failedWindows.size() < 0.01 * rows.size()) {
logger.warn(
"Failed " + failedWindows.size() + " windows out of " + rows.size() + ", failures:\n" + String.join("\n", failedWindows)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,21 @@ private static Object randomDimensionValue(String dimensionName) {
// Making a list-to-set-to-list to ensure uniqueness.
this.numDocs = numDocs;
var maxAttributes = (int) Math.sqrt(numDocs);
attributesForMetrics = List.copyOf(
List<String> tempAttributeSet = List.copyOf(
Set.copyOf(ESTestCase.randomList(1, maxAttributes, () -> ESTestCase.randomAlphaOfLengthBetween(2, 30)))
);
var maxTimeSeries = (int) Math.sqrt(numDocs);
var minTimeSeries = Math.max(1, maxTimeSeries / 4);
numTimeSeries = ESTestCase.randomIntBetween(minTimeSeries, maxTimeSeries);
Set<String> usedAttributeNames = new HashSet<>();
// allTimeSeries contains the list of dimension-values for each time series.
List<List<Tuple<String, Object>>> allTimeSeries = IntStream.range(0, numTimeSeries).mapToObj(tsIdx -> {
List<String> dimensionsInMetric = ESTestCase.randomNonEmptySubsetOf(attributesForMetrics);
List<String> dimensionsInMetric = ESTestCase.randomNonEmptySubsetOf(tempAttributeSet);
// TODO: How do we handle the case when there are no dimensions? (i.e. regular randomSubsetof(...)
usedAttributeNames.addAll(dimensionsInMetric);
return dimensionsInMetric.stream().map(attr -> new Tuple<>(attr, randomDimensionValue(attr))).collect(Collectors.toList());
}).toList();
attributesForMetrics = List.copyOf(usedAttributeNames);

// We want to ensure that all documents have different timestamps.
var timeRangeMs = timeRangeSeconds * 1000;
Expand Down