Skip to content

Commit bbb1b32

Browse files
committed
Add InfluxDB.now and InfluxDB::Client#now
1 parent f4e4ebc commit bbb1b32

File tree

3 files changed

+110
-42
lines changed

3 files changed

+110
-42
lines changed

README.md

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Maintained by [@toddboom](https://github.com/toddboom) and [@dmke](https://githu
1414
- [Usage](#usage)
1515
- [Creating a client](#creating-a-client)
1616
- [Writing data](#writing-data)
17-
- [A Note About Time Precision](#a-note-about-time-precision)
17+
- [A Note About Time Precision](#a-note-about-time-precision)
1818
- [Querying](#querying)
1919
- [Advanced Topics](#advanced-topics)
2020
- [Administrative tasks](#administrative-tasks)
@@ -145,34 +145,8 @@ influxdb.write_point(name, data)
145145
influxdb.write_point(name, data, time_precision)
146146
```
147147

148-
### A Note About Time Precision
149-
150-
The default precision in this gem is `"s"` (second), as Ruby's `Time#to_i`
151-
operates on this resolution.
152-
153-
If you write data points with sub-second resolution, you _have_ to configure
154-
your client instance with a more granular `time_precision` option **and** you
155-
need to provide timestamp values which reflect this precision. **If you don't do
156-
this, your points will be squashed!**
157-
158-
> A point is uniquely identified by the measurement name, tag set, and
159-
> timestamp. If you submit a new point with the same measurement, tag set, and
160-
> timestamp as an existing point, the field set becomes the union of the old
161-
> field set and the new field set, where any ties go to the new field set. This
162-
> is the intended behavior.
163-
164-
See [How does InfluxDB handle duplicate points?][docs-faq] for details.
165-
166-
For example, this is how to specify millisecond precision (which moves the
167-
pitfall from the second- to the millisecond barrier):
168-
169-
```ruby
170-
influxdb = InfluxDB::Client.new(time_precision: "ms")
171-
time = (Time.now.to_r * 1000).to_i
172-
# A faster, albeit less readable alternative:
173-
# time = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
174-
influxdb.write_point("foobar", { values: { n: 42 }, timestamp: time })
175-
```
148+
> **Attention:** Please also read the
149+
> [note about time precision](#a-note-about-time-precision) below.
176150
177151
Allowed values for `time_precision` are:
178152

@@ -337,6 +311,56 @@ influxdb = InfluxDB::Client.new(
337311
influxdb.write_point('hitchhiker', { values: { value: 666 } })
338312
```
339313

314+
### A Note About Time Precision
315+
316+
The default precision in this gem is `"s"` (second), as Ruby's `Time#to_i`
317+
operates on this resolution.
318+
319+
If you write data points with sub-second resolution, you _have_ to configure
320+
your client instance with a more granular `time_precision` option **and** you
321+
need to provide timestamp values which reflect this precision. **If you don't do
322+
this, your points will be squashed!**
323+
324+
> A point is uniquely identified by the measurement name, tag set, and
325+
> timestamp. If you submit a new point with the same measurement, tag set, and
326+
> timestamp as an existing point, the field set becomes the union of the old
327+
> field set and the new field set, where any ties go to the new field set. This
328+
> is the intended behavior.
329+
330+
See [How does InfluxDB handle duplicate points?][docs-faq] for details.
331+
332+
For example, this is how to specify millisecond precision (which moves the
333+
pitfall from the second- to the millisecond barrier):
334+
335+
```ruby
336+
client = InfluxDB::Client.new(time_precision: "ms")
337+
time = (Time.now.to_r * 1000).to_i
338+
client.write_point("foobar", { values: { n: 42 }, timestamp: time })
339+
```
340+
341+
For convenience, InfluxDB provides a few helper methods:
342+
343+
```ruby
344+
# to get a timestamp with the precision configured in the client:
345+
client.now
346+
347+
# to get a timestamp with the given precision:
348+
InfluxDB.now(time_precision)
349+
350+
# to convert a Time into a timestamp with the given precision:
351+
InfluxDB.convert_timestamp(Time.now, time_precision)
352+
```
353+
354+
As with `client.write_point`, allowed values for `time_precision` are:
355+
356+
- `"ns"` or `nil` for nanosecond
357+
- `"u"` for microsecond
358+
- `"ms"` for millisecond
359+
- `"s"` for second
360+
- `"m"` for minute
361+
- `"h"` for hour
362+
363+
[docs-faq]: http://docs.influxdata.com/influxdb/v1.7/troubleshooting/frequently-asked-questions/#how-does-influxdb-handle-duplicate-points
340364

341365
### Querying
342366

lib/influxdb/client.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Client
4848
# +:verify_ssl+:: verify ssl server certificate?
4949
# +:ssl_ca_cert+:: ssl CA certificate, chainfile or CA path.
5050
# The system CA path is automatically included
51-
# +:retry:: number of times a failed request should be retried. Defaults to infinite.
51+
# +:retry+:: number of times a failed request should be retried. Defaults to infinite.
5252
def initialize(database = nil, **opts)
5353
opts[:database] = database if database.is_a? String
5454
@config = InfluxDB::Config.new(opts)
@@ -72,6 +72,10 @@ def stopped?
7272
@stopped
7373
end
7474

75+
def now
76+
InfluxDB.now(config.time_precision)
77+
end
78+
7579
private
7680

7781
def find_writer
Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
module InfluxDB #:nodoc:
2-
TIMESTAMP_CONVERSIONS = {
2+
# Converts a Time to a timestamp with the given precision.
3+
#
4+
# === Example
5+
#
6+
# InfluxDB.convert_timestamp(Time.now, "ms")
7+
# #=> 1543533308243
8+
def self.convert_timestamp(time, precision = "s")
9+
factor = TIME_PRECISION_FACTORS.fetch(precision) do
10+
raise ArgumentError, "invalid time precision: #{precision}"
11+
end
12+
13+
(time.to_r * factor).to_i
14+
end
15+
16+
# Returns the current timestamp with the given precision.
17+
#
18+
# Implementation detail: This does not create an intermediate Time
19+
# object with `Time.now`, but directly requests the CLOCK_REALTIME,
20+
# which in general is a bit faster.
21+
#
22+
# This is useful, if you want or need to shave off a few microseconds
23+
# from your measurement.
24+
#
25+
# === Examples
26+
#
27+
# InfluxDB.now("ns") #=> 1543612126401392625
28+
# InfluxDB.now("u") #=> 1543612126401392
29+
# InfluxDB.now("ms") #=> 1543612126401
30+
# InfluxDB.now("s") #=> 1543612126
31+
# InfluxDB.now("m") #=> 25726868
32+
# InfluxDB.now("h") #=> 428781
33+
def self.now(precision = "s")
34+
name, divisor = TIME_PRECISION_FACTORS.fetch(precision) do
35+
raise ArgumentError, "invalid time precision: #{precision}"
36+
end
37+
38+
time = Process.clock_gettime Process::CLOCK_REALTIME, name
39+
(time / divisor).to_i
40+
end
41+
42+
TIME_PRECISION_FACTORS = {
343
"ns" => 1e9.to_r,
444
nil => 1e9.to_r,
545
"u" => 1e6.to_r,
@@ -8,16 +48,16 @@ module InfluxDB #:nodoc:
848
"m" => 1.to_r / 60,
949
"h" => 1.to_r / 60 / 60,
1050
}.freeze
11-
private_constant :TIMESTAMP_CONVERSIONS
51+
private_constant :TIME_PRECISION_FACTORS
1252

13-
# Converts a Time to a timestamp with the given precision.
14-
#
15-
# `convert_timestamp(Time.now, "ms")` might return `1543533308243`.
16-
def self.convert_timestamp(time, time_precision)
17-
factor = TIMESTAMP_CONVERSIONS.fetch(time_precision) do
18-
raise "Invalid time precision: #{time_precision}"
19-
end
20-
21-
(time.to_r * factor).to_i
22-
end
53+
CLOCK_NAMES = {
54+
"ns" => [:nanosecond, 1],
55+
nil => [:nanosecond, 1],
56+
"u" => [:microsecond, 1],
57+
"ms" => [:millisecond, 1],
58+
"s" => [:second, 1],
59+
"m" => [:second, 1.to_r / 60],
60+
"h" => [:second, 1.to_r / 60 / 60],
61+
}.freeze
62+
private_constant :CLOCK_NAMES
2363
end

0 commit comments

Comments
 (0)