From 02fe3a59f28b6501bfcafc5e34577b95c432173f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 23 May 2017 13:38:00 +0200 Subject: [PATCH 01/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds --- src/main/java/org/influxdb/InfluxDB.java | 20 + .../java/org/influxdb/dto/BatchPoints.java | 41 +- src/main/java/org/influxdb/dto/Point.java | 20 + .../java/org/influxdb/impl/InfluxDBImpl.java | 35 +- src/test/java/org/influxdb/InfluxDBTest.java | 141 ++++ src/test/java/org/influxdb/dto/PointTest.java | 668 ++++++++++-------- 6 files changed, 635 insertions(+), 290 deletions(-) diff --git a/src/main/java/org/influxdb/InfluxDB.java b/src/main/java/org/influxdb/InfluxDB.java index 2d1793dfb..69c0dbb7c 100644 --- a/src/main/java/org/influxdb/InfluxDB.java +++ b/src/main/java/org/influxdb/InfluxDB.java @@ -183,6 +183,16 @@ public InfluxDB enableBatch(final int actions, final int flushDuration, final Ti public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final String records); + /** + * Write a set of Points to the influxdb database with the string records. + * + * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * + * @param records + */ + public void write(final String database, final String retentionPolicy, + final ConsistencyLevel consistency, final TimeUnit precision, final String records); + /** * Write a set of Points to the influxdb database with the list of string records. * @@ -193,6 +203,16 @@ public void write(final String database, final String retentionPolicy, public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final List records); + /** + * Write a set of Points to the influxdb database with the list of string records. + * + * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * + * @param records + */ + public void write(final String database, final String retentionPolicy, + final ConsistencyLevel consistency, final TimeUnit precision, final List records); + /** * Write a set of Points to the influxdb database with the string records through UDP. * diff --git a/src/main/java/org/influxdb/dto/BatchPoints.java b/src/main/java/org/influxdb/dto/BatchPoints.java index 0f39540d7..8886fea69 100644 --- a/src/main/java/org/influxdb/dto/BatchPoints.java +++ b/src/main/java/org/influxdb/dto/BatchPoints.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.TimeUnit; import org.influxdb.InfluxDB.ConsistencyLevel; @@ -27,6 +28,7 @@ public class BatchPoints { private Map tags; private List points; private ConsistencyLevel consistency; + private TimeUnit precision; BatchPoints() { // Only visible in the Builder @@ -52,6 +54,7 @@ public static final class Builder { private final Map tags = Maps.newTreeMap(Ordering.natural()); private final List points = Lists.newArrayList(); private ConsistencyLevel consistency; + private TimeUnit precision; /** * @param database @@ -118,6 +121,16 @@ public Builder consistency(final ConsistencyLevel consistencyLevel) { return this; } + /** + * Set the time precision to use for the whole batch. If unspecified, will default to {@link TimeUnit#NANOSECONDS} + * @param precision + * @return the Builder instance + */ + public Builder precision(final TimeUnit precision) { + this.precision = precision; + return this; + } + /** * Create a new BatchPoints instance. * @@ -138,6 +151,10 @@ public BatchPoints build() { this.consistency = ConsistencyLevel.ONE; } batchPoints.setConsistency(this.consistency); + if (null == this.precision) { + this.precision = TimeUnit.NANOSECONDS; + } + batchPoints.setPrecision(this.precision); return batchPoints; } } @@ -187,6 +204,20 @@ void setPoints(final List points) { this.points = points; } + /** + * @return the time precision unit + */ + public TimeUnit getPrecision() { + return precision; + } + + /** + * @param precision the time precision to set for the batch points + */ + public void setPrecision(TimeUnit precision) { + this.precision = precision; + } + /** * Add a single Point to these batches. * @@ -242,12 +273,13 @@ public boolean equals(final Object o) { && Objects.equals(retentionPolicy, that.retentionPolicy) && Objects.equals(tags, that.tags) && Objects.equals(points, that.points) - && consistency == that.consistency; + && consistency == that.consistency + && precision == that.precision; } @Override public int hashCode() { - return Objects.hash(database, retentionPolicy, tags, points, consistency); + return Objects.hash(database, retentionPolicy, tags, points, consistency, precision); } /** @@ -264,6 +296,8 @@ public String toString() { builder.append(this.consistency); builder.append(", tags="); builder.append(this.tags); + builder.append(", precision="); + builder.append(this.precision); builder.append(", points="); builder.append(this.points); builder.append("]"); @@ -278,8 +312,9 @@ public String toString() { */ public String lineProtocol() { StringBuilder sb = new StringBuilder(); + for (Point point : this.points) { - sb.append(point.lineProtocol()).append("\n"); + sb.append(point.lineProtocol(this.precision)).append("\n"); } return sb.toString(); } diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index 760a155ef..a19a18348 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -323,6 +323,20 @@ public String lineProtocol() { return sb.toString(); } + /** + * Calculate the lineprotocol entry for a single point, using a specific {@link TimeUnit} for the timestamp + * @param precision the time precision unit for this point + * @return the String without newLine + */ + public String lineProtocol(final TimeUnit precision) { + final StringBuilder sb = new StringBuilder(); + sb.append(KEY_ESCAPER.escape(this.measurement)); + sb.append(concatenatedTags()); + sb.append(concatenateFields()); + sb.append(formatedTime(precision)); + return sb.toString(); + } + private StringBuilder concatenatedTags() { final StringBuilder sb = new StringBuilder(); for (Entry tag : this.tags.entrySet()) { @@ -380,4 +394,10 @@ private StringBuilder formatedTime() { return sb; } + private StringBuilder formatedTime(TimeUnit precision) { + final StringBuilder sb = new StringBuilder(); + sb.append(" ").append(precision.convert(this.time, this.precision)); + return sb; + } + } diff --git a/src/main/java/org/influxdb/impl/InfluxDBImpl.java b/src/main/java/org/influxdb/impl/InfluxDBImpl.java index 293909fcb..dd3718618 100644 --- a/src/main/java/org/influxdb/impl/InfluxDBImpl.java +++ b/src/main/java/org/influxdb/impl/InfluxDBImpl.java @@ -259,31 +259,46 @@ public void write(final BatchPoints batchPoints) { this.password, batchPoints.getDatabase(), batchPoints.getRetentionPolicy(), - TimeUtil.toTimePrecision(TimeUnit.NANOSECONDS), + TimeUtil.toTimePrecision(batchPoints.getPrecision()), batchPoints.getConsistency().value(), lineProtocol)); } + + @Override + public void write(String database, String retentionPolicy, ConsistencyLevel consistency, + TimeUnit precision, String records) { + execute(this.influxDBService.writePoints( + this.username, + this.password, + database, + retentionPolicy, + TimeUtil.toTimePrecision(precision), + consistency.value(), + RequestBody.create(MEDIA_TYPE_STRING, records))); + } + @Override public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final String records) { - execute(this.influxDBService.writePoints( - this.username, - this.password, - database, - retentionPolicy, - TimeUtil.toTimePrecision(TimeUnit.NANOSECONDS), - consistency.value(), - RequestBody.create(MEDIA_TYPE_STRING, records))); + write(database, retentionPolicy, consistency, TimeUnit.NANOSECONDS, records); } @Override public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final List records) { + write(database, retentionPolicy, consistency, TimeUnit.NANOSECONDS, records); + } + + + @Override + public void write(String database, String retentionPolicy, ConsistencyLevel consistency, + TimeUnit precision, List records) { final String joinedRecords = Joiner.on("\n").join(records); - write(database, retentionPolicy, consistency, joinedRecords); + write(database, retentionPolicy, consistency, precision, joinedRecords); } + /** * {@inheritDoc} */ diff --git a/src/test/java/org/influxdb/InfluxDBTest.java b/src/test/java/org/influxdb/InfluxDBTest.java index 132df79ac..44623b3b6 100644 --- a/src/test/java/org/influxdb/InfluxDBTest.java +++ b/src/test/java/org/influxdb/InfluxDBTest.java @@ -1,5 +1,7 @@ package org.influxdb; +import static org.assertj.core.api.Assertions.assertThat; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -19,12 +21,14 @@ import org.influxdb.dto.Query; import org.influxdb.dto.QueryResult; import org.influxdb.impl.InfluxDBImpl; +import org.influxdb.impl.TimeUtil; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import com.google.common.collect.Lists; import com.google.common.util.concurrent.Uninterruptibles; /** @@ -348,6 +352,143 @@ public void testWriteMultipleStringDataLines() { this.influxDB.deleteDatabase(dbName); } + /** + * Tests writing points using the time precision feature + * @throws Exception + */ + @Test + public void testWriteBatchWithPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a batch of points using second precision + Point p1 = Point + .measurement(measurement) + .addField("foo", 1d) + .tag("device", "one") + .time(1485273600, TimeUnit.SECONDS).build(); // 2017-01-27T16:00:00 + String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + Point p2 = Point + .measurement(measurement) + .addField("foo", 2d) + .tag("device", "two") + .time(1485277200, TimeUnit.SECONDS).build(); // 2017-01-27T17:00:00 + String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + Point p3 = Point + .measurement(measurement) + .addField("foo", 3d) + .tag("device", "three") + .time(1485280800, TimeUnit.SECONDS).build(); // 2017-01-27T18:00:00 + String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + + BatchPoints batchPoints = BatchPoints + .database(dbName) + .retentionPolicy(rp) + .precision(TimeUnit.SECONDS) + .points(p1, p2, p3) + .build(); + + // WHEN I write the batch + this.influxDB.write(batchPoints); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + + @Test + public void testWriteBatchWithoutPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a batch of points that has no specific precision + Point p1 = Point + .measurement(measurement) + .addField("foo", 1d) + .tag("device", "one") + .time(1485273600000000100L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T16:00:00.000000100Z + String timeP1 = "2017-01-27T16:00:00.000000100Z"; + Point p2 = Point + .measurement(measurement) + .addField("foo", 2d) + .tag("device", "two") + .time(1485277200000000200L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T17:00:00.000000200Z + String timeP2 = "2017-01-27T17:00:00.000000200Z"; + Point p3 = Point + .measurement(measurement) + .addField("foo", 3d) + .tag("device", "three") + .time(1485280800000000300L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T18:00:00.000000300Z + String timeP3 = "2017-01-27T18:00:00.000000300Z"; + + BatchPoints batchPoints = BatchPoints + .database(dbName) + .retentionPolicy(rp) + .points(p1, p2, p3) + .build(); + + // WHEN I write the batch + this.influxDB.write(batchPoints); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + + @Test + public void testWriteRecordsWithPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a set of records using second precision + List records = Lists.newArrayList(); + records.add("cpu,atag=test1 idle=100,usertime=10,system=1 1485273600"); + String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + + records.add("cpu,atag=test2 idle=200,usertime=20,system=2 1485277200"); + String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + + records.add("cpu,atag=test3 idle=300,usertime=30,system=3 1485280800"); + String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + + // WHEN I write the batch + this.influxDB.write(dbName, rp, null, TimeUnit.SECONDS, records); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + /** * Test that creating database which name is composed of numbers only works */ diff --git a/src/test/java/org/influxdb/dto/PointTest.java b/src/test/java/org/influxdb/dto/PointTest.java index 2801f5dab..ac9c45b4b 100644 --- a/src/test/java/org/influxdb/dto/PointTest.java +++ b/src/test/java/org/influxdb/dto/PointTest.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -17,284 +18,397 @@ * Test for the Point DTO. * * @author stefan.majer [at] gmail.com - * */ public class PointTest { - /** - * Test that lineprotocol is conformant to: - * - * https://github.com/influxdb/influxdb/blob/master/tsdb/README.md - * - */ - @Test - public void lineProtocol() { - Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1"); - - point = Point.measurement("test,1").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test\\,1 a=1.0 1"); - - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A").build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\" 1"); - - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A\"B").build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\" 1"); - - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A\"B\"C").build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\\\"C\" 1"); - - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A B C").build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A B C\" 1"); - - point = Point - .measurement("test") - .time(1, TimeUnit.NANOSECONDS) - .addField("a", "A\"B") - .addField("b", "D E \"F") - .build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\",b=\"D E \\\"F\" 1"); - - //Integer type - point = Point.measurement("inttest").time(1, TimeUnit.NANOSECONDS).addField("a", (Integer)1).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("inttest a=1i 1"); - - point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", (Integer)1).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=1i 1"); - - point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", 1L).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=1i 1"); - - point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", BigInteger.valueOf(100)).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=100i 1"); - } - - /** - * Test for ticket #44 - */ - @Test - public void testTicket44() { - Point point = Point.measurement("test").time(1, TimeUnit.MICROSECONDS).addField("a", 1.0).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1000"); - - point = Point.measurement("test").time(1, TimeUnit.MILLISECONDS).addField("a", 1.0).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1000000"); - - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); - BatchPoints batchPoints = BatchPoints.database("db").point(point).build(); - assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1\n"); - - point = Point.measurement("test").time(1, TimeUnit.MICROSECONDS).addField("a", 1.0).build(); - batchPoints = BatchPoints.database("db").point(point).build(); - assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000\n"); - - point = Point.measurement("test").time(1, TimeUnit.MILLISECONDS).addField("a", 1.0).build(); - batchPoints = BatchPoints.database("db").point(point).build(); - assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000000\n"); - - point = Point.measurement("test").addField("a", 1.0).time(1, TimeUnit.MILLISECONDS).build(); - batchPoints = BatchPoints.database("db").build(); - batchPoints = batchPoints.point(point); - assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000000\n"); - - } - - /** - * Test for ticket #54 - */ - @Test - public void testTicket54() { - Byte byteNumber = 100; - Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", byteNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100i 1"); - - int intNumber = 100000000; - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", intNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); - - Integer integerNumber = 100000000; - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", integerNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); - - AtomicInteger atomicIntegerNumber = new AtomicInteger(100000000); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", atomicIntegerNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); - - Long longNumber = 1000000000000000000L; - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", longNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1000000000000000000i 1"); - - AtomicLong atomicLongNumber = new AtomicLong(1000000000000000000L); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", atomicLongNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1000000000000000000i 1"); - - BigInteger bigIntegerNumber = BigInteger.valueOf(100000000); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", bigIntegerNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); - - Double doubleNumber = Double.valueOf(100000000.0001); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", doubleNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000.0001 1"); - - Float floatNumber = Float.valueOf(0.1f); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", floatNumber).build(); - assertThat(point.lineProtocol()).asString().startsWith("test a=0.10"); - - BigDecimal bigDecimalNumber = BigDecimal.valueOf(100000000.00000001); - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", bigDecimalNumber).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000.00000001 1"); - } - - @Test - public void testEscapingOfKeysAndValues() { - // Test escaping of spaces - Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar baz").addField( "a", 1.0 ).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\ baz a=1.0 1"); - - // Test escaping of commas - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar,baz").addField( "a", 1.0 ).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\,baz a=1.0 1"); - - // Test escaping of equals sign - point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar=baz").addField( "a", 1.0 ).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\=baz a=1.0 1"); - } - - @Test - public void testDeprecatedFieldMethodOnlyProducesFloatingPointValues() { - - Object[] ints = {(byte) 1, (short) 1, (int) 1, (long) 1, BigInteger.ONE}; - - for (Object intExample : ints) { - Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).field("a", intExample ).build(); - assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1"); - } - - } - /** - * Test for issue #117. - */ - @Test - public void testIgnoreNullPointerValue() { - // Test omission of null values - Point.Builder pointBuilder = Point.measurement("nulltest").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar"); - - pointBuilder.field("field1", "value1"); - pointBuilder.field("field2", (Number) null); - pointBuilder.field("field3", (Integer) 1); - - Point point = pointBuilder.build(); - - assertThat(point.lineProtocol()).asString().isEqualTo("nulltest,foo=bar field1=\"value1\",field3=1.0 1"); - } - - /** - * Tests for issue #110 - */ - @Test(expected = IllegalArgumentException.class) - public void testAddingTagsWithNullNameThrowsAnError() { - Point.measurement("dontcare").tag(null, "DontCare"); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddingTagsWithNullValueThrowsAnError() { - Point.measurement("dontcare").tag("DontCare", null); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddingMapOfTagsWithNullNameThrowsAnError() { - Map map = Maps.newHashMap(); - map.put(null, "DontCare"); - Point.measurement("dontcare").tag(map); - } - - @Test(expected = IllegalArgumentException.class) - public void testAddingMapOfTagsWithNullValueThrowsAnError() { - Map map = Maps.newHashMap(); - map.put("DontCare", null); - Point.measurement("dontcare").tag(map); - } - - @Test(expected = IllegalArgumentException.class) - public void testNullValueThrowsExceptionViaAddField() { - Point.measurement("dontcare").addField("field", (String) null); - } - - /** - * Tests for issue #266 - */ - @Test - public void testEquals() throws Exception { - // GIVEN two point objects with identical data - Map fields = Maps.newHashMap(); - fields.put("foo", "bar"); - - String measurement = "measurement"; - - TimeUnit precision = TimeUnit.NANOSECONDS; - - Map tags = Maps.newHashMap(); - tags.put("bar", "baz"); - - Long time = System.currentTimeMillis(); - - Point p1 = new Point(); - p1.setFields(fields); - p1.setMeasurement(measurement); - p1.setPrecision(precision); - p1.setTags(tags); - p1.setTime(time); - - Point p2 = new Point(); - p2.setFields(fields); - p2.setMeasurement(measurement); - p2.setPrecision(precision); - p2.setTags(tags); - p2.setTime(time); - - // WHEN I call equals on one with the other as arg - boolean equals = p1.equals(p2); - - // THEN equals returns true - assertThat(equals).isEqualTo(true); - } - - @Test - public void testUnEquals() throws Exception { - // GIVEN two point objects with different data - Map fields1 = Maps.newHashMap(); - fields1.put("foo", "bar"); - - Map fields2 = Maps.newHashMap(); - fields2.put("foo", "baz"); - - String measurement = "measurement"; - - TimeUnit precision = TimeUnit.NANOSECONDS; - - Map tags = Maps.newHashMap(); - tags.put("bar", "baz"); - - Long time = System.currentTimeMillis(); - - Point p1 = new Point(); - p1.setFields(fields1); - p1.setMeasurement(measurement); - p1.setPrecision(precision); - p1.setTags(tags); - p1.setTime(time); - - Point p2 = new Point(); - p2.setFields(fields2); - p2.setMeasurement(measurement); - p2.setPrecision(precision); - p2.setTags(tags); - p2.setTime(time); - - // WHEN I call equals on one with the other as arg - boolean equals = p1.equals(p2); - - // THEN equals returns true - assertThat(equals).isEqualTo(false); - } + /** + * Test that lineprotocol is conformant to: + *

+ * https://github.com/influxdb/influxdb/blob/master/tsdb/README.md + */ + @Test + public void lineProtocol() { + Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1"); + + point = Point.measurement("test,1").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test\\,1 a=1.0 1"); + + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A").build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\" 1"); + + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A\"B").build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\" 1"); + + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A\"B\"C").build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\\\"C\" 1"); + + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", "A B C").build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A B C\" 1"); + + point = Point + .measurement("test") + .time(1, TimeUnit.NANOSECONDS) + .addField("a", "A\"B") + .addField("b", "D E \"F") + .build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=\"A\\\"B\",b=\"D E \\\"F\" 1"); + + //Integer type + point = Point.measurement("inttest").time(1, TimeUnit.NANOSECONDS).addField("a", (Integer) 1).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("inttest a=1i 1"); + + point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", (Integer) 1).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=1i 1"); + + point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", 1L).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=1i 1"); + + point = Point.measurement("inttest,1").time(1, TimeUnit.NANOSECONDS).addField("a", BigInteger.valueOf(100)) + .build(); + assertThat(point.lineProtocol()).asString().isEqualTo("inttest\\,1 a=100i 1"); + } + + /** + * Test for ticket #44 + */ + @Test + public void testTicket44() { + Point point = Point.measurement("test").time(1, TimeUnit.MICROSECONDS).addField("a", 1.0).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1000"); + + point = Point.measurement("test").time(1, TimeUnit.MILLISECONDS).addField("a", 1.0).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1000000"); + + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", 1.0).build(); + BatchPoints batchPoints = BatchPoints.database("db").point(point).build(); + assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1\n"); + + point = Point.measurement("test").time(1, TimeUnit.MICROSECONDS).addField("a", 1.0).build(); + batchPoints = BatchPoints.database("db").point(point).build(); + assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000\n"); + + point = Point.measurement("test").time(1, TimeUnit.MILLISECONDS).addField("a", 1.0).build(); + batchPoints = BatchPoints.database("db").point(point).build(); + assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000000\n"); + + point = Point.measurement("test").addField("a", 1.0).time(1, TimeUnit.MILLISECONDS).build(); + batchPoints = BatchPoints.database("db").build(); + batchPoints = batchPoints.point(point); + assertThat(batchPoints.lineProtocol()).asString().isEqualTo("test a=1.0 1000000\n"); + + } + + /** + * Test for ticket #54 + */ + @Test + public void testTicket54() { + Byte byteNumber = 100; + Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", byteNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100i 1"); + + int intNumber = 100000000; + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", intNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); + + Integer integerNumber = 100000000; + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", integerNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); + + AtomicInteger atomicIntegerNumber = new AtomicInteger(100000000); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", atomicIntegerNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); + + Long longNumber = 1000000000000000000L; + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", longNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1000000000000000000i 1"); + + AtomicLong atomicLongNumber = new AtomicLong(1000000000000000000L); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", atomicLongNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1000000000000000000i 1"); + + BigInteger bigIntegerNumber = BigInteger.valueOf(100000000); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", bigIntegerNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000i 1"); + + Double doubleNumber = Double.valueOf(100000000.0001); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", doubleNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000.0001 1"); + + Float floatNumber = Float.valueOf(0.1f); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", floatNumber).build(); + assertThat(point.lineProtocol()).asString().startsWith("test a=0.10"); + + BigDecimal bigDecimalNumber = BigDecimal.valueOf(100000000.00000001); + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).addField("a", bigDecimalNumber).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=100000000.00000001 1"); + } + + @Test + public void testEscapingOfKeysAndValues() { + // Test escaping of spaces + Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar baz").addField("a", 1.0) + .build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\ baz a=1.0 1"); + + // Test escaping of commas + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar,baz").addField("a", 1.0) + .build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\,baz a=1.0 1"); + + // Test escaping of equals sign + point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar=baz").addField("a", 1.0) + .build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test,foo=bar\\=baz a=1.0 1"); + } + + @Test + public void testDeprecatedFieldMethodOnlyProducesFloatingPointValues() { + + Object[] ints = { (byte) 1, (short) 1, (int) 1, (long) 1, BigInteger.ONE }; + + for (Object intExample : ints) { + Point point = Point.measurement("test").time(1, TimeUnit.NANOSECONDS).field("a", intExample).build(); + assertThat(point.lineProtocol()).asString().isEqualTo("test a=1.0 1"); + } + + } + + /** + * Test for issue #117. + */ + @Test + public void testIgnoreNullPointerValue() { + // Test omission of null values + Point.Builder pointBuilder = Point.measurement("nulltest").time(1, TimeUnit.NANOSECONDS).tag("foo", "bar"); + + pointBuilder.field("field1", "value1"); + pointBuilder.field("field2", (Number) null); + pointBuilder.field("field3", (Integer) 1); + + Point point = pointBuilder.build(); + + assertThat(point.lineProtocol()).asString().isEqualTo("nulltest,foo=bar field1=\"value1\",field3=1.0 1"); + } + + /** + * Tests for issue #110 + */ + @Test(expected = IllegalArgumentException.class) + public void testAddingTagsWithNullNameThrowsAnError() { + Point.measurement("dontcare").tag(null, "DontCare"); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddingTagsWithNullValueThrowsAnError() { + Point.measurement("dontcare").tag("DontCare", null); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddingMapOfTagsWithNullNameThrowsAnError() { + Map map = Maps.newHashMap(); + map.put(null, "DontCare"); + Point.measurement("dontcare").tag(map); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddingMapOfTagsWithNullValueThrowsAnError() { + Map map = Maps.newHashMap(); + map.put("DontCare", null); + Point.measurement("dontcare").tag(map); + } + + @Test(expected = IllegalArgumentException.class) + public void testNullValueThrowsExceptionViaAddField() { + Point.measurement("dontcare").addField("field", (String) null); + } + + /** + * Tests for issue #266 + */ + @Test + public void testEquals() throws Exception { + // GIVEN two point objects with identical data + Map fields = Maps.newHashMap(); + fields.put("foo", "bar"); + + String measurement = "measurement"; + + TimeUnit precision = TimeUnit.NANOSECONDS; + + Map tags = Maps.newHashMap(); + tags.put("bar", "baz"); + + Long time = System.currentTimeMillis(); + + Point p1 = new Point(); + p1.setFields(fields); + p1.setMeasurement(measurement); + p1.setPrecision(precision); + p1.setTags(tags); + p1.setTime(time); + + Point p2 = new Point(); + p2.setFields(fields); + p2.setMeasurement(measurement); + p2.setPrecision(precision); + p2.setTags(tags); + p2.setTime(time); + + // WHEN I call equals on one with the other as arg + boolean equals = p1.equals(p2); + + // THEN equals returns true + assertThat(equals).isEqualTo(true); + } + + @Test + public void testUnEquals() throws Exception { + // GIVEN two point objects with different data + Map fields1 = Maps.newHashMap(); + fields1.put("foo", "bar"); + + Map fields2 = Maps.newHashMap(); + fields2.put("foo", "baz"); + + String measurement = "measurement"; + + TimeUnit precision = TimeUnit.NANOSECONDS; + + Map tags = Maps.newHashMap(); + tags.put("bar", "baz"); + + Long time = System.currentTimeMillis(); + + Point p1 = new Point(); + p1.setFields(fields1); + p1.setMeasurement(measurement); + p1.setPrecision(precision); + p1.setTags(tags); + p1.setTime(time); + + Point p2 = new Point(); + p2.setFields(fields2); + p2.setMeasurement(measurement); + p2.setPrecision(precision); + p2.setTags(tags); + p2.setTime(time); + + // WHEN I call equals on one with the other as arg + boolean equals = p1.equals(p2); + + // THEN equals returns true + assertThat(equals).isEqualTo(false); + } + + /** + * Tests for #182 + * + * @throws Exception + */ + @Test + public void testLineProtocolNanosecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.NANOSECONDS) + String nanosTime = p.lineProtocol(TimeUnit.NANOSECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in nanoseconds + assertThat(nanosTime).isEqualTo(String.valueOf(pDate.getTime() * 1000000)); + } + + @Test + public void testLineProtocolMicrosecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MICROSECONDS) + String microsTime = p.lineProtocol(TimeUnit.MICROSECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in microseconds + assertThat(microsTime).isEqualTo(String.valueOf(pDate.getTime() * 1000)); + } + + @Test + public void testLineProtocolMillisecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MILLISECONDS) + String millisTime = p.lineProtocol(TimeUnit.MILLISECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in microseconds + assertThat(millisTime).isEqualTo(String.valueOf(pDate.getTime())); + } + + @Test + public void testLineProtocolSecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.SECONDS) + String secondTime = p.lineProtocol(TimeUnit.SECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in seconds + String expectedSecondTimeStamp = String.valueOf(pDate.getTime() / 1000); + assertThat(secondTime).isEqualTo(expectedSecondTimeStamp); + } + + @Test + public void testLineProtocolMinutePrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MINUTE) + String secondTime = p.lineProtocol(TimeUnit.MINUTES).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in seconds + String expectedSecondTimeStamp = String.valueOf(pDate.getTime() / 60000); + assertThat(secondTime).isEqualTo(expectedSecondTimeStamp); + } + + @Test + public void testLineProtocolHourPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.NANOSECONDS) + String hourTime = p.lineProtocol(TimeUnit.HOURS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in hours + String expectedHourTimeStamp = String.valueOf(Math.round(pDate.getTime() / 3600000)); // 1000ms * 60s * 60m + assertThat(hourTime).isEqualTo(expectedHourTimeStamp); + } } From 237c9260e83423e63c96911bc071915488790732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 23 May 2017 13:38:00 +0200 Subject: [PATCH 02/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds --- src/main/java/org/influxdb/InfluxDB.java | 20 +++ .../java/org/influxdb/dto/BatchPoints.java | 41 ++++- src/main/java/org/influxdb/dto/Point.java | 20 +++ .../java/org/influxdb/impl/InfluxDBImpl.java | 35 +++-- src/test/java/org/influxdb/InfluxDBTest.java | 141 ++++++++++++++++++ src/test/java/org/influxdb/dto/PointTest.java | 117 ++++++++++++++- 6 files changed, 358 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/influxdb/InfluxDB.java b/src/main/java/org/influxdb/InfluxDB.java index cad445c05..b98622e66 100644 --- a/src/main/java/org/influxdb/InfluxDB.java +++ b/src/main/java/org/influxdb/InfluxDB.java @@ -197,6 +197,16 @@ public InfluxDB enableBatch(final int actions, final int flushDuration, final Ti public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final String records); + /** + * Write a set of Points to the influxdb database with the string records. + * + * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * + * @param records + */ + public void write(final String database, final String retentionPolicy, + final ConsistencyLevel consistency, final TimeUnit precision, final String records); + /** * Write a set of Points to the influxdb database with the list of string records. * @@ -207,6 +217,16 @@ public void write(final String database, final String retentionPolicy, public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final List records); + /** + * Write a set of Points to the influxdb database with the list of string records. + * + * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * + * @param records + */ + public void write(final String database, final String retentionPolicy, + final ConsistencyLevel consistency, final TimeUnit precision, final List records); + /** * Write a set of Points to the influxdb database with the string records through UDP. * diff --git a/src/main/java/org/influxdb/dto/BatchPoints.java b/src/main/java/org/influxdb/dto/BatchPoints.java index 0f39540d7..8886fea69 100644 --- a/src/main/java/org/influxdb/dto/BatchPoints.java +++ b/src/main/java/org/influxdb/dto/BatchPoints.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.TimeUnit; import org.influxdb.InfluxDB.ConsistencyLevel; @@ -27,6 +28,7 @@ public class BatchPoints { private Map tags; private List points; private ConsistencyLevel consistency; + private TimeUnit precision; BatchPoints() { // Only visible in the Builder @@ -52,6 +54,7 @@ public static final class Builder { private final Map tags = Maps.newTreeMap(Ordering.natural()); private final List points = Lists.newArrayList(); private ConsistencyLevel consistency; + private TimeUnit precision; /** * @param database @@ -118,6 +121,16 @@ public Builder consistency(final ConsistencyLevel consistencyLevel) { return this; } + /** + * Set the time precision to use for the whole batch. If unspecified, will default to {@link TimeUnit#NANOSECONDS} + * @param precision + * @return the Builder instance + */ + public Builder precision(final TimeUnit precision) { + this.precision = precision; + return this; + } + /** * Create a new BatchPoints instance. * @@ -138,6 +151,10 @@ public BatchPoints build() { this.consistency = ConsistencyLevel.ONE; } batchPoints.setConsistency(this.consistency); + if (null == this.precision) { + this.precision = TimeUnit.NANOSECONDS; + } + batchPoints.setPrecision(this.precision); return batchPoints; } } @@ -187,6 +204,20 @@ void setPoints(final List points) { this.points = points; } + /** + * @return the time precision unit + */ + public TimeUnit getPrecision() { + return precision; + } + + /** + * @param precision the time precision to set for the batch points + */ + public void setPrecision(TimeUnit precision) { + this.precision = precision; + } + /** * Add a single Point to these batches. * @@ -242,12 +273,13 @@ public boolean equals(final Object o) { && Objects.equals(retentionPolicy, that.retentionPolicy) && Objects.equals(tags, that.tags) && Objects.equals(points, that.points) - && consistency == that.consistency; + && consistency == that.consistency + && precision == that.precision; } @Override public int hashCode() { - return Objects.hash(database, retentionPolicy, tags, points, consistency); + return Objects.hash(database, retentionPolicy, tags, points, consistency, precision); } /** @@ -264,6 +296,8 @@ public String toString() { builder.append(this.consistency); builder.append(", tags="); builder.append(this.tags); + builder.append(", precision="); + builder.append(this.precision); builder.append(", points="); builder.append(this.points); builder.append("]"); @@ -278,8 +312,9 @@ public String toString() { */ public String lineProtocol() { StringBuilder sb = new StringBuilder(); + for (Point point : this.points) { - sb.append(point.lineProtocol()).append("\n"); + sb.append(point.lineProtocol(this.precision)).append("\n"); } return sb.toString(); } diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index d1dd78a7c..c00e9128a 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -328,6 +328,20 @@ public String lineProtocol() { return sb.toString(); } + /** + * Calculate the lineprotocol entry for a single point, using a specific {@link TimeUnit} for the timestamp + * @param precision the time precision unit for this point + * @return the String without newLine + */ + public String lineProtocol(final TimeUnit precision) { + final StringBuilder sb = new StringBuilder(); + sb.append(KEY_ESCAPER.escape(this.measurement)); + sb.append(concatenatedTags()); + sb.append(concatenateFields()); + sb.append(formatedTime(precision)); + return sb.toString(); + } + private StringBuilder concatenatedTags() { final StringBuilder sb = new StringBuilder(); for (Entry tag : this.tags.entrySet()) { @@ -385,4 +399,10 @@ private StringBuilder formatedTime() { return sb; } + private StringBuilder formatedTime(TimeUnit precision) { + final StringBuilder sb = new StringBuilder(); + sb.append(" ").append(precision.convert(this.time, this.precision)); + return sb; + } + } diff --git a/src/main/java/org/influxdb/impl/InfluxDBImpl.java b/src/main/java/org/influxdb/impl/InfluxDBImpl.java index 884787cab..f3ec4632d 100644 --- a/src/main/java/org/influxdb/impl/InfluxDBImpl.java +++ b/src/main/java/org/influxdb/impl/InfluxDBImpl.java @@ -269,31 +269,46 @@ public void write(final BatchPoints batchPoints) { this.password, batchPoints.getDatabase(), batchPoints.getRetentionPolicy(), - TimeUtil.toTimePrecision(TimeUnit.NANOSECONDS), + TimeUtil.toTimePrecision(batchPoints.getPrecision()), batchPoints.getConsistency().value(), lineProtocol)); } + + @Override + public void write(String database, String retentionPolicy, ConsistencyLevel consistency, + TimeUnit precision, String records) { + execute(this.influxDBService.writePoints( + this.username, + this.password, + database, + retentionPolicy, + TimeUtil.toTimePrecision(precision), + consistency.value(), + RequestBody.create(MEDIA_TYPE_STRING, records))); + } + @Override public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final String records) { - execute(this.influxDBService.writePoints( - this.username, - this.password, - database, - retentionPolicy, - TimeUtil.toTimePrecision(TimeUnit.NANOSECONDS), - consistency.value(), - RequestBody.create(MEDIA_TYPE_STRING, records))); + write(database, retentionPolicy, consistency, TimeUnit.NANOSECONDS, records); } @Override public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final List records) { + write(database, retentionPolicy, consistency, TimeUnit.NANOSECONDS, records); + } + + + @Override + public void write(String database, String retentionPolicy, ConsistencyLevel consistency, + TimeUnit precision, List records) { final String joinedRecords = Joiner.on("\n").join(records); - write(database, retentionPolicy, consistency, joinedRecords); + write(database, retentionPolicy, consistency, precision, joinedRecords); } + /** * {@inheritDoc} */ diff --git a/src/test/java/org/influxdb/InfluxDBTest.java b/src/test/java/org/influxdb/InfluxDBTest.java index 116f42552..0ef5794d3 100644 --- a/src/test/java/org/influxdb/InfluxDBTest.java +++ b/src/test/java/org/influxdb/InfluxDBTest.java @@ -1,5 +1,7 @@ package org.influxdb; +import static org.assertj.core.api.Assertions.assertThat; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -19,12 +21,14 @@ import org.influxdb.dto.Query; import org.influxdb.dto.QueryResult; import org.influxdb.impl.InfluxDBImpl; +import org.influxdb.impl.TimeUtil; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import com.google.common.collect.Lists; import com.google.common.util.concurrent.Uninterruptibles; /** @@ -362,6 +366,143 @@ public void testWriteMultipleStringDataLines() { this.influxDB.deleteDatabase(dbName); } + /** + * Tests writing points using the time precision feature + * @throws Exception + */ + @Test + public void testWriteBatchWithPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a batch of points using second precision + Point p1 = Point + .measurement(measurement) + .addField("foo", 1d) + .tag("device", "one") + .time(1485273600, TimeUnit.SECONDS).build(); // 2017-01-27T16:00:00 + String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + Point p2 = Point + .measurement(measurement) + .addField("foo", 2d) + .tag("device", "two") + .time(1485277200, TimeUnit.SECONDS).build(); // 2017-01-27T17:00:00 + String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + Point p3 = Point + .measurement(measurement) + .addField("foo", 3d) + .tag("device", "three") + .time(1485280800, TimeUnit.SECONDS).build(); // 2017-01-27T18:00:00 + String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + + BatchPoints batchPoints = BatchPoints + .database(dbName) + .retentionPolicy(rp) + .precision(TimeUnit.SECONDS) + .points(p1, p2, p3) + .build(); + + // WHEN I write the batch + this.influxDB.write(batchPoints); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + + @Test + public void testWriteBatchWithoutPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a batch of points that has no specific precision + Point p1 = Point + .measurement(measurement) + .addField("foo", 1d) + .tag("device", "one") + .time(1485273600000000100L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T16:00:00.000000100Z + String timeP1 = "2017-01-27T16:00:00.000000100Z"; + Point p2 = Point + .measurement(measurement) + .addField("foo", 2d) + .tag("device", "two") + .time(1485277200000000200L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T17:00:00.000000200Z + String timeP2 = "2017-01-27T17:00:00.000000200Z"; + Point p3 = Point + .measurement(measurement) + .addField("foo", 3d) + .tag("device", "three") + .time(1485280800000000300L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T18:00:00.000000300Z + String timeP3 = "2017-01-27T18:00:00.000000300Z"; + + BatchPoints batchPoints = BatchPoints + .database(dbName) + .retentionPolicy(rp) + .points(p1, p2, p3) + .build(); + + // WHEN I write the batch + this.influxDB.write(batchPoints); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + + @Test + public void testWriteRecordsWithPrecision() throws Exception { + // GIVEN a database and a measurement + String dbName = "precision_unittest_" + System.currentTimeMillis(); + this.influxDB.createDatabase(dbName); + + String rp = TestUtils.defaultRetentionPolicy(this.influxDB.version()); + + String measurement = TestUtils.getRandomMeasurement(); + + // GIVEN a set of records using second precision + List records = Lists.newArrayList(); + records.add("cpu,atag=test1 idle=100,usertime=10,system=1 1485273600"); + String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + + records.add("cpu,atag=test2 idle=200,usertime=20,system=2 1485277200"); + String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + + records.add("cpu,atag=test3 idle=300,usertime=30,system=3 1485280800"); + String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + + // WHEN I write the batch + this.influxDB.write(dbName, rp, null, TimeUnit.SECONDS, records); + + // THEN the measure points have a timestamp with second precision + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); + assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(2).get(0)).isEqualTo(timeP3); + + this.influxDB.deleteDatabase(dbName); + } + /** * Test that creating database which name is composed of numbers only works */ diff --git a/src/test/java/org/influxdb/dto/PointTest.java b/src/test/java/org/influxdb/dto/PointTest.java index 62301db39..fb9c1226e 100644 --- a/src/test/java/org/influxdb/dto/PointTest.java +++ b/src/test/java/org/influxdb/dto/PointTest.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Date; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -314,7 +315,117 @@ public void testUnEquals() throws Exception { // WHEN I call equals on one with the other as arg boolean equals = p1.equals(p2); - // THEN equals returns true - assertThat(equals).isEqualTo(false); - } + // THEN equals returns true + assertThat(equals).isEqualTo(false); + } + + /** + * Tests for #182 + * + * @throws Exception + */ + @Test + public void testLineProtocolNanosecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.NANOSECONDS) + String nanosTime = p.lineProtocol(TimeUnit.NANOSECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in nanoseconds + assertThat(nanosTime).isEqualTo(String.valueOf(pDate.getTime() * 1000000)); + } + + @Test + public void testLineProtocolMicrosecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MICROSECONDS) + String microsTime = p.lineProtocol(TimeUnit.MICROSECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in microseconds + assertThat(microsTime).isEqualTo(String.valueOf(pDate.getTime() * 1000)); + } + + @Test + public void testLineProtocolMillisecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MILLISECONDS) + String millisTime = p.lineProtocol(TimeUnit.MILLISECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in microseconds + assertThat(millisTime).isEqualTo(String.valueOf(pDate.getTime())); + } + + @Test + public void testLineProtocolSecondPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.SECONDS) + String secondTime = p.lineProtocol(TimeUnit.SECONDS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in seconds + String expectedSecondTimeStamp = String.valueOf(pDate.getTime() / 1000); + assertThat(secondTime).isEqualTo(expectedSecondTimeStamp); + } + + @Test + public void testLineProtocolMinutePrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.MINUTE) + String secondTime = p.lineProtocol(TimeUnit.MINUTES).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in seconds + String expectedSecondTimeStamp = String.valueOf(pDate.getTime() / 60000); + assertThat(secondTime).isEqualTo(expectedSecondTimeStamp); + } + + @Test + public void testLineProtocolHourPrecision() throws Exception { + // GIVEN a point with millisecond precision + Date pDate = new Date(); + Point p = Point + .measurement("measurement") + .addField("foo", "bar") + .time(pDate.getTime(), TimeUnit.MILLISECONDS) + .build(); + + // WHEN i call lineProtocol(TimeUnit.NANOSECONDS) + String hourTime = p.lineProtocol(TimeUnit.HOURS).replace("measurement foo=\"bar\" ", ""); + + // THEN the timestamp is in hours + String expectedHourTimeStamp = String.valueOf(Math.round(pDate.getTime() / 3600000)); // 1000ms * 60s * 60m + assertThat(hourTime).isEqualTo(expectedHourTimeStamp); + } } From 7c185d1e9c47fa96c3599092f606fd46604749e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 23 May 2017 15:52:52 +0200 Subject: [PATCH 03/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds checkstyle violations fix --- src/main/java/org/influxdb/dto/BatchPoints.java | 17 ++++++++--------- src/main/java/org/influxdb/dto/Point.java | 14 +++++++------- .../java/org/influxdb/impl/InfluxDBImpl.java | 8 ++++---- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/influxdb/dto/BatchPoints.java b/src/main/java/org/influxdb/dto/BatchPoints.java index 8886fea69..c1bee4383 100644 --- a/src/main/java/org/influxdb/dto/BatchPoints.java +++ b/src/main/java/org/influxdb/dto/BatchPoints.java @@ -1,18 +1,17 @@ package org.influxdb.dto; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -import org.influxdb.InfluxDB.ConsistencyLevel; - import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; +import org.influxdb.InfluxDB.ConsistencyLevel; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; /** * {Purpose of This Type}. @@ -214,7 +213,7 @@ public TimeUnit getPrecision() { /** * @param precision the time precision to set for the batch points */ - public void setPrecision(TimeUnit precision) { + public void setPrecision(final TimeUnit precision) { this.precision = precision; } diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index c00e9128a..647dbdbd4 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -1,5 +1,10 @@ package org.influxdb.dto; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; + import java.math.BigDecimal; import java.math.BigInteger; import java.text.NumberFormat; @@ -10,11 +15,6 @@ import java.util.TreeMap; import java.util.concurrent.TimeUnit; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.escape.Escaper; -import com.google.common.escape.Escapers; - /** * Representation of a InfluxDB database Point. * @@ -329,7 +329,7 @@ public String lineProtocol() { } /** - * Calculate the lineprotocol entry for a single point, using a specific {@link TimeUnit} for the timestamp + * Calculate the lineprotocol entry for a single point, using a specific {@link TimeUnit} for the timestamp. * @param precision the time precision unit for this point * @return the String without newLine */ @@ -399,7 +399,7 @@ private StringBuilder formatedTime() { return sb; } - private StringBuilder formatedTime(TimeUnit precision) { + private StringBuilder formatedTime(final TimeUnit precision) { final StringBuilder sb = new StringBuilder(); sb.append(" ").append(precision.convert(this.time, this.precision)); return sb; diff --git a/src/main/java/org/influxdb/impl/InfluxDBImpl.java b/src/main/java/org/influxdb/impl/InfluxDBImpl.java index f3ec4632d..247adf543 100644 --- a/src/main/java/org/influxdb/impl/InfluxDBImpl.java +++ b/src/main/java/org/influxdb/impl/InfluxDBImpl.java @@ -276,8 +276,8 @@ public void write(final BatchPoints batchPoints) { @Override - public void write(String database, String retentionPolicy, ConsistencyLevel consistency, - TimeUnit precision, String records) { + public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, + final TimeUnit precision, final String records) { execute(this.influxDBService.writePoints( this.username, this.password, @@ -302,8 +302,8 @@ public void write(final String database, final String retentionPolicy, final Con @Override - public void write(String database, String retentionPolicy, ConsistencyLevel consistency, - TimeUnit precision, List records) { + public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, + final TimeUnit precision, final List records) { final String joinedRecords = Joiner.on("\n").join(records); write(database, retentionPolicy, consistency, precision, joinedRecords); } From 701519796c22bedbd364106c53f5f509af01ab56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 23 May 2017 16:54:39 +0200 Subject: [PATCH 04/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds tests failing fixes --- src/test/java/org/influxdb/InfluxDBTest.java | 66 ++++++++++++-------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/src/test/java/org/influxdb/InfluxDBTest.java b/src/test/java/org/influxdb/InfluxDBTest.java index 0ef5794d3..9ef6ae188 100644 --- a/src/test/java/org/influxdb/InfluxDBTest.java +++ b/src/test/java/org/influxdb/InfluxDBTest.java @@ -3,6 +3,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -73,7 +76,7 @@ public void setUp() throws InterruptedException, IOException { System.out.println("# Connected to InfluxDB Version: " + this.influxDB.version() + " #"); System.out.println("##################################################################################"); } - + /** * delete UDP database after all tests end. */ @@ -133,7 +136,7 @@ public void testDescribeDatabases() { Assert.assertTrue("It is expected that describeDataBases contents the newly create database.", found); this.influxDB.deleteDatabase(dbName); } - + /** * Test that Database exists works. */ @@ -174,7 +177,7 @@ public void testWrite() { Assert.assertFalse(result.getResults().get(0).getSeries().get(0).getTags().isEmpty()); this.influxDB.deleteDatabase(dbName); } - + /** * Test the implementation of {@link InfluxDB#write(int, Point)}'s sync support. */ @@ -189,7 +192,7 @@ public void testSyncWritePointThroughUDP() { QueryResult result = this.influxDB.query(query); Assert.assertFalse(result.getResults().get(0).getSeries().get(0).getTags().isEmpty()); } - + /** * Test the implementation of {@link InfluxDB#write(int, Point)}'s async support. */ @@ -209,8 +212,8 @@ public void testAsyncWritePointThroughUDP() { this.influxDB.disableBatch(); } } - - + + /** * Test the implementation of {@link InfluxDB#write(int, Point)}'s async support. */ @@ -381,24 +384,32 @@ public void testWriteBatchWithPrecision() throws Exception { String measurement = TestUtils.getRandomMeasurement(); // GIVEN a batch of points using second precision + DateTimeFormatter formatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") + .withZone(ZoneId.of("UTC")); + int t1 = 1485273600; Point p1 = Point .measurement(measurement) .addField("foo", 1d) .tag("device", "one") - .time(1485273600, TimeUnit.SECONDS).build(); // 2017-01-27T16:00:00 - String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + .time(t1, TimeUnit.SECONDS).build(); // 2017-01-27T16:00:00 + String timeP1 = formatter.format(Instant.ofEpochSecond(t1)); + + int t2 = 1485277200; Point p2 = Point .measurement(measurement) .addField("foo", 2d) .tag("device", "two") - .time(1485277200, TimeUnit.SECONDS).build(); // 2017-01-27T17:00:00 - String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + .time(t2, TimeUnit.SECONDS).build(); // 2017-01-27T17:00:00 + String timeP2 = formatter.format(Instant.ofEpochSecond(t2)); + + int t3 = 1485280800; Point p3 = Point .measurement(measurement) .addField("foo", 3d) .tag("device", "three") - .time(1485280800, TimeUnit.SECONDS).build(); // 2017-01-27T18:00:00 - String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + .time(t3, TimeUnit.SECONDS).build(); // 2017-01-27T18:00:00 + String timeP3 = formatter.format(Instant.ofEpochSecond(t3)); BatchPoints batchPoints = BatchPoints .database(dbName) @@ -431,24 +442,29 @@ public void testWriteBatchWithoutPrecision() throws Exception { String measurement = TestUtils.getRandomMeasurement(); // GIVEN a batch of points that has no specific precision + long t1 = 1485273600000000100L; Point p1 = Point .measurement(measurement) .addField("foo", 1d) .tag("device", "one") - .time(1485273600000000100L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T16:00:00.000000100Z - String timeP1 = "2017-01-27T16:00:00.000000100Z"; + .time(t1, TimeUnit.NANOSECONDS).build(); // 2017-01-27T16:00:00.000000100Z + Double timeP1 = Double.valueOf(t1); + + long t2 = 1485277200000000200L; Point p2 = Point .measurement(measurement) .addField("foo", 2d) .tag("device", "two") - .time(1485277200000000200L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T17:00:00.000000200Z - String timeP2 = "2017-01-27T17:00:00.000000200Z"; + .time(t2, TimeUnit.NANOSECONDS).build(); // 2017-01-27T17:00:00.000000200Z + Double timeP2 = Double.valueOf(t2); + + long t3 = 1485280800000000300L; Point p3 = Point .measurement(measurement) .addField("foo", 3d) .tag("device", "three") - .time(1485280800000000300L, TimeUnit.NANOSECONDS).build(); // 2017-01-27T18:00:00.000000300Z - String timeP3 = "2017-01-27T18:00:00.000000300Z"; + .time(t3, TimeUnit.NANOSECONDS).build(); // 2017-01-27T18:00:00.000000300Z + Double timeP3 = Double.valueOf(t3); BatchPoints batchPoints = BatchPoints .database(dbName) @@ -460,7 +476,7 @@ public void testWriteBatchWithoutPrecision() throws Exception { this.influxDB.write(batchPoints); // THEN the measure points have a timestamp with second precision - QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); + QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName), TimeUnit.NANOSECONDS); assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().size()).isEqualTo(3); assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(0).get(0)).isEqualTo(timeP1); assertThat(queryResult.getResults().get(0).getSeries().get(0).getValues().get(1).get(0)).isEqualTo(timeP2); @@ -491,7 +507,7 @@ public void testWriteRecordsWithPrecision() throws Exception { String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); // WHEN I write the batch - this.influxDB.write(dbName, rp, null, TimeUnit.SECONDS, records); + this.influxDB.write(dbName, rp, InfluxDB.ConsistencyLevel.ALL, TimeUnit.SECONDS, records); // THEN the measure points have a timestamp with second precision QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); @@ -515,7 +531,7 @@ public void testCreateNumericNamedDatabase() { Assert.assertTrue(result.contains(numericDbName)); this.influxDB.deleteDatabase(numericDbName); } - + /** * Test that creating database which name is empty will throw expected exception */ @@ -553,7 +569,7 @@ public void testIsBatchEnabled() { this.influxDB.disableBatch(); Assert.assertFalse(this.influxDB.isBatchEnabled()); } - + /** * Test the implementation of {@link InfluxDB#enableBatch(int, int, TimeUnit, ThreadFactory)}. */ @@ -561,7 +577,7 @@ public void testIsBatchEnabled() { public void testBatchEnabledWithThreadFactory() { final String threadName = "async_influxdb_write"; this.influxDB.enableBatch(1, 1, TimeUnit.SECONDS, new ThreadFactory() { - + @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); @@ -576,7 +592,7 @@ public Thread newThread(Runnable r) { existThreadWithSettedName = true; break; } - + } Assert.assertTrue(existThreadWithSettedName); this.influxDB.disableBatch(); @@ -586,7 +602,7 @@ public Thread newThread(Runnable r) { public void testBatchEnabledWithThreadFactoryIsNull() { this.influxDB.enableBatch(1, 1, TimeUnit.SECONDS, null); } - + /** * Test the implementation of {@link InfluxDBImpl#InfluxDBImpl(String, String, String, okhttp3.OkHttpClient.Builder)}. */ From 1b26692690c7f8f080c2a8c4f316049053d867a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 23 May 2017 17:19:15 +0200 Subject: [PATCH 05/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds tests failing fixes --- src/test/java/org/influxdb/InfluxDBTest.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/test/java/org/influxdb/InfluxDBTest.java b/src/test/java/org/influxdb/InfluxDBTest.java index 9ef6ae188..00fd32bf9 100644 --- a/src/test/java/org/influxdb/InfluxDBTest.java +++ b/src/test/java/org/influxdb/InfluxDBTest.java @@ -496,18 +496,21 @@ public void testWriteRecordsWithPrecision() throws Exception { String measurement = TestUtils.getRandomMeasurement(); // GIVEN a set of records using second precision + DateTimeFormatter formatter = DateTimeFormatter + .ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") + .withZone(ZoneId.of("UTC")); List records = Lists.newArrayList(); - records.add("cpu,atag=test1 idle=100,usertime=10,system=1 1485273600"); - String timeP1 = TimeUtil.toInfluxDBTimeFormat(1485273600000L); + records.add(measurement + ",atag=test1 idle=100,usertime=10,system=1 1485273600"); + String timeP1 = formatter.format(Instant.ofEpochSecond(1485273600)); - records.add("cpu,atag=test2 idle=200,usertime=20,system=2 1485277200"); - String timeP2 = TimeUtil.toInfluxDBTimeFormat(1485277200000L); + records.add(measurement + ",atag=test2 idle=200,usertime=20,system=2 1485277200"); + String timeP2 = formatter.format(Instant.ofEpochSecond(1485277200)); - records.add("cpu,atag=test3 idle=300,usertime=30,system=3 1485280800"); - String timeP3 = TimeUtil.toInfluxDBTimeFormat(1485280800000L); + records.add(measurement + ",atag=test3 idle=300,usertime=30,system=3 1485280800"); + String timeP3 = formatter.format(Instant.ofEpochSecond(1485280800)); // WHEN I write the batch - this.influxDB.write(dbName, rp, InfluxDB.ConsistencyLevel.ALL, TimeUnit.SECONDS, records); + this.influxDB.write(dbName, rp, InfluxDB.ConsistencyLevel.ONE, TimeUnit.SECONDS, records); // THEN the measure points have a timestamp with second precision QueryResult queryResult = this.influxDB.query(new Query("SELECT * FROM " + measurement, dbName)); From 3cf468e752599b2419981d3352021c6468d35653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Thu, 25 May 2017 11:19:22 +0200 Subject: [PATCH 06/12] revert automatic import reorganize --- src/main/java/org/influxdb/dto/BatchPoints.java | 15 ++++++++------- src/main/java/org/influxdb/dto/Point.java | 10 +++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/influxdb/dto/BatchPoints.java b/src/main/java/org/influxdb/dto/BatchPoints.java index c1bee4383..5a04f4cf2 100644 --- a/src/main/java/org/influxdb/dto/BatchPoints.java +++ b/src/main/java/org/influxdb/dto/BatchPoints.java @@ -1,18 +1,19 @@ package org.influxdb.dto; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Ordering; -import org.influxdb.InfluxDB.ConsistencyLevel; - import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; +import org.influxdb.InfluxDB.ConsistencyLevel; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; + /** * {Purpose of This Type}. * diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index 647dbdbd4..cc7d0c134 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -1,10 +1,5 @@ package org.influxdb.dto; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.escape.Escaper; -import com.google.common.escape.Escapers; - import java.math.BigDecimal; import java.math.BigInteger; import java.text.NumberFormat; @@ -15,6 +10,11 @@ import java.util.TreeMap; import java.util.concurrent.TimeUnit; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.common.escape.Escaper; +import com.google.common.escape.Escapers; + /** * Representation of a InfluxDB database Point. * From 69801af87e9b32ec43ab3d1f3d2b8532ff08cdbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Thu, 25 May 2017 11:21:55 +0200 Subject: [PATCH 07/12] revert automatic indent --- src/main/java/org/influxdb/impl/InfluxDBImpl.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/influxdb/impl/InfluxDBImpl.java b/src/main/java/org/influxdb/impl/InfluxDBImpl.java index 247adf543..fec81a4f9 100644 --- a/src/main/java/org/influxdb/impl/InfluxDBImpl.java +++ b/src/main/java/org/influxdb/impl/InfluxDBImpl.java @@ -279,13 +279,13 @@ public void write(final BatchPoints batchPoints) { public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final TimeUnit precision, final String records) { execute(this.influxDBService.writePoints( - this.username, - this.password, - database, - retentionPolicy, - TimeUtil.toTimePrecision(precision), - consistency.value(), - RequestBody.create(MEDIA_TYPE_STRING, records))); + this.username, + this.password, + database, + retentionPolicy, + TimeUtil.toTimePrecision(precision), + consistency.value(), + RequestBody.create(MEDIA_TYPE_STRING, records))); } @Override From 1f98f1e238580617993b7c3556bf53a92f1d8c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 13 Jun 2017 09:18:36 +0200 Subject: [PATCH 08/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds merged changes from 2.6 release --- src/main/java/org/influxdb/dto/Point.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index 5ecc00e2d..ec60c06b0 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -346,11 +346,14 @@ public String lineProtocol() { * @return the String without newLine */ public String lineProtocol(final TimeUnit precision) { - final StringBuilder sb = new StringBuilder(); - sb.append(KEY_ESCAPER.escape(this.measurement)); - sb.append(concatenatedTags()); - sb.append(concatenateFields()); - sb.append(formatedTime(precision)); + final StringBuilder sb = CACHED_STRINGBUILDERS + .get() + .computeIfAbsent(this.measurement, MeasurementStringBuilder::new) + .resetForUse(); + + concatenatedTags(sb); + concatenatedFields(sb); + formatedTime(sb, precision); return sb.toString(); } @@ -399,8 +402,7 @@ private void formatedTime(final StringBuilder sb) { sb.append(' ').append(TimeUnit.NANOSECONDS.convert(this.time, this.precision)); } - private StringBuilder formatedTime(final TimeUnit precision) { - final StringBuilder sb = new StringBuilder(); + private StringBuilder formatedTime(final StringBuilder sb, final TimeUnit precision) { sb.append(" ").append(precision.convert(this.time, this.precision)); return sb; } From da2e1b99ae2422ced1f6b0cf69565c98edc3a387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Marty?= Date: Tue, 13 Jun 2017 09:51:12 +0200 Subject: [PATCH 09/12] influxdb-java-182 Allow write precision of TimeUnit other than Nanoseconds fix merge errors --- src/test/java/org/influxdb/InfluxDBTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/influxdb/InfluxDBTest.java b/src/test/java/org/influxdb/InfluxDBTest.java index 6ff1fe61a..4a74a94a3 100644 --- a/src/test/java/org/influxdb/InfluxDBTest.java +++ b/src/test/java/org/influxdb/InfluxDBTest.java @@ -560,6 +560,7 @@ public void testWriteRecordsWithPrecision() throws Exception { this.influxDB.deleteDatabase(dbName); } + /** * Test writing multiple separate records to the database using string protocol with simpler interface. */ @Test From f5634ce5205ec24160c34ba77f42c2139b42471c Mon Sep 17 00:00:00 2001 From: Hoan Xuan Le Date: Wed, 9 May 2018 10:18:16 +0700 Subject: [PATCH 10/12] fix build javadocs failed + fix unit test --- src/main/java/org/influxdb/InfluxDB.java | 22 ++++++++++++++++++++-- src/main/java/org/influxdb/dto/Point.java | 3 +++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/influxdb/InfluxDB.java b/src/main/java/org/influxdb/InfluxDB.java index 7ff02165a..ec9b7b32a 100644 --- a/src/main/java/org/influxdb/InfluxDB.java +++ b/src/main/java/org/influxdb/InfluxDB.java @@ -299,9 +299,18 @@ public void write(final String database, final String retentionPolicy, /** * Write a set of Points to the influxdb database with the string records. * - * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * @see 2696 * + * @param database + * the name of the database to write + * @param retentionPolicy + * the retentionPolicy to use + * @param consistency + * the ConsistencyLevel to use + * @param precision + * the time precision to use * @param records + * the points in the correct lineprotocol. */ public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final TimeUnit precision, final String records); @@ -326,9 +335,18 @@ public void write(final String database, final String retentionPolicy, /** * Write a set of Points to the influxdb database with the list of string records. * - * {@linkplain "https://github.com/influxdb/influxdb/pull/2696"} + * @see 2696 * + * @param database + * the name of the database to write + * @param retentionPolicy + * the retentionPolicy to use + * @param consistency + * the ConsistencyLevel to use + * @param precision + * the time precision to use * @param records + * the List of points in the correct lineprotocol. */ public void write(final String database, final String retentionPolicy, final ConsistencyLevel consistency, final TimeUnit precision, final List records); diff --git a/src/main/java/org/influxdb/dto/Point.java b/src/main/java/org/influxdb/dto/Point.java index 67f486762..fd0175c41 100644 --- a/src/main/java/org/influxdb/dto/Point.java +++ b/src/main/java/org/influxdb/dto/Point.java @@ -423,6 +423,9 @@ private void formatedTime(final StringBuilder sb) { } private StringBuilder formatedTime(final StringBuilder sb, final TimeUnit precision) { + if (this.time == null || this.precision == null) { + return sb; + } sb.append(" ").append(precision.convert(this.time, this.precision)); return sb; } From 348faa117b9790865d1744aa7b1b5992d293af5d Mon Sep 17 00:00:00 2001 From: Hoan Xuan Le Date: Fri, 11 May 2018 14:51:21 +0700 Subject: [PATCH 11/12] set method accessibility to default --- src/main/java/org/influxdb/dto/BatchPoints.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/influxdb/dto/BatchPoints.java b/src/main/java/org/influxdb/dto/BatchPoints.java index a2f484258..9d5fc9328 100644 --- a/src/main/java/org/influxdb/dto/BatchPoints.java +++ b/src/main/java/org/influxdb/dto/BatchPoints.java @@ -211,7 +211,7 @@ public TimeUnit getPrecision() { /** * @param precision the time precision to set for the batch points */ - public void setPrecision(final TimeUnit precision) { + void setPrecision(final TimeUnit precision) { this.precision = precision; } From 565c535c9c7382e90eed4366abb8d0de31e5406a Mon Sep 17 00:00:00 2001 From: Hoan Xuan Le Date: Fri, 11 May 2018 17:13:59 +0700 Subject: [PATCH 12/12] change log entry for PR #321 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48467b140..24e142fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## 2.11 [unreleased] +### Features + +- Allow write precision of TimeUnit other than Nanoseconds [PR #321](https://github.com/influxdata/influxdb-java/pull/321) - Support dynamic measurement name in InfluxDBResultMapper [PR #423](https://github.com/influxdata/influxdb-java/pull/423) ## 2.10 [2018-04-26]