Skip to content

Commit 61b11a1

Browse files
authored
Merge pull request #8 from artstorm/fix-influxdb-datatypes
Add data types to InfluxDB measurements
2 parents cef02a0 + bf99644 commit 61b11a1

File tree

4 files changed

+178
-25
lines changed

4 files changed

+178
-25
lines changed

README.md

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Jenkins Shared Library for Unity
22

33
[![Test Suite](https://github.com/artstorm/jenkins-shared-library-unity/actions/workflows/tests.yml/badge.svg)](https://github.com/artstorm/jenkins-shared-library-unity/actions)
4+
[![Mastodon: @johansteen](https://img.shields.io/badge/mastodon-@johansteen-blue.svg?logo=mastodon&logoColor=ffffff&labelColor=383f47)](https://mastodon.gamedev.place/@johansteen)
45
[![Twitter: @artstorm](https://img.shields.io/badge/twitter-@artstorm-blue.svg?logo=twitter&logoColor=ffffff&labelColor=383f47)](https://twitter.com/artstorm)
56
[![Discord: Bitbebop](https://img.shields.io/badge/chat-discord-blue?logo=discord&logoColor=ffffff&labelColor=383f47)](https://discord.gg/WJn7w5WaU9)
67

@@ -323,7 +324,13 @@ success {
323324

324325
#### InfluxFB Add Measurement
325326

326-
Add a measurement for writing to InfluxDB.
327+
Add a measurement for writing to InfluxDB. The data type for each field in teh measurement is set with a string.
328+
329+
| value | Data type |
330+
| ----- | --------- |
331+
| `"f"` | float |
332+
| `"i"` | integer |
333+
| `"s"` | string |
327334

328335
```groovy
329336
influxdb.addMeasurement("build",
@@ -332,12 +339,13 @@ influxdb.addMeasurement("build",
332339
build_type: buildType
333340
],
334341
[
335-
size: size,
336-
duration_unity: timers.getDuration("Unity.${platform}"),
337-
duration_xcode: timers.getDuration("Xcode.${platform}"),
338-
jenkins_build_number: currentBuild.number,
339-
unity_build_number: unityBuildNumber(),
340-
commit_sha: env.GIT_COMMIT_SHA_SHORT
342+
code_coverage: ["f", coverage.lineCoverage],
343+
size: ["i", size],
344+
duration_unity: ["i", timers.getDuration("Unity.${platform}")],
345+
duration_xcode: ["i", timers.getDuration("Xcode.${platform}")],
346+
jenkins_build_number: ["i", currentBuild.number],
347+
unity_build_number: ["i", unityBuildNumber()],
348+
commit_sha: ["s", env.GIT_COMMIT_SHA_SHORT]
341349
]
342350
)
343351
```
@@ -427,3 +435,20 @@ Gradle needs Java runtime, and the version of Gradle used in this project uses J
427435
```
428436
export JAVA_HOME=/usr/local/opt/openjdk@17
429437
```
438+
439+
### Debug Output
440+
441+
During development it can be useful to get output from tests to the console.
442+
443+
```groovy
444+
@Test
445+
void foo_SomeBar_GetSomeBaz() {
446+
println(someObjectToDebug)
447+
}
448+
```
449+
450+
Enable log info level to display `println` statements in the test output.
451+
452+
```sh
453+
./gradlew test --info
454+
```

src/com/bitbebop/InfluxDB.groovy

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.bitbebop
2+
3+
/**
4+
* Collects measurements for writing to InfluxDB.
5+
*
6+
* The provided measurement data is transformed to InfluxDB line protocol.
7+
* https://docs.influxdata.com/influxdb/v2.6/reference/syntax/line-protocol/
8+
*/
9+
class InfluxDB {
10+
private def measurements = []
11+
12+
/**
13+
* Add a measurement for writing to InfluxDB.
14+
*
15+
* @param String measurement The measurement to write data to.
16+
* @param Map tags The measurement tags.
17+
* @param Map fields The measurement fields, each field is an array
18+
* with type and value.
19+
*/
20+
def addMeasurement(String measurement, def tags, def fields) {
21+
22+
def tagsString = tags.collect { /$it.key=$it.value/ } join ","
23+
if (tagsString.length() > 0) {
24+
tagsString = ",${tagsString}"
25+
}
26+
27+
def fieldsString = fields.collect {
28+
// Note for future similar functionality:
29+
// I tried using a switch statement instead of else if. While that
30+
// works in the test ebv, the Jenkins instance couldn't handle it.
31+
if (it.value[0] == "f") {
32+
/$it.key=${it.value[1]}/
33+
} else if (it.value[0] == "i") {
34+
/$it.key=${it.value[1]}i/
35+
} else if (it.value[0] == "s") {
36+
/$it.key="${it.value[1]}"/
37+
}
38+
} join ","
39+
40+
def line = "${measurement}${tagsString} ${fieldsString}"
41+
measurements.add(line)
42+
}
43+
44+
/**
45+
* Get the array of line protocol formatted strings, that can be written to
46+
* InfluxDB.
47+
*/
48+
def getMeasurements() {
49+
return measurements
50+
}
51+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import org.junit.*
2+
import com.lesfurets.jenkins.unit.BasePipelineTest
3+
import static groovy.test.GroovyAssert.*
4+
5+
import com.bitbebop.InfluxDB
6+
7+
class InfluxDBTests extends BasePipelineTest {
8+
@Test
9+
void addMeasurement_NoTag_SkipsTagSegment() {
10+
def influxDB = new InfluxDB();
11+
influxDB.addMeasurement("foo", [:], [a_float: ["f", 123.45]]
12+
)
13+
14+
def measurements = influxDB.getMeasurements()
15+
assertEquals "No Tag:", /foo a_float=123.45/, measurements[0].toString()
16+
}
17+
18+
@Test
19+
void addMeasurement_WithTag_AddsTagSegment() {
20+
def influxDB = new InfluxDB();
21+
influxDB.addMeasurement("foo", [some_tag:"tag_value"], [a_float: ["f", 123.45]]
22+
)
23+
24+
def measurements = influxDB.getMeasurements()
25+
assertEquals "With Tag:", /foo,some_tag=tag_value a_float=123.45/, measurements[0].toString()
26+
}
27+
28+
@Test
29+
void addMeasurement_WithMultipleTags_AddsJoinedTagSegment() {
30+
def influxDB = new InfluxDB();
31+
influxDB.addMeasurement("foo", [some_tag:"tag_value", some_other_tag:"another_tag_value"], [a_float: ["f", 123.45]]
32+
)
33+
34+
def measurements = influxDB.getMeasurements()
35+
assertEquals "With Multiple Tags:", /foo,some_tag=tag_value,some_other_tag=another_tag_value a_float=123.45/, measurements[0].toString()
36+
}
37+
38+
@Test
39+
void addMeasurement_FloatDataType_RemainsAsIs() {
40+
def influxDB = new InfluxDB();
41+
influxDB.addMeasurement("foo", [:], [a_float: ["f", 123.45]]
42+
)
43+
44+
def measurements = influxDB.getMeasurements()
45+
assertEquals "Float Datatype:", /foo a_float=123.45/, measurements[0].toString()
46+
}
47+
48+
@Test
49+
void addMeasurement_IntDataType_EndsWithi() {
50+
def influxDB = new InfluxDB();
51+
influxDB.addMeasurement("foo", [:], [an_int: ["i", 123]]
52+
)
53+
54+
def measurements = influxDB.getMeasurements()
55+
assertEquals "Int Datatype:", /foo an_int=123i/, measurements[0].toString()
56+
}
57+
58+
@Test
59+
void addMeasurement_StringDataType_HasQuotes() {
60+
def influxDB = new InfluxDB();
61+
influxDB.addMeasurement("foo", [:], [a_str: ["s", "some string"]]
62+
)
63+
64+
def measurements = influxDB.getMeasurements()
65+
assertEquals "String Datatype:", /foo a_str="some string"/, measurements[0].toString()
66+
}
67+
68+
@Test
69+
void addMeasurement_WithMultipleFields_FieldsAreJoined() {
70+
def influxDB = new InfluxDB();
71+
influxDB.addMeasurement("foo", [:], [a_str: ["s", "some string"], an_int: ["i", 123]]
72+
)
73+
74+
def measurements = influxDB.getMeasurements()
75+
assertEquals "String Datatype:", /foo a_str="some string",an_int=123i/, measurements[0].toString()
76+
}
77+
78+
}

vars/influxdb.groovy

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
* Measurements are collected with the addMeasurement method. Calling the write
66
* method will write all collected measurements in the same call to InfluxDB.
77
*/
8+
import com.bitbebop.InfluxDB
89

9-
// Array that holds the measurements to write to InfluxDB.
10-
@groovy.transform.Field private def measurements = []
10+
@groovy.transform.Field private def influxDB = new InfluxDB()
1111

1212
/**
1313
* Add a measurement for writing to InfluxDB.
@@ -16,32 +16,31 @@
1616
* https://docs.influxdata.com/influxdb/v2.6/reference/syntax/line-protocol/
1717
*
1818
* @param String measurement The measurement to write data to.
19-
* @param Map tags The measurement tags.
20-
* @param Maps fields The measurement fields.
19+
* @param Map tags The measurement tags.
20+
* @param Map fields The measurement fields, each field is an array
21+
* with type and value.
2122
*/
2223
def addMeasurement(String measurement, def tags, def fields) {
24+
influxDB.addMeasurement(measurement, tags, fields)
25+
}
2326

24-
def tagsString = tags.collect { /$it.key=$it.value/ } join ","
25-
if (tagsString.length() > 0) {
26-
tagsString = ",${tagsString}"
27-
}
28-
29-
def fieldsString = fields.collect { it.value instanceof String ? /$it.key="$it.value"/ : /$it.key=$it.value/ } join ","
30-
31-
def line = "${measurement}${tagsString} ${fieldsString}"
32-
measurements.add(line)
27+
/**
28+
* Get the array of line protocol formatted strings.
29+
*/
30+
def getMeasurements() {
31+
return influxDB.getMeasurements()
3332
}
3433

3534
/**
3635
* Write all added measurements to InfluxDB.
3736
*
38-
* @param String host The host address to InfluxDB. Include http/https. No trailing slash.
39-
* @param String org The InfluxDB organization.
37+
* @param String host The host address to InfluxDB. Include http/https. No trailing slash.
38+
* @param String org The InfluxDB organization.
4039
* @param String bucket The bucket to write to.
41-
* @param String token The InfluxDB API token to use for authentication.
40+
* @param String token The InfluxDB API token to use for authentication.
4241
*/
4342
def write(String host, String org, String bucket, String token) {
44-
if (this.measurements.size() == 0) {
43+
if (getMeasurements().size() == 0) {
4544
return
4645
}
4746

@@ -51,5 +50,5 @@ def write(String host, String org, String bucket, String token) {
5150
'--header "Content-Type: text/plain; charset=utf-8" ' +
5251
'--header "Accept: application/json" ' +
5352
'--fail-with-body ' +
54-
"--data-binary '${this.measurements.join('\n')}'"
53+
"--data-binary '${getMeasurements().join('\n')}'"
5554
}

0 commit comments

Comments
 (0)