Skip to content

Commit 23d1cde

Browse files
authored
Implement write and query time precision (#231 #303)
1 parent 106e5c9 commit 23d1cde

16 files changed

+291
-32
lines changed

include/InfluxDB/InfluxDB.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,18 @@
2828
#ifndef INFLUXDATA_INFLUXDB_H
2929
#define INFLUXDATA_INFLUXDB_H
3030

31-
#include <chrono>
3231
#include <memory>
3332
#include <string>
3433
#include <vector>
3534
#include <deque>
3635

3736
#include "InfluxDB/Transport.h"
3837
#include "InfluxDB/Point.h"
38+
#include "InfluxDB/TimePrecision.h"
3939
#include "InfluxDB/influxdb_export.h"
4040

4141
namespace influxdb
4242
{
43-
4443
class INFLUXDB_EXPORT InfluxDB
4544
{
4645
public:
@@ -89,8 +88,13 @@ namespace influxdb
8988
/// \param cmd
9089
std::string execute(const std::string& cmd);
9190

91+
/// Sets the timestamp precision
92+
/// \param precision
93+
void setTimePrecision(TimePrecision precision);
94+
9295
private:
9396
void addPointToBatch(Point&& point);
97+
std::string joinLineProtocolBatch() const;
9498

9599
/// line protocol batch to be written
96100
std::deque<Point> mPointBatch;
@@ -110,7 +114,7 @@ namespace influxdb
110114
/// List of global tags
111115
std::string mGlobalTags;
112116

113-
std::string joinLineProtocolBatch() const;
117+
TimePrecision timePrecision;
114118
};
115119

116120
} // namespace influxdb

include/InfluxDB/TimePrecision.h

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

include/InfluxDB/Transport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define INFLUXDATA_TRANSPORTINTERFACE_H
3030

3131
#include "InfluxDB/InfluxDBException.h"
32+
#include "InfluxDB/TimePrecision.h"
3233
#include "InfluxDB/influxdb_export.h"
3334
#include "InfluxDB/Proxy.h"
3435

@@ -69,6 +70,11 @@ namespace influxdb
6970
{
7071
throw InfluxDBException{"Proxy is not supported by the selected transport"};
7172
}
73+
74+
virtual void setTimePrecision([[maybe_unused]] TimePrecision precision)
75+
{
76+
throw InfluxDBException{"Time precision is not supported by the selected transport"};
77+
}
7278
};
7379

7480
} // namespace influxdb

src/HTTP.cxx

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,14 @@ namespace influxdb::transports
8282
std::string HTTP::query(const std::string& query)
8383
{
8484
session.SetUrl(cpr::Url{endpointUrl + "/query"});
85-
session.SetParameters(cpr::Parameters{{"db", databaseName}, {"q", query}});
85+
86+
cpr::Parameters params{{"db", databaseName}, {"q", query}};
87+
88+
if (!timePrecision.empty())
89+
{
90+
params.Add({"precision", timePrecision});
91+
}
92+
session.SetParameters(std::move(params));
8693

8794
const auto response = session.Get();
8895
checkResponse(response);
@@ -104,7 +111,14 @@ namespace influxdb::transports
104111
{
105112
session.SetUrl(cpr::Url{endpointUrl + "/write"});
106113
session.UpdateHeader(cpr::Header{{"Content-Type", "application/json"}});
107-
session.SetParameters(cpr::Parameters{{"db", databaseName}});
114+
115+
cpr::Parameters params{{"db", databaseName}};
116+
117+
if (!timePrecision.empty())
118+
{
119+
params.Add({"precision", timePrecision});
120+
}
121+
session.SetParameters(std::move(params));
108122
session.SetBody(cpr::Body{lineprotocol});
109123

110124
const auto response = session.Post();
@@ -133,6 +147,32 @@ namespace influxdb::transports
133147
session.SetConnectTimeout(timeout);
134148
}
135149

150+
void HTTP::setTimePrecision(TimePrecision precision)
151+
{
152+
switch (precision)
153+
{
154+
case TimePrecision::Hours:
155+
timePrecision = "h";
156+
break;
157+
case TimePrecision::Minutes:
158+
timePrecision = "m";
159+
break;
160+
case TimePrecision::Seconds:
161+
timePrecision = "s";
162+
break;
163+
case TimePrecision::MilliSeconds:
164+
timePrecision = "ms";
165+
break;
166+
case TimePrecision::MicroSeconds:
167+
timePrecision = "u";
168+
break;
169+
case TimePrecision::NanoSeconds:
170+
default:
171+
timePrecision = "ns";
172+
break;
173+
}
174+
}
175+
136176
std::string HTTP::execute(const std::string& cmd)
137177
{
138178
session.SetUrl(cpr::Url{endpointUrl + "/query"});

src/HTTP.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#define INFLUXDATA_TRANSPORTS_HTTP_H
3030

3131
#include "InfluxDB/Transport.h"
32-
#include <memory>
32+
#include "InfluxDB/TimePrecision.h"
3333
#include <string>
3434
#include <chrono>
3535
#include <cpr/cpr.h>
@@ -74,10 +74,12 @@ namespace influxdb::transports
7474

7575
void setVerifyCertificate(bool verify);
7676
void setTimeout(std::chrono::milliseconds timeout);
77+
void setTimePrecision(TimePrecision precision) override;
7778

7879
private:
7980
std::string endpointUrl;
8081
std::string databaseName;
82+
std::string timePrecision;
8183
cpr::Session session;
8284
};
8385

src/InfluxDB.cxx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "InfluxDB/InfluxDBException.h"
3030
#include "LineProtocol.h"
3131
#include "BoostSupport.h"
32-
#include <iostream>
3332
#include <memory>
3433
#include <string>
3534

@@ -41,7 +40,8 @@ namespace influxdb
4140
mIsBatchingActivated{false},
4241
mBatchSize{0},
4342
mTransport(std::move(transport)),
44-
mGlobalTags{}
43+
mGlobalTags{},
44+
timePrecision{TimePrecision::NanoSeconds}
4545
{
4646
if (mTransport == nullptr)
4747
{
@@ -78,7 +78,7 @@ namespace influxdb
7878
{
7979
std::string joinedBatch;
8080

81-
LineProtocol formatter{mGlobalTags};
81+
LineProtocol formatter{mGlobalTags, timePrecision};
8282
for (const auto& point : mPointBatch)
8383
{
8484
joinedBatch += formatter.format(point) + "\n";
@@ -113,7 +113,7 @@ namespace influxdb
113113
}
114114
else
115115
{
116-
LineProtocol formatter{mGlobalTags};
116+
LineProtocol formatter{mGlobalTags, timePrecision};
117117
transmit(formatter.format(point));
118118
}
119119
}
@@ -130,7 +130,7 @@ namespace influxdb
130130
else
131131
{
132132
std::string lineProtocol;
133-
LineProtocol formatter{mGlobalTags};
133+
LineProtocol formatter{mGlobalTags, timePrecision};
134134

135135
for (const auto& point : points)
136136
{
@@ -147,6 +147,12 @@ namespace influxdb
147147
return mTransport->execute(cmd);
148148
}
149149

150+
void InfluxDB::setTimePrecision(TimePrecision precision)
151+
{
152+
timePrecision = precision;
153+
mTransport->setTimePrecision(precision);
154+
}
155+
150156
void InfluxDB::addPointToBatch(Point&& point)
151157
{
152158
mPointBatch.emplace_back(std::move(point));

src/LineProtocol.cxx

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,30 @@ namespace influxdb
125125

126126
return convert.str();
127127
}
128-
}
129-
LineProtocol::LineProtocol()
130-
: LineProtocol(std::string{})
131-
{
128+
129+
std::string toPrecision(TimePrecision precision, std::chrono::time_point<std::chrono::system_clock> timestamp)
130+
{
131+
switch (precision)
132+
{
133+
case TimePrecision::Hours:
134+
return std::to_string(std::chrono::duration_cast<std::chrono::hours>(timestamp.time_since_epoch()).count());
135+
case TimePrecision::Minutes:
136+
return std::to_string(std::chrono::duration_cast<std::chrono::minutes>(timestamp.time_since_epoch()).count());
137+
case TimePrecision::Seconds:
138+
return std::to_string(std::chrono::duration_cast<std::chrono::seconds>(timestamp.time_since_epoch()).count());
139+
case TimePrecision::MilliSeconds:
140+
return std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(timestamp.time_since_epoch()).count());
141+
case TimePrecision::MicroSeconds:
142+
return std::to_string(std::chrono::duration_cast<std::chrono::microseconds>(timestamp.time_since_epoch()).count());
143+
case TimePrecision::NanoSeconds:
144+
default:
145+
return std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(timestamp.time_since_epoch()).count());
146+
}
147+
}
132148
}
133149

134-
LineProtocol::LineProtocol(const std::string& tags)
135-
: globalTags(tags)
150+
LineProtocol::LineProtocol(const std::string& tags, TimePrecision precision)
151+
: globalTags(tags), timePrecision(precision)
136152
{
137153
}
138154

@@ -143,8 +159,7 @@ namespace influxdb
143159
appendIfNotEmpty(line, formatTags(point.getTagSet()), ',');
144160
appendIfNotEmpty(line, formatFields(point.getFieldSet()), ' ');
145161

146-
return line.append(" ")
147-
.append(std::to_string(std::chrono::duration_cast<std::chrono::nanoseconds>(point.getTimestamp().time_since_epoch()).count()));
162+
return line.append(" ").append(toPrecision(timePrecision, point.getTimestamp()));
148163
}
149164

150165
std::string LineProtocol::EscapeStringElement(LineProtocol::ElementType type, std::string_view element)

src/LineProtocol.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#pragma once
2424

2525
#include "InfluxDB/Point.h"
26+
#include "InfluxDB/TimePrecision.h"
2627

2728
#include <string>
2829

@@ -31,9 +32,8 @@ namespace influxdb
3132
class LineProtocol
3233
{
3334
public:
34-
LineProtocol();
3535
// Caller must ensure that the tags string is correctly escaped
36-
explicit LineProtocol(const std::string& tags);
36+
LineProtocol(const std::string& tags, TimePrecision precision);
3737

3838
std::string format(const Point& point) const;
3939

@@ -53,5 +53,6 @@ namespace influxdb
5353

5454
private:
5555
std::string globalTags;
56+
TimePrecision timePrecision;
5657
};
5758
}

src/UDP.cxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,8 @@ namespace influxdb::transports
5656
}
5757
}
5858

59+
void UDP::setTimePrecision([[maybe_unused]] TimePrecision precision)
60+
{
61+
}
62+
5963
} // namespace influxdb::transports

src/UDP.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ namespace influxdb::transports
4747
/// Sends blob via UDP
4848
void send(std::string&& message) override;
4949

50+
void setTimePrecision(TimePrecision precision) override;
51+
5052
private:
5153
/// Boost Asio I/O functionality
5254
boost::asio::io_context mIoContext;

src/UriParser.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#ifndef INFLUXDATA_HTTPPARSER_H
2121
#define INFLUXDATA_HTTPPARSER_H
2222

23-
#include <iostream>
2423
#include <string>
2524
#include <stdlib.h>
2625

0 commit comments

Comments
 (0)