redis-time-series 0.2.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +15 -0
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +10 -2
- data/README.md +164 -25
- data/bin/console +3 -9
- data/bin/setup +29 -6
- data/lib/ext/time_msec.rb +29 -0
- data/lib/redis-time-series.rb +8 -5
- data/lib/redis/time_series.rb +255 -65
- data/lib/redis/time_series/aggregation.rb +88 -0
- data/lib/redis/time_series/client.rb +77 -0
- data/lib/redis/time_series/errors.rb +19 -0
- data/lib/redis/time_series/filters.rb +169 -0
- data/lib/redis/time_series/info.rb +65 -10
- data/lib/redis/time_series/rule.rb +49 -0
- data/lib/redis/time_series/sample.rb +22 -6
- data/lib/redis/time_series/version.rb +6 -0
- data/redis-time-series.gemspec +4 -3
- metadata +24 -4
- data/lib/time/msec.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 461a6f3842867d1ba51440e7576aad3e9b92ecd02700cd59e5508c0e8bbfcaa7
|
4
|
+
data.tar.gz: 0c03af91af0eaaa37917db2cad21417c38709a53b223ed2864bad0f9857fa1f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56dcd4439b2f4f06469237d2925d84b2ffabc40e2dccb608d5489b78f0e2a5b299881487b55e67fb48f1c9d0f7f56951ee98254ae84229b1827fb4cf3683ca44
|
7
|
+
data.tar.gz: 860e638f906b9dc19358e6156ad6a0488452be0be499853926742073cf6e85d00f4e95755f1659feae9763334eebbab044147fa3d94512dbb2a91360ec08728b
|
data/.github/workflows/rspec.yml
CHANGED
@@ -16,13 +16,28 @@ jobs:
|
|
16
16
|
image: redislabs/redistimeseries:latest
|
17
17
|
ports:
|
18
18
|
- 6379:6379/tcp
|
19
|
+
env:
|
20
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
21
|
+
GIT_COMMIT_SHA: ${{ github.sha }}
|
22
|
+
GIT_BRANCH: ${{ github.head_ref }}
|
19
23
|
steps:
|
20
24
|
- uses: actions/checkout@v2
|
21
25
|
- name: Set up Ruby
|
22
26
|
uses: ruby/setup-ruby@v1
|
23
27
|
with:
|
24
28
|
ruby-version: 2.6
|
29
|
+
- name: Set up CodeClimate
|
30
|
+
run: |
|
31
|
+
curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
32
|
+
chmod +x ./cc-test-reporter
|
33
|
+
./cc-test-reporter before-build
|
25
34
|
- name: Install dependencies
|
26
35
|
run: bundle install
|
27
36
|
- name: Run specs
|
28
37
|
run: bundle exec rake spec
|
38
|
+
- name: Upload coverage report
|
39
|
+
run: ./cc-test-reporter after-build -t simplecov coverage/.resultset.json
|
40
|
+
- uses: actions/upload-artifact@v2
|
41
|
+
with:
|
42
|
+
name: coverage
|
43
|
+
path: coverage/
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,29 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 0.5.2
|
6
|
+
* Add chunk_type to info struct (#47)
|
7
|
+
|
8
|
+
## 0.5.1
|
9
|
+
* Update Info struct for RTS 1.4 compatibility (#45)
|
10
|
+
|
11
|
+
## 0.5.0
|
12
|
+
* Fix aggregations for TS.RANGE command (#34)
|
13
|
+
* Extract client handling into Client module (#32)
|
14
|
+
* Add `uncompressed` param to TS.ADD, TS.INCRBY, TS.DECRBY (#35)
|
15
|
+
* Add `Redis::TimeSeries::Rule` object (#38)
|
16
|
+
* Add [YARD documentation](https://rubydoc.info/gems/redis-time-series) (#40)
|
17
|
+
|
18
|
+
## 0.4.0
|
19
|
+
* Added [hash-based filter DSL](https://github.com/dzunk/redis-time-series/tree/7173c73588da50614c02f9c89bf2ecef77766a78#filter-dsl)
|
20
|
+
* Removed `Time#ts_msec` monkey-patch
|
21
|
+
* Renamed `TimeSeries.queryindex` to `.query_index`
|
22
|
+
* Added `TS.CREATERULE` and `TS.DELETERULE` commands
|
23
|
+
* Renamed `InvalidFilters` to `FilterError`
|
24
|
+
|
25
|
+
## 0.3.0
|
26
|
+
* Added `TS.QUERYINDEX` command
|
27
|
+
|
5
28
|
## 0.2.0
|
6
29
|
* Converted `#info` to a struct instead of a hash.
|
7
30
|
* Added methods on time series for getting info attributes.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
redis-time-series (0.
|
4
|
+
redis-time-series (0.5.2)
|
5
5
|
redis (~> 4.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -16,15 +16,17 @@ GEM
|
|
16
16
|
coderay (1.1.3)
|
17
17
|
concurrent-ruby (1.1.6)
|
18
18
|
diff-lcs (1.3)
|
19
|
+
docile (1.3.2)
|
19
20
|
i18n (1.8.3)
|
20
21
|
concurrent-ruby (~> 1.0)
|
22
|
+
json (2.3.1)
|
21
23
|
method_source (1.0.0)
|
22
24
|
minitest (5.14.1)
|
23
25
|
pry (0.13.1)
|
24
26
|
coderay (~> 1.1)
|
25
27
|
method_source (~> 1.0)
|
26
28
|
rake (13.0.1)
|
27
|
-
redis (4.2.
|
29
|
+
redis (4.2.2)
|
28
30
|
rspec (3.9.0)
|
29
31
|
rspec-core (~> 3.9.0)
|
30
32
|
rspec-expectations (~> 3.9.0)
|
@@ -38,6 +40,11 @@ GEM
|
|
38
40
|
diff-lcs (>= 1.2.0, < 2.0)
|
39
41
|
rspec-support (~> 3.9.0)
|
40
42
|
rspec-support (3.9.3)
|
43
|
+
simplecov (0.17.1)
|
44
|
+
docile (~> 1.1)
|
45
|
+
json (>= 1.8, < 3)
|
46
|
+
simplecov-html (~> 0.10.0)
|
47
|
+
simplecov-html (0.10.2)
|
41
48
|
thread_safe (0.3.6)
|
42
49
|
tzinfo (1.2.7)
|
43
50
|
thread_safe (~> 0.1)
|
@@ -53,6 +60,7 @@ DEPENDENCIES
|
|
53
60
|
rake (~> 13.0)
|
54
61
|
redis-time-series!
|
55
62
|
rspec (~> 3.0)
|
63
|
+
simplecov (< 0.18)
|
56
64
|
|
57
65
|
BUNDLED WITH
|
58
66
|
1.17.2
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-

|
1
|
+
[](https://github.com/dzunk/redis-time-series/actions?query=workflow%3ARSpec+branch%3Amaster)
|
2
|
+
[](https://badge.fury.io/rb/redis-time-series)
|
3
|
+
[](https://rubydoc.info/gems/redis-time-series)
|
4
|
+
[](https://codeclimate.com/github/dzunk/redis-time-series/maintainability)
|
5
|
+
[](https://codeclimate.com/github/dzunk/redis-time-series/test_coverage)
|
2
6
|
|
3
7
|
# RedisTimeSeries
|
4
8
|
|
@@ -72,6 +76,10 @@ Add a single value with a timestamp
|
|
72
76
|
```ruby
|
73
77
|
ts.add 1234, 3.minutes.ago # Used ActiveSupport here, but any Time object works fine
|
74
78
|
=> #<Redis::TimeSeries::Sample:0x00007fa6ce05f3f8 @time=2020-06-25 23:39:54 -0700, @value=0.1234e4>
|
79
|
+
|
80
|
+
# Optionally store data uncompressed
|
81
|
+
ts.add 5678, uncompressed: true
|
82
|
+
=> #<Redis::TimeSeries::Sample:0x00007f93f43cdf68 @time=2020-07-18 23:15:29 -0700, @value=0.5678e4>
|
75
83
|
```
|
76
84
|
Add multiple values with timestamps
|
77
85
|
```ruby
|
@@ -88,6 +96,10 @@ ts.increment # alias of incrby
|
|
88
96
|
=> 1593154255069
|
89
97
|
ts.decrement # alias of decrby
|
90
98
|
=> 1593154257344
|
99
|
+
|
100
|
+
# Optionally store data uncompressed
|
101
|
+
ts.incrby 4, uncompressed: true
|
102
|
+
=> 1595139299769
|
91
103
|
```
|
92
104
|
```ruby
|
93
105
|
ts.get
|
@@ -119,31 +131,53 @@ ts.get
|
|
119
131
|
```
|
120
132
|
Get a range of values
|
121
133
|
```ruby
|
122
|
-
|
134
|
+
# Time range as an argument
|
135
|
+
ts.range(10.minutes.ago..Time.current)
|
123
136
|
=> [#<Redis::TimeSeries::Sample:0x00007fa25f13fc28 @time=2020-06-25 23:50:51 -0700, @value=0.57e2>,
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
137
|
+
#<Redis::TimeSeries::Sample:0x00007fa25f13db58 @time=2020-06-25 23:50:55 -0700, @value=0.58e2>,
|
138
|
+
#<Redis::TimeSeries::Sample:0x00007fa25f13d900 @time=2020-06-25 23:50:57 -0700, @value=0.57e2>,
|
139
|
+
#<Redis::TimeSeries::Sample:0x00007fa25f13d680 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>]
|
140
|
+
|
141
|
+
# Time range as keyword args
|
142
|
+
ts.range(from: 10.minutes.ago, to: Time.current)
|
128
143
|
=> [#<Redis::TimeSeries::Sample:0x00007fa25dc01f00 @time=2020-06-25 23:50:51 -0700, @value=0.57e2>,
|
129
|
-
|
130
|
-
|
131
|
-
|
144
|
+
#<Redis::TimeSeries::Sample:0x00007fa25dc01d20 @time=2020-06-25 23:50:55 -0700, @value=0.58e2>,
|
145
|
+
#<Redis::TimeSeries::Sample:0x00007fa25dc01b68 @time=2020-06-25 23:50:57 -0700, @value=0.57e2>,
|
146
|
+
#<Redis::TimeSeries::Sample:0x00007fa25dc019b0 @time=2020-06-25 23:51:30 -0700, @value=0.58e2>]
|
147
|
+
|
148
|
+
# Limit number of results with count argument
|
149
|
+
ts.range(10.minutes.ago..Time.current, count: 2)
|
150
|
+
=> [#<Redis::TimeSeries::Sample:0x00007fa25dc01f00 @time=2020-06-25 23:50:51 -0700, @value=0.57e2>,
|
151
|
+
#<Redis::TimeSeries::Sample:0x00007fa25dc01d20 @time=2020-06-25 23:50:55 -0700, @value=0.58e2>]
|
152
|
+
|
153
|
+
# Apply aggregations to the range
|
154
|
+
ts.range(from: 10.minutes.ago, to: Time.current, aggregation: [:avg, 10.minutes])
|
155
|
+
=> [#<Redis::TimeSeries::Sample:0x00007fa25dc01f00 @time=2020-06-25 23:50:00 -0700, @value=0.575e2>]
|
132
156
|
```
|
133
157
|
Get info about the series
|
134
158
|
```ruby
|
135
159
|
ts.info
|
136
160
|
=> #<struct Redis::TimeSeries::Info
|
161
|
+
series=
|
162
|
+
#<Redis::TimeSeries:0x00007ff46da9b578 @key="ts3", @redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>>,
|
137
163
|
total_samples=3,
|
138
|
-
memory_usage=
|
139
|
-
first_timestamp=
|
140
|
-
last_timestamp=
|
164
|
+
memory_usage=4264,
|
165
|
+
first_timestamp=1595187993605,
|
166
|
+
last_timestamp=1595187993629,
|
141
167
|
retention_time=0,
|
142
168
|
chunk_count=1,
|
143
169
|
max_samples_per_chunk=256,
|
144
170
|
labels={"foo"=>"bar"},
|
145
171
|
source_key=nil,
|
146
|
-
rules=
|
172
|
+
rules=
|
173
|
+
[#<Redis::TimeSeries::Rule:0x00007ff46db30c68
|
174
|
+
@aggregation=#<Redis::TimeSeries::Aggregation:0x00007ff46db30c18 @duration=3600000, @type="avg">,
|
175
|
+
@destination_key="ts1",
|
176
|
+
@source=
|
177
|
+
#<Redis::TimeSeries:0x00007ff46da9b578
|
178
|
+
@key="ts3",
|
179
|
+
@redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>>>]>
|
180
|
+
|
147
181
|
# Each info property is also a method on the time series object
|
148
182
|
ts.memory_usage
|
149
183
|
=> 4208
|
@@ -151,6 +185,7 @@ ts.labels
|
|
151
185
|
=> {"foo"=>"bar"}
|
152
186
|
ts.total_samples
|
153
187
|
=> 3
|
188
|
+
|
154
189
|
# Total samples also available as #count, #length, and #size
|
155
190
|
ts.count
|
156
191
|
=> 3
|
@@ -159,36 +194,140 @@ ts.length
|
|
159
194
|
ts.size
|
160
195
|
=> 3
|
161
196
|
```
|
197
|
+
Find series matching specific label(s)
|
198
|
+
```ruby
|
199
|
+
Redis::TimeSeries.query_index('foo=bar')
|
200
|
+
=> [#<Redis::TimeSeries:0x00007fc115ba1610
|
201
|
+
@key="ts3",
|
202
|
+
@redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>,
|
203
|
+
@retention=nil,
|
204
|
+
@uncompressed=false>]
|
205
|
+
# Note that you need at least one "label equals value" filter
|
206
|
+
Redis::TimeSeries.query_index('foo!=bar')
|
207
|
+
=> RuntimeError: Filtering requires at least one equality comparison
|
208
|
+
# query_index is also aliased as .where for fluency
|
209
|
+
Redis::TimeSeries.where('foo=bar')
|
210
|
+
=> [#<Redis::TimeSeries:0x00007fb8981010c8
|
211
|
+
@key="ts3",
|
212
|
+
@redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>,
|
213
|
+
@retention=nil,
|
214
|
+
@uncompressed=false>]
|
215
|
+
```
|
216
|
+
### Filter DSL
|
217
|
+
You can provide filter strings directly, per the time series documentation.
|
218
|
+
```ruby
|
219
|
+
Redis::TimeSeries.where('foo=bar')
|
220
|
+
=> [#<Redis::TimeSeries:0x00007fb8981010c8...>]
|
221
|
+
```
|
222
|
+
There is also a hash-based syntax available, which may be more pleasant to work with.
|
223
|
+
```ruby
|
224
|
+
Redis::TimeSeries.where(foo: 'bar')
|
225
|
+
=> [#<Redis::TimeSeries:0x00007fb89811dca0...>]
|
226
|
+
```
|
227
|
+
All six filter types are represented in hash format below.
|
228
|
+
```ruby
|
229
|
+
{
|
230
|
+
foo: 'bar', # label=value (equality)
|
231
|
+
foo: { not: 'bar' }, # label!=value (inequality)
|
232
|
+
foo: true, # label= (presence)
|
233
|
+
foo: false, # label!= (absence)
|
234
|
+
foo: [1, 2], # label=(1,2) (any value)
|
235
|
+
foo: { not: [1, 2] } # label!=(1,2) (no values)
|
236
|
+
}
|
237
|
+
```
|
238
|
+
Note the special use of `true` and `false`. If you're representing a boolean value with a label, rather than setting its value to "true" or "false" (which would be treated as strings in Redis anyway), you should add or remove the label from the series.
|
239
|
+
|
240
|
+
Values can be any object that responds to `.to_s`:
|
241
|
+
```ruby
|
242
|
+
class Person
|
243
|
+
def initialize(name)
|
244
|
+
@name = name
|
245
|
+
end
|
246
|
+
|
247
|
+
def to_s
|
248
|
+
@name
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
Redis::TimeSeries.where(person: Person.new('John'))
|
253
|
+
#=> TS.QUERYINDEX person=John
|
254
|
+
```
|
255
|
+
|
256
|
+
### Compaction Rules
|
257
|
+
Add a compaction rule to a series.
|
258
|
+
```ruby
|
259
|
+
# Destintation time series needs to be created before the rule is added.
|
260
|
+
other_ts = Redis::TimeSeries.create('other_ts')
|
261
|
+
|
262
|
+
# Aggregation buckets are measured in milliseconds
|
263
|
+
ts.create_rule(dest: other_ts, aggregation: [:count, 60000]) # 1 minute
|
264
|
+
|
265
|
+
# Can provide a string key instead of a time series object
|
266
|
+
ts.create_rule(dest: 'other_ts', aggregation: [:avg, 120000])
|
267
|
+
|
268
|
+
# If you're using Rails or ActiveSupport, you can provide an
|
269
|
+
# ActiveSupport::Duration instead of an integer
|
270
|
+
ts.create_rule(dest: other_ts, aggregation: [:avg, 2.minutes])
|
271
|
+
|
272
|
+
# Can also provide an Aggregation object instead of an array
|
273
|
+
agg = Redis::TimeSeries::Aggregation.new(:avg, 120000)
|
274
|
+
ts.create_rule(dest: other_ts, aggregation: agg)
|
275
|
+
|
276
|
+
# Class-level method also available
|
277
|
+
Redis::TimeSeries.create_rule(source: ts, dest: other_ts, aggregation: ['std.p', 150000])
|
278
|
+
```
|
279
|
+
Get existing compaction rules
|
280
|
+
```ruby
|
281
|
+
ts.rules
|
282
|
+
=> [#<Redis::TimeSeries::Rule:0x00007ff46e91c728
|
283
|
+
@aggregation=#<Redis::TimeSeries::Aggregation:0x00007ff46e91c6d8 @duration=3600000, @type="avg">,
|
284
|
+
@destination_key="ts1",
|
285
|
+
@source=
|
286
|
+
#<Redis::TimeSeries:0x00007ff46da9b578 @key="ts3", @redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>>>]
|
287
|
+
|
288
|
+
# Get properties of a rule too
|
289
|
+
ts.rules.first.aggregation
|
290
|
+
=> #<Redis::TimeSeries::Aggregation:0x00007ff46d146d38 @duration=3600000, @type="avg">
|
291
|
+
ts.rules.first.destination
|
292
|
+
=> #<Redis::TimeSeries:0x00007ff46d8a3d60 @key="ts1", @redis=#<Redis client v4.2.1 for redis://127.0.0.1:6379/0>>
|
293
|
+
```
|
294
|
+
|
295
|
+
Remove an existing compaction rule
|
296
|
+
```ruby
|
297
|
+
ts.delete_rule(dest: 'other_ts')
|
298
|
+
ts.rules.first.delete
|
299
|
+
Redis::TimeSeries.delete_rule(source: ts, dest: 'other_ts')
|
300
|
+
```
|
301
|
+
|
162
302
|
|
163
303
|
### TODO
|
164
304
|
* `TS.REVRANGE`
|
165
305
|
* `TS.MRANGE`/`TS.MREVRANGE`
|
166
|
-
* `TS.QUERYINDEX`
|
167
|
-
* Compaction rules
|
168
|
-
* Filters
|
169
306
|
* Probably a bunch more stuff
|
170
307
|
|
171
308
|
## Development
|
172
309
|
|
173
|
-
After checking out the repo, run `bin/setup
|
310
|
+
After checking out the repo, run `bin/setup`. You need the `docker` daemon installed and running. This script will:
|
311
|
+
* Install gem dependencies
|
312
|
+
* Pull the latest `redislabs/redistimeseries` image
|
313
|
+
* Start a Redis server on port 6379
|
314
|
+
* Seed three time series with some sample data
|
315
|
+
* Attach to the running server and print logs to `STDOUT`
|
174
316
|
|
175
|
-
|
176
|
-
```
|
177
|
-
docker run -p 6379:6379 -it --rm redislabs/redistimeseries
|
178
|
-
```
|
179
|
-
|
180
|
-
The `bin/console` script will set up three time series, `@ts1`, `@ts2`, and `@ts3`, with three values in each. **It will also flush the local Redis server each time you run it**, so don't try it if you have data you don't want to lose!
|
317
|
+
With the above script running, or after starting a server manually, you can run `bin/console` to interact with it. The three series are named `ts1`, `ts2`, and `ts3`, and are available as instance variables in the console.
|
181
318
|
|
182
319
|
If you want to see the commands being executed, run the console with `DEBUG=true bin/console` and it will output the raw command strings as they're executed.
|
183
320
|
```ruby
|
184
321
|
[1] pry(main)> @ts1.increment
|
185
|
-
DEBUG: TS.INCRBY
|
322
|
+
DEBUG: TS.INCRBY ts1 1
|
186
323
|
=> 1593159795467
|
187
324
|
[2] pry(main)> @ts1.get
|
188
|
-
DEBUG: TS.GET
|
325
|
+
DEBUG: TS.GET ts1
|
189
326
|
=> #<Redis::TimeSeries::Sample:0x00007f8e1a190cf8 @time=2020-06-26 01:23:15 -0700, @value=0.4e1>
|
190
327
|
```
|
191
328
|
|
329
|
+
Use `rake spec` to run the test suite.
|
330
|
+
|
192
331
|
## Contributing
|
193
332
|
|
194
333
|
Bug reports and pull requests are welcome on GitHub at https://github.com/dzunk/redis-time-series.
|
data/bin/console
CHANGED
@@ -6,15 +6,9 @@ require 'pry'
|
|
6
6
|
require 'redis'
|
7
7
|
require 'redis-time-series'
|
8
8
|
|
9
|
-
Redis.
|
10
|
-
|
11
|
-
@
|
12
|
-
@ts2 = Redis::TimeSeries.create('bar')
|
13
|
-
@ts3 = Redis::TimeSeries.create('baz')
|
14
|
-
|
9
|
+
@ts1 = Redis::TimeSeries.new('ts1')
|
10
|
+
@ts2 = Redis::TimeSeries.new('ts2')
|
11
|
+
@ts3 = Redis::TimeSeries.new('ts3')
|
15
12
|
@series = [@ts1, @ts2, @ts3]
|
16
|
-
@series.each do |ts|
|
17
|
-
3.times { ts.increment; sleep 0.01 }
|
18
|
-
end
|
19
13
|
|
20
14
|
Pry.start
|
data/bin/setup
CHANGED
@@ -1,8 +1,31 @@
|
|
1
|
-
#!/usr/bin/env
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
set -vx
|
1
|
+
#!/usr/bin/env ruby
|
5
2
|
|
6
|
-
bundle install
|
3
|
+
system 'bundle install'
|
4
|
+
system 'docker pull redislabs/redistimeseries:latest'
|
5
|
+
container_id = `docker run -p 6379:6379 -dit --rm redislabs/redistimeseries`
|
6
|
+
at_exit { system "docker stop #{container_id}" }
|
7
7
|
|
8
|
-
|
8
|
+
require 'bundler/setup'
|
9
|
+
require 'active_support/core_ext/numeric/time'
|
10
|
+
require 'redis'
|
11
|
+
require 'redis-time-series'
|
12
|
+
|
13
|
+
Redis.current.flushall
|
14
|
+
ts1 = Redis::TimeSeries.create('ts1')
|
15
|
+
ts2 = Redis::TimeSeries.create('ts2')
|
16
|
+
ts3 = Redis::TimeSeries.create('ts3')
|
17
|
+
|
18
|
+
ts1.add 12, 6.minutes.ago
|
19
|
+
ts1.add 34, 4.minutes.ago
|
20
|
+
ts1.add 56, 2.minutes.ago
|
21
|
+
|
22
|
+
10.times { ts2.increment; sleep 0.01 }
|
23
|
+
|
24
|
+
ts3.labels = { foo: 'bar' }
|
25
|
+
ts3.add 1
|
26
|
+
sleep 0.01
|
27
|
+
ts3.incrby 2
|
28
|
+
sleep 0.01
|
29
|
+
ts3.decrement
|
30
|
+
|
31
|
+
system "docker logs -f #{container_id}"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The +TimeMsec+ module is a refinement for the +Time+ class that makes it easier
|
4
|
+
# to work with millisecond timestamps.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# Time.now.to_i # 1595194259
|
8
|
+
# Time.now.ts_msec # NoMethodError
|
9
|
+
#
|
10
|
+
# using TimeMsec
|
11
|
+
#
|
12
|
+
# Time.now.to_i # 1595194259
|
13
|
+
# Time.now.ts_msec # 1595194259000
|
14
|
+
#
|
15
|
+
# Time.from_msec(1595194259000) # 2020-07-19 14:30:59 -0700
|
16
|
+
module TimeMsec
|
17
|
+
refine Time do
|
18
|
+
# TODO: convert to #to_msec
|
19
|
+
def ts_msec
|
20
|
+
(to_f * 1000.0).to_i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
refine Time.singleton_class do
|
25
|
+
def from_msec(timestamp)
|
26
|
+
at(timestamp / 1000.0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|