Skip to content

Commit 4fda495

Browse files
authored
Merge pull request #107 from bonitoo-io/feat/default-tags
feat: default tags
2 parents 3a57696 + b8d719e commit 4fda495

File tree

7 files changed

+141
-8
lines changed

7 files changed

+141
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22
## 3.5.0 [in progress]
33
### Features
4+
- [#107](https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino/pull/107) - Added possibility to set default tags. Use `WriteOptions::addDefaultTag()` to add a tag that will be added to each written point using the `writePoint()` function.
45

56
### Documentation
67

src/InfluxDbClient.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ void InfluxDBClient::setWriteOptions(const WriteOptions & writeOptions) {
291291
_writeOptions._retryInterval = writeOptions._retryInterval;
292292
_writeOptions._maxRetryInterval = writeOptions._maxRetryInterval;
293293
_writeOptions._maxRetryAttempts = writeOptions._maxRetryAttempts;
294+
_writeOptions._defaultTags = writeOptions._defaultTags;
294295
}
295296

296297
void InfluxDBClient::setHTTPOptions(const HTTPOptions & httpOptions) {
@@ -339,7 +340,7 @@ bool InfluxDBClient::writePoint(Point & point) {
339340
if(_writeOptions._writePrecision != WritePrecision::NoTime && !point.hasTime()) {
340341
point.setTime(_writeOptions._writePrecision);
341342
}
342-
String line = point.toLineProtocol();
343+
String line = point.toLineProtocol(_writeOptions._defaultTags);
343344
return writeRecord(line);
344345
}
345346
return false;

src/Options.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
*
3+
* Options.cpp: InfluxDB Client write options and HTTP options
4+
*
5+
* MIT License
6+
*
7+
* Copyright (c) 2020 InfluxData
8+
*
9+
* Permission is hereby granted, free of charge, to any person obtaining a copy
10+
* of this software and associated documentation files (the "Software"), to deal
11+
* in the Software without restriction, including without limitation the rights
12+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
* copies of the Software, and to permit persons to whom the Software is
14+
* furnished to do so, subject to the following conditions:
15+
*
16+
* The above copyright notice and this permission notice shall be included in all
17+
* copies or substantial portions of the Software.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
* SOFTWARE.
26+
*/
27+
#include <Arduino.h>
28+
#include "Options.h"
29+
#include "util/helpers.h"
30+
31+
WriteOptions& WriteOptions::addDefaultTag(String name, String value) {
32+
if(_defaultTags.length() > 0) {
33+
_defaultTags += ',';
34+
}
35+
_defaultTags += escapeKey(name);
36+
_defaultTags += '=';
37+
_defaultTags += escapeKey(value);
38+
return *this;
39+
}

src/Options.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class WriteOptions {
5959
uint16_t _maxRetryInterval;
6060
// Maximum count of retry attempts of failed writes, default 3
6161
uint16_t _maxRetryAttempts;
62+
// Default tags. Default tags are added to every written point.
63+
// There cannot be duplicate tags in default tags and tags included in a point.
64+
String _defaultTags;
6265
public:
6366
WriteOptions():
6467
_writePrecision(WritePrecision::NoTime),
@@ -76,6 +79,8 @@ class WriteOptions {
7679
WriteOptions& retryInterval(uint16_t retryIntervalSec) { _retryInterval = retryIntervalSec; return *this; }
7780
WriteOptions& maxRetryInterval(uint16_t maxRetryIntervalSec) { _maxRetryInterval = maxRetryIntervalSec; return *this; }
7881
WriteOptions& maxRetryAttempts(uint16_t maxRetryAttempts) { _maxRetryAttempts = maxRetryAttempts; return *this; }
82+
WriteOptions& addDefaultTag(String name, String value);
83+
WriteOptions& clearDefaultTags() { _defaultTags = (char *)nullptr; return *this; }
7984
};
8085

8186
/**

src/Point.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,17 @@ void Point::putField(String name, String value) {
5959
_fields += value;
6060
}
6161

62-
String Point::toLineProtocol() const {
62+
String Point::toLineProtocol(String includeTags) const {
6363
String line = _measurement;
64-
line.reserve(1 + _tags.length() + 1 + _fields.length() + 1 + _timestamp.length());
64+
line.reserve(1 + _tags.length() + 1 + includeTags.length() + 1 + _fields.length() + 1 + _timestamp.length());
6565
if(hasTags()) {
6666
line += ",";
6767
line += _tags;
6868
}
69+
if(includeTags.length()>0) {
70+
line += ",";
71+
line += includeTags;
72+
}
6973
if(hasFields()) {
7074
line += " ";
7175
line += _fields;

src/Point.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ class Point {
6767
bool hasTags() const { return _tags.length() > 0; }
6868
// True if a point contains timestamp
6969
bool hasTime() const { return _timestamp.length() > 0; }
70-
// Creates line protocol
71-
String toLineProtocol() const;
70+
// Creates line protocol with optionaly added tags
71+
String toLineProtocol(String includeTags = "") const;
7272
// returns current timestamp
7373
String getTime() const { return _timestamp; }
7474
protected:

test/test.ino

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ private:
7575
static void testServerTempDownBatchsize5();
7676
static void testRetriesOnServerOverload();
7777
static void testRetryInterval();
78+
static void testDefaultTags();
7879
};
7980

8081
void loop() {
@@ -88,8 +89,8 @@ void loop() {
8889
void Test::run() {
8990
// Basic tests
9091
testOptions();
91-
testEcaping();
9292
testPoint();
93+
testEcaping();
9394
testFluxTypes();
9495
testFluxParserEmpty();
9596
testFluxParserSingleTable();
@@ -106,6 +107,7 @@ void Test::run() {
106107
testV1();
107108
testUserAgent();
108109
testHTTPReadTimeout();
110+
testDefaultTags();
109111
// Advanced tests
110112
testFailedWrites();
111113
testTimestamp();
@@ -127,15 +129,17 @@ void Test::testOptions() {
127129
TEST_ASSERT(defWO._retryInterval == 5);
128130
TEST_ASSERT(defWO._maxRetryInterval == 300);
129131
TEST_ASSERT(defWO._maxRetryAttempts == 3);
132+
TEST_ASSERT(defWO._defaultTags.length() == 0);
130133

131-
defWO = WriteOptions().writePrecision(WritePrecision::NS).batchSize(10).bufferSize(20).flushInterval(120).retryInterval(1).maxRetryInterval(20).maxRetryAttempts(5);
134+
defWO = WriteOptions().writePrecision(WritePrecision::NS).batchSize(10).bufferSize(20).flushInterval(120).retryInterval(1).maxRetryInterval(20).maxRetryAttempts(5).addDefaultTag("tag1","val1").addDefaultTag("tag2","val2");
132135
TEST_ASSERT(defWO._writePrecision == WritePrecision::NS);
133136
TEST_ASSERT(defWO._batchSize == 10);
134137
TEST_ASSERT(defWO._bufferSize == 20);
135138
TEST_ASSERT(defWO._flushInterval == 120);
136139
TEST_ASSERT(defWO._retryInterval == 1);
137140
TEST_ASSERT(defWO._maxRetryInterval == 20);
138141
TEST_ASSERT(defWO._maxRetryAttempts == 5);
142+
TEST_ASSERT(defWO._defaultTags == "tag1=val1,tag2=val2");
139143

140144
HTTPOptions defHO;
141145
TEST_ASSERT(!defHO._connectionReuse);
@@ -200,9 +204,16 @@ void Test::testEcaping() {
200204
p.addField("fie ld", "val ue");
201205
p.addField("fie,ld", "val,ue");
202206
p.addField("fie\"ld", "val\"ue");
207+
203208

204209
String line = p.toLineProtocol();
205-
TEST_ASSERTM(line == "t\\\re=s\\\nt\\\t_t\\ e\"s\\,t,ta\\=g=val\\=ue,ta\\\tg=val\\\tue,ta\\\rg=val\\\rue,ta\\\ng=val\\\nue,ta\\ g=valu\\ e,ta\\,g=valu\\,e,tag=value,ta\"g=val\"ue fie\\=ld=\"val=ue\",fie\\\tld=\"val\tue\",fie\\\rld=\"val\rue\",fie\\\nld=\"val\nue\",fie\\ ld=\"val ue\",fie\\,ld=\"val,ue\",fie\"ld=\"val\\\"ue\"", line);//
210+
TEST_ASSERTM(line == "t\\\re=s\\\nt\\\t_t\\ e\"s\\,t,ta\\=g=val\\=ue,ta\\\tg=val\\\tue,ta\\\rg=val\\\rue,ta\\\ng=val\\\nue,ta\\ g=valu\\ e,ta\\,g=valu\\,e,tag=value,ta\"g=val\"ue fie\\=ld=\"val=ue\",fie\\\tld=\"val\tue\",fie\\\rld=\"val\rue\",fie\\\nld=\"val\nue\",fie\\ ld=\"val ue\",fie\\,ld=\"val,ue\",fie\"ld=\"val\\\"ue\"", line);
211+
212+
WriteOptions w;
213+
w.addDefaultTag("dta=g","dval=ue");
214+
w.addDefaultTag("dtag","dvalue");
215+
line = p.toLineProtocol(w._defaultTags);
216+
TEST_ASSERTM(line == "t\\\re=s\\\nt\\\t_t\\ e\"s\\,t,ta\\=g=val\\=ue,ta\\\tg=val\\\tue,ta\\\rg=val\\\rue,ta\\\ng=val\\\nue,ta\\ g=valu\\ e,ta\\,g=valu\\,e,tag=value,ta\"g=val\"ue,dta\\=g=dval\\=ue,dtag=dvalue fie\\=ld=\"val=ue\",fie\\\tld=\"val\tue\",fie\\\rld=\"val\rue\",fie\\\nld=\"val\nue\",fie\\ ld=\"val ue\",fie\\,ld=\"val,ue\",fie\"ld=\"val\\\"ue\"", line);
206217
TEST_END();
207218
}
208219

@@ -233,6 +244,17 @@ void Test::testPoint() {
233244
String testLine = "test,tag1=tagvalue fieldInt=-23i,fieldBool=true,fieldFloat1=1.12,fieldFloat2=1.12345,fieldDouble1=1.12,fieldDouble2=1.12345,fieldChar=\"A\",fieldUChar=1i,fieldUInt=23i,fieldLong=123456i,fieldULong=123456i,fieldString=\"text test\"";
234245
TEST_ASSERTM(line == testLine, line);
235246

247+
String defaultTags="dtag=val";
248+
line = p.toLineProtocol(defaultTags);
249+
testLine = "test,tag1=tagvalue,dtag=val fieldInt=-23i,fieldBool=true,fieldFloat1=1.12,fieldFloat2=1.12345,fieldDouble1=1.12,fieldDouble2=1.12345,fieldChar=\"A\",fieldUChar=1i,fieldUInt=23i,fieldLong=123456i,fieldULong=123456i,fieldString=\"text test\"";
250+
TEST_ASSERTM(line == testLine, line);
251+
252+
p.clearTags();
253+
line = p.toLineProtocol(defaultTags);
254+
testLine = "test,dtag=val fieldInt=-23i,fieldBool=true,fieldFloat1=1.12,fieldFloat2=1.12345,fieldDouble1=1.12,fieldDouble2=1.12345,fieldChar=\"A\",fieldUChar=1i,fieldUInt=23i,fieldLong=123456i,fieldULong=123456i,fieldString=\"text test\"";
255+
TEST_ASSERTM(line == testLine, line);
256+
257+
236258
p.clearFields();
237259
p.clearTags();
238260

@@ -355,6 +377,7 @@ void Test::testBasicFunction() {
355377
deleteAll(INFLUXDB_CLIENT_TESTING_URL);
356378
}
357379

380+
358381
void Test::testInit() {
359382
TEST_INIT("testInit");
360383
{
@@ -1696,6 +1719,66 @@ void Test::testRetryInterval() {
16961719
deleteAll(INFLUXDB_CLIENT_TESTING_URL);
16971720
}
16981721

1722+
void Test::testDefaultTags() {
1723+
TEST_INIT("testDefaultTags");
1724+
1725+
InfluxDBClient client(INFLUXDB_CLIENT_TESTING_URL, INFLUXDB_CLIENT_TESTING_ORG, INFLUXDB_CLIENT_TESTING_BUC, INFLUXDB_CLIENT_TESTING_TOK);
1726+
1727+
TEST_ASSERT(waitServer(client, true));
1728+
for (int i = 0; i < 5; i++) {
1729+
Point *p = createPoint("test1");
1730+
p->addField("index", i);
1731+
TEST_ASSERT(client.writePoint(*p));
1732+
delete p;
1733+
}
1734+
String query = "select";
1735+
FluxQueryResult q = client.query(query);
1736+
TEST_ASSERTM(q.getError()=="", q.getError());
1737+
TEST_ASSERT(q.next());
1738+
TEST_ASSERTM(q.getColumnsName().size()==10,String(q.getColumnsName().size()));
1739+
TEST_ASSERT(q.next());
1740+
TEST_ASSERT(q.next());
1741+
TEST_ASSERT(q.next());
1742+
TEST_ASSERTM(q.getColumnsName().size()==10,String(q.getColumnsName().size())) ;
1743+
TEST_ASSERT(q.next());
1744+
TEST_ASSERT(!q.next());
1745+
q.close();
1746+
deleteAll(INFLUXDB_CLIENT_TESTING_URL);
1747+
1748+
client.setWriteOptions(WriteOptions().addDefaultTag("dtag1","dval1").addDefaultTag("dtag2","dval2"));
1749+
1750+
for (int i = 0; i < 5; i++) {
1751+
Point *p = createPoint("test1");
1752+
p->addField("index", i);
1753+
TEST_ASSERT(client.writePoint(*p));
1754+
delete p;
1755+
}
1756+
q = client.query(query);
1757+
TEST_ASSERTM(q.getError()=="", q.getError());
1758+
TEST_ASSERT(q.next());
1759+
TEST_ASSERTM(q.getColumnsName().size()==12,String(q.getColumnsName().size()));
1760+
TEST_ASSERTM(q.getValueByName("dtag1").getString() == "dval1", q.getValueByName("dtag1").getString());
1761+
TEST_ASSERTM(q.getValueByName("dtag2").getString() == "dval2", q.getValueByName("dtag2").getString());
1762+
TEST_ASSERT(q.next());
1763+
TEST_ASSERTM(q.getValueByName("dtag1").getString() == "dval1",q.getValueByName("dtag1").getString());
1764+
TEST_ASSERTM(q.getValueByName("dtag2").getString() == "dval2", q.getValueByName("dtag2").getString());
1765+
TEST_ASSERT(q.next());
1766+
TEST_ASSERTM(q.getValueByName("dtag1").getString() == "dval1",q.getValueByName("dtag1").getString());
1767+
TEST_ASSERTM(q.getValueByName("dtag2").getString() == "dval2", q.getValueByName("dtag2").getString());
1768+
TEST_ASSERT(q.next());
1769+
TEST_ASSERTM(q.getColumnsName().size()==12,String(q.getColumnsName().size())) ;
1770+
TEST_ASSERTM(q.getValueByName("dtag1").getString() == "dval1",q.getValueByName("dtag1").getString());
1771+
TEST_ASSERTM(q.getValueByName("dtag2").getString() == "dval2", q.getValueByName("dtag2").getString());
1772+
TEST_ASSERT(q.next());
1773+
TEST_ASSERTM(q.getValueByName("dtag1").getString() == "dval1",q.getValueByName("dtag1").getString());
1774+
TEST_ASSERTM(q.getValueByName("dtag2").getString() == "dval2", q.getValueByName("dtag2").getString());
1775+
TEST_ASSERT(!q.next());
1776+
q.close();
1777+
1778+
TEST_END();
1779+
deleteAll(INFLUXDB_CLIENT_TESTING_URL);
1780+
}
1781+
16991782
Point *createPoint(String measurement) {
17001783
Point *point = new Point(measurement);
17011784
point->addTag("SSID", WiFi.SSID());

0 commit comments

Comments
 (0)