Skip to content

Commit

Permalink
NMS-16271: Do not persist NaN values
Browse files Browse the repository at this point in the history
  • Loading branch information
christianpape authored Feb 8, 2024
1 parent 3cdfa98 commit d48dd71
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
10 changes: 8 additions & 2 deletions plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,22 @@
<version>${opennms.api.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.15.2</version>
<version>1.15.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.5.0</version>
<version>5.8.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public void store(final List<Sample> samples) throws StorageException {

public void store(final List<Sample> samples, String clientID) throws StorageException {
final List<Sample> samplesSorted = samples.stream() // Cortex doesn't like the Samples to be out of time order
.filter(sample -> !sample.getValue().isNaN())
.sorted(Comparator.comparing(Sample::getTime))
.collect(Collectors.toList());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package org.opennms.timeseries.cortex;

import java.io.File;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

import org.awaitility.Awaitility;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.opennms.integration.api.v1.timeseries.Aggregation;
import org.opennms.integration.api.v1.timeseries.Metric;
import org.opennms.integration.api.v1.timeseries.Sample;
import org.opennms.integration.api.v1.timeseries.TimeSeriesFetchRequest;
import org.opennms.integration.api.v1.timeseries.TimeSeriesStorage;
import org.opennms.integration.api.v1.timeseries.immutables.ImmutableMetric;
import org.opennms.integration.api.v1.timeseries.immutables.ImmutableSample;
import org.opennms.integration.api.v1.timeseries.immutables.ImmutableTimeSeriesFetchRequest;
import org.testcontainers.containers.DockerComposeContainer;
import org.testcontainers.containers.wait.strategy.Wait;

public class NMS16271_IT {
@ClassRule
public static DockerComposeContainer<?> environment = new DockerComposeContainer<>(new File("src/test/resources/org/opennms/timeseries/cortex/docker-compose.yaml"))
.withExposedService("cortex", 9009, Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(10)))
.withExposedService("grafana", 3000, Wait.forListeningPort().withStartupTimeout(Duration.ofSeconds(10)));

@Test
public void myTest() throws Exception {
final TimeSeriesStorage storage = new CortexTSS(new CortexTSSConfig(), new KVStoreMock());
final Instant referenceTime = Instant.now().with(ChronoField.MICRO_OF_SECOND, 0L);

final Metric metric = ImmutableMetric.builder()
.intrinsicTag("name", "name")
.metaTag("mtype", Metric.Mtype.gauge.name())
.build();

final List<Sample> samplesIn = new ArrayList<>();

// add samples including some NaN values
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(7, ChronoUnit.SECONDS)).value(42.3).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(6, ChronoUnit.SECONDS)).value(Double.NaN).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(5, ChronoUnit.SECONDS)).value(42.3).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(4, ChronoUnit.SECONDS)).value(Double.NaN).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(3, ChronoUnit.SECONDS)).value(42.3).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(2, ChronoUnit.SECONDS)).value(Double.NaN).metric(metric).build());
samplesIn.add(ImmutableSample.builder().time(referenceTime.plus(1, ChronoUnit.SECONDS)).value(42.3).metric(metric).build());
Assert.assertTrue(samplesIn.stream().anyMatch(s -> s.getValue().isNaN()));

// store the samples
storage.store(samplesIn);

final TimeSeriesFetchRequest request = ImmutableTimeSeriesFetchRequest.builder().start(referenceTime).end(referenceTime.plusSeconds(10)).metric(metric).aggregation(Aggregation.NONE).step(Duration.of(1, ChronoUnit.SECONDS)).build();

// wait till ten samples are available
Awaitility.await()
.atLeast(Duration.of(1, ChronoUnit.SECONDS))
.atMost(Duration.of(10, ChronoUnit.SECONDS))
.with()
.pollInterval(Duration.of(1, ChronoUnit.SECONDS))
.until(() -> storage.getTimeseries(request).size() == 10);

// retrieve the samples
final List<Sample> samplesOut = storage.getTimeseries(request);
// ten samples available?
Assert.assertTrue(samplesOut.size() == 10);
// all values are 42.3, no NaN
Assert.assertFalse(samplesOut.stream().anyMatch(s->!Double.valueOf(42.3).equals(s.getValue())));
}
}

0 comments on commit d48dd71

Please sign in to comment.