SIRONA-57 Bad timestamp unit for Graphite push
git-svn-id: https://svn.apache.org/repos/asf/incubator/sirona/trunk@1720105 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteCounterDataStore.java b/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteCounterDataStore.java
index cf48650..71dbc2f 100755
--- a/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteCounterDataStore.java
+++ b/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteCounterDataStore.java
@@ -40,7 +40,8 @@
try {
graphite.open();
- final long ts = System.currentTimeMillis();
+ // timestamp is the unix epoch time in seconds NOT ms.
+ final long ts = System.currentTimeMillis() / 1000l;
for (final Counter counter : instances) {
final Counter.Key key = counter.getKey();
diff --git a/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteGaugeDataStore.java b/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteGaugeDataStore.java
index cd1e5c4..821cad1 100755
--- a/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteGaugeDataStore.java
+++ b/agent/store/graphite/src/main/java/org/apache/sirona/graphite/GraphiteGaugeDataStore.java
@@ -38,7 +38,8 @@
try {
graphite.open();
- final long ts = System.currentTimeMillis();
+ // timestamp is the unix epoch time in seconds NOT ms.
+ final long ts = System.currentTimeMillis() / 1000l;
for (final Map.Entry<Role, Value> gauge : gauges.entrySet()) {
graphite.push(GAUGE_PREFIX + gauge.getKey().getName(), gauge.getValue().getMean(), ts);
diff --git a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTest.java b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTest.java
index 54ccd5f..bf3e3d2 100644
--- a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTest.java
+++ b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTest.java
@@ -23,8 +23,10 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class GraphiteTest extends GraphiteTestBase {
@@ -42,9 +44,9 @@
}
{ // counters
- final Collection<String> counters = extract(extract(messages(), "counter"), "counter"); // don't keep values
+ final Collection<String> counters = extract(messages(), "(counter-performances-test-[a-zA-Z]+) .+ [0-9]+"); // don't keep values
- assertTrue(counters.size() >= 30);
+ assertTrue(String.valueOf(counters.size()), counters.size() >= 30);
assertTrue(counters.contains("counter-performances-test-Hits"));
assertTrue(counters.contains("counter-performances-test-Max"));
assertTrue(counters.contains("counter-performances-test-Mean"));
@@ -57,7 +59,7 @@
{ // gauges
Thread.sleep(450);
- final Collection<String> gauges = extract(messages(), "gauge");
+ final Collection<String> gauges = extract(messages(), "(gauge-mock [0-9.]+) [0-9]+");
assertTrue(gauges.size() >= 3);
@@ -69,11 +71,59 @@
}
}
- private static Collection<String> extract(final Collection<String> messages, final String prefix) {
+ // The graphite protocol uses Unix Timestamp which is the number or seconds since epoc
+ // In Java System.currentTimeMillis() is the number of milliseconds since epoc.
+ // test case to reproduce the Unix Timestamp issue
+ // It sends 2 events in the same second and verifies they have the same timestamp.
+ @Test
+ public void issueUnixTimestampEpoc() throws InterruptedException {
+ final Counter counter = Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, "UnixTimestamp"));
+ counter.add(2.4);
+ counter.add(2.9);
+
+ // wait a bit so the that we can send more than once the data to the graphite server
+ // wait less than a second obviously
+ Thread.sleep(600);
+
+ {
+ final Collection<String> counters = extract(messages(), "counter-performances-UnixTimestamp-Hits [0-9.]+ ([0-9]+)"); // don't keep values
+ validateTimestamp(counters, 1);
+ }
+
+ {
+ final Collection<String> counters = extract(messages(), "gauge-mock [0-9.]+ ([0-9]+)"); // don't keep values
+ validateTimestamp(counters, 5);
+ }
+ }
+
+ private void validateTimestamp(final Collection<String> counters, final int delta) {
+ assertTrue(counters.size() > 0);
+ final Iterator<String> iterator = counters.iterator();
+ String val = null;
+ while (iterator.hasNext()) {
+ final String next = iterator.next();
+ if (val == null) {
+ val = next;
+ }
+ // allow one second difference cause we might switch to the following second in the middle
+ // with milliseconds 1ms never succeeds
+ assertTrue(Integer.parseInt(next) - Integer.parseInt(val) <= delta);
+ }
+ }
+
+ private static Collection<String> extract(final Collection<String> messages, final String regexp) {
+ final Pattern pattern = Pattern.compile(regexp);
final Collection<String> list = new ArrayList<String>(messages.size());
for (final String msg : messages) {
- if (msg.startsWith(prefix)) {
- list.add(msg.substring(0, msg.lastIndexOf(" ")));
+ final Matcher matcher = pattern.matcher(msg);
+ if (matcher.matches()) {
+ if (matcher.groupCount() != 1) {
+ throw new IllegalArgumentException("Can only capture 1 group. Current count is " + matcher.groupCount());
+ }
+
+ list.add(matcher.group(1));
+// } else {
+// System.out.println(msg + " does not match pattern " + regexp);
}
}
return list;
diff --git a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTestBase.java b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTestBase.java
index 8cbd7f3..d93518f 100644
--- a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTestBase.java
+++ b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/GraphiteTestBase.java
@@ -21,7 +21,9 @@
import org.apache.sirona.graphite.server.GraphiteMockServer;
import org.apache.sirona.repositories.Repository;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import java.io.IOException;
import java.util.Collection;
@@ -31,23 +33,29 @@
private Gauge.LoaderHelper gauges;
@Before
- public void startGraphite() throws IOException {
+ public void startGraphite() throws IOException, InterruptedException {
server = new GraphiteMockServer(Integer.getInteger("collector.server.port", 1234)).start();
if (System.getProperty("org.apache.sirona.graphite.GraphiteBuilder.port", "").isEmpty()) {
System.setProperty("org.apache.sirona.graphite.GraphiteBuilder.port", Integer.toString(server.getPort()));
}
+ Thread.sleep(200); // make sure it gets time to restart between tests
+ server.clear();
Repository.INSTANCE.clearCounters();
gauges = new Gauge.LoaderHelper(false);
}
@After
public void shutdownGraphite() throws IOException {
- IoCs.shutdown();
gauges.destroy();
server.stop();
Repository.INSTANCE.clearCounters();
}
+ @AfterClass
+ public static void shutdownSirona() throws IOException {
+ IoCs.shutdown();
+ }
+
protected Collection<String> messages() {
return server.getMessages();
}
diff --git a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/server/GraphiteMockServer.java b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/server/GraphiteMockServer.java
index c1290a4..d8482ac 100644
--- a/agent/store/graphite/src/test/java/org/apache/sirona/graphite/server/GraphiteMockServer.java
+++ b/agent/store/graphite/src/test/java/org/apache/sirona/graphite/server/GraphiteMockServer.java
@@ -22,7 +22,6 @@
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -60,6 +59,10 @@
return messages;
}
+ public void clear() {
+ messages.clear();
+ }
+
private static class GraphiteThread extends Thread {
private final Collection<String> messages;
diff --git a/agent/store/graphite/src/test/resources/sirona.properties b/agent/store/graphite/src/test/resources/sirona.properties
index 744d19d..54838be 100644
--- a/agent/store/graphite/src/test/resources/sirona.properties
+++ b/agent/store/graphite/src/test/resources/sirona.properties
@@ -16,7 +16,7 @@
# under the License.
org.apache.sirona.store.DataStoreFactory = org.apache.sirona.graphite.GraphiteDataStoreFactory
-org.apache.sirona.graphite.aggregated.gauge.period = 220
+org.apache.sirona.graphite.aggregated.gauge.period = 200
org.apache.sirona.graphite.period = 125
org.apache.sirona.graphite.GraphiteBuilder.address = localhost