influx 0.1.0.alpha → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4b53c95048c7332be3eed378213fe0952d7815ec5f3780e18ceaeac0328cc83
4
- data.tar.gz: 0ac5483c268718a4267227a6a18636e6ce68fb9c5c63076a47f174e8a0ded456
3
+ metadata.gz: 0d2c6ec69b8f21ac0b2fab377c7215598ac2cd8ecd20f443b971e5909fa014aa
4
+ data.tar.gz: 120f06af14b691787c7b25e6ed40fc287d8e0d7a7e0f03ea3d97348f4e76a8b2
5
5
  SHA512:
6
- metadata.gz: 01c4f79cf46720f791139bf14507c8ead9e4e7a8560ad8ca03886188552e219a15a968646671a6eaa8d084893a2c16d11e75b188ce9bf74292913ee7985263b7
7
- data.tar.gz: f10c0ebf7fd02de18f1e120ade62e4c0a5d7fe02607123e28aaa2379a38cdc10c79347ddda3f505f679382a925286f689db201c54aec88e2543148081efabd33
6
+ metadata.gz: 6e1df569de6d83a399004cb32597a00e51fd454d07a929f47a62b439867b63da2cf6e81c1830bd8b9d279f0ea8be439de962580533501119d2c03867a90d50ce
7
+ data.tar.gz: 002a155c47b90be78d75ecbeee8ee980559c6088992023e3ba079556a068dba18978ed838ffe0b0d53dadb34cd894e217c50704932817573381ebff89dad8a24
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,13 +1,177 @@
1
+ # require: rubocop-graphql
2
+
3
+ # Allow longer lines and methods
4
+ Layout/LineLength:
5
+ Max: 500
6
+
7
+ Metrics/MethodLength:
8
+ Max: 30
9
+
10
+ # Tests are declarative, no block length test
11
+ Metrics/BlockLength:
12
+ IgnoredMethods: ["describe", "context", "namespace"]
13
+
1
14
  AllCops:
2
- TargetRubyVersion: 2.6
15
+ TargetRubyVersion: 3.0.2
16
+ # RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
17
+ # to ignore them, so only the ones explicitly set in this file are enabled.
18
+ DisabledByDefault: true
19
+
20
+ # Prefer &&/|| over and/or.
21
+ Style/AndOr:
22
+ Enabled: true
23
+
24
+ # Align `when` with `case`.
25
+ Layout/CaseIndentation:
26
+ Enabled: true
27
+
28
+ # Align comments with method definitions.
29
+ Layout/CommentIndentation:
30
+ Enabled: true
31
+
32
+ Layout/ElseAlignment:
33
+ Enabled: true
34
+
35
+ # Align `end` with the matching keyword or starting expression except for
36
+ # assignments, where it should be aligned with the LHS.
37
+ Layout/EndAlignment:
38
+ Enabled: true
39
+ EnforcedStyleAlignWith: variable
40
+ AutoCorrect: true
41
+
42
+ Layout/EmptyLineAfterMagicComment:
43
+ Enabled: true
44
+
45
+ # In a regular class definition, no empty lines around the body.
46
+ Layout/EmptyLinesAroundClassBody:
47
+ Enabled: true
48
+
49
+ # In a regular method definition, no empty lines around the body.
50
+ Layout/EmptyLinesAroundMethodBody:
51
+ Enabled: true
52
+
53
+ # In a regular module definition, no empty lines around the body.
54
+ Layout/EmptyLinesAroundModuleBody:
55
+ Enabled: true
56
+
57
+ Layout/FirstArgumentIndentation:
58
+ Enabled: true
59
+
60
+ # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
61
+ Style/HashSyntax:
62
+ Enabled: true
63
+
64
+ # Method definitions after `private` or `protected` isolated calls need one
65
+ # extra level of indentation.
66
+ Layout/IndentationConsistency:
67
+ Enabled: true
68
+ EnforcedStyle: indented_internal_methods
69
+
70
+ # Two spaces, no tabs (for indentation).
71
+ Layout/IndentationWidth:
72
+ Enabled: true
73
+
74
+ Layout/LeadingCommentSpace:
75
+ Enabled: true
76
+
77
+ Layout/SpaceAfterColon:
78
+ Enabled: true
79
+
80
+ Layout/SpaceAfterComma:
81
+ Enabled: true
82
+
83
+ Layout/SpaceAroundEqualsInParameterDefault:
84
+ Enabled: true
85
+
86
+ Layout/SpaceAroundKeyword:
87
+ Enabled: true
88
+
89
+ Layout/SpaceAroundOperators:
90
+ Enabled: true
91
+
92
+ Layout/SpaceBeforeComma:
93
+ Enabled: true
94
+
95
+ Layout/SpaceBeforeFirstArg:
96
+ Enabled: true
97
+
98
+ Style/DefWithParentheses:
99
+ Enabled: true
100
+
101
+ # Defining a method with parameters needs parentheses.
102
+ Style/MethodDefParentheses:
103
+ Enabled: true
104
+
105
+ Style/FrozenStringLiteralComment:
106
+ Enabled: true
107
+ EnforcedStyle: always
108
+ Exclude:
109
+ - "actionview/test/**/*.builder"
110
+ - "actionview/test/**/*.ruby"
111
+ - "actionpack/test/**/*.builder"
112
+ - "actionpack/test/**/*.ruby"
113
+ - "activestorage/db/migrate/**/*.rb"
114
+ - "db/migrate/**/*.rb"
115
+ - "db/*.rb"
116
+
117
+ # Use `foo {}` not `foo{}`.
118
+ Layout/SpaceBeforeBlockBraces:
119
+ Enabled: true
3
120
 
121
+ # Use `foo { bar }` not `foo {bar}`.
122
+ Layout/SpaceInsideBlockBraces:
123
+ Enabled: true
124
+
125
+ # Use `{ a: 1 }` not `{a:1}`.
126
+ Layout/SpaceInsideHashLiteralBraces:
127
+ Enabled: true
128
+
129
+ Layout/SpaceInsideParens:
130
+ Enabled: true
131
+
132
+ # Check quotes usage according to lint rule below.
4
133
  Style/StringLiterals:
5
134
  Enabled: true
6
- EnforcedStyle: double_quotes
135
+ EnforcedStyle: single_quotes
7
136
 
8
- Style/StringLiteralsInInterpolation:
137
+ # Detect hard tabs, no hard tabs.
138
+ Layout/IndentationStyle:
9
139
  Enabled: true
10
- EnforcedStyle: double_quotes
11
140
 
12
- Layout/LineLength:
13
- Max: 120
141
+ # Blank lines should not have any spaces.
142
+ Layout/TrailingEmptyLines:
143
+ Enabled: true
144
+
145
+ # No trailing whitespace.
146
+ Layout/TrailingWhitespace:
147
+ Enabled: true
148
+
149
+ # Use quotes for string literals when they are enough.
150
+ Style/RedundantPercentQ:
151
+ Enabled: true
152
+
153
+ # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
154
+ Lint/RequireParentheses:
155
+ Enabled: true
156
+
157
+ Lint/RedundantStringCoercion:
158
+ Enabled: true
159
+
160
+ # Supports --auto-correct
161
+ Style/RedundantSelf:
162
+ Description: Don't use self where it's not needed.
163
+ StyleGuide: https://github.com/rubocop-hq/ruby-style-guide#no-self-unless-required
164
+ Enabled: true
165
+
166
+ Style/RedundantReturn:
167
+ Enabled: true
168
+ AllowMultipleReturnValues: true
169
+
170
+ Style/Semicolon:
171
+ Enabled: true
172
+ AllowAsExpressionSeparator: true
173
+
174
+ # Prefer Foo.method over Foo::method
175
+ Style/ColonMethodCall:
176
+ Enabled: true
177
+
data/Gemfile CHANGED
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in influx.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
8
+ gem 'rake', '~> 13.0'
9
9
 
10
- gem "rubocop", "~> 1.21"
10
+ gem 'rspec', '~> 3'
11
+
12
+ gem 'rubocop', '~> 1'
13
+
14
+ gem 'simplecov', require: false, group: :test
data/Gemfile.lock ADDED
@@ -0,0 +1,63 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ influx (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ diff-lcs (1.5.0)
11
+ docile (1.4.0)
12
+ parallel (1.22.0)
13
+ parser (3.1.1.0)
14
+ ast (~> 2.4.1)
15
+ rainbow (3.1.1)
16
+ rake (13.0.6)
17
+ regexp_parser (2.2.1)
18
+ rexml (3.2.5)
19
+ rspec (3.10.0)
20
+ rspec-core (~> 3.10.0)
21
+ rspec-expectations (~> 3.10.0)
22
+ rspec-mocks (~> 3.10.0)
23
+ rspec-core (3.10.2)
24
+ rspec-support (~> 3.10.0)
25
+ rspec-expectations (3.10.2)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.10.0)
28
+ rspec-mocks (3.10.2)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.10.0)
31
+ rspec-support (3.10.3)
32
+ rubocop (1.26.1)
33
+ parallel (~> 1.10)
34
+ parser (>= 3.1.0.0)
35
+ rainbow (>= 2.2.2, < 4.0)
36
+ regexp_parser (>= 1.8, < 3.0)
37
+ rexml
38
+ rubocop-ast (>= 1.16.0, < 2.0)
39
+ ruby-progressbar (~> 1.7)
40
+ unicode-display_width (>= 1.4.0, < 3.0)
41
+ rubocop-ast (1.16.0)
42
+ parser (>= 3.1.1.0)
43
+ ruby-progressbar (1.11.0)
44
+ simplecov (0.21.2)
45
+ docile (~> 1.1)
46
+ simplecov-html (~> 0.11)
47
+ simplecov_json_formatter (~> 0.1)
48
+ simplecov-html (0.12.3)
49
+ simplecov_json_formatter (0.1.4)
50
+ unicode-display_width (2.1.0)
51
+
52
+ PLATFORMS
53
+ arm64-darwin-21
54
+
55
+ DEPENDENCIES
56
+ influx!
57
+ rake (~> 13.0)
58
+ rspec (~> 3)
59
+ rubocop (~> 1)
60
+ simplecov
61
+
62
+ BUNDLED WITH
63
+ 2.3.9
data/README.md CHANGED
@@ -1,8 +1,42 @@
1
- # Influx
1
+ ## <img src="https://user-images.githubusercontent.com/50866745/168482997-7ed6ae74-aac9-4aee-bf03-fef5e01d683a.png" width="48" align="left"> Ruby InfluxDB Flux <!-- omit in toc -->
2
+ [![CircleCI](https://circleci.com/gh/LapoElisacci/influx/tree/main.svg?style=svg)](https://circleci.com/gh/LapoElisacci/influx/tree/main)
3
+ ![](https://img.shields.io/static/v1?label=Coverage&message=99.54%&color=brightgreen)
4
+ ![](https://img.shields.io/static/v1?label=Latest&message=0.1.0.alpha&color=blue)
5
+ ![](https://ruby-gem-downloads-badge.herokuapp.com/influx?type=total&color=blue)
6
+ ![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)
2
7
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/influx`. To experiment with that code, run `bin/console` for an interactive prompt.
8
+ Write InfluxDB Flux queries in an ORM fashion with Ruby.
4
9
 
5
- TODO: Delete this and the text above, and describe your gem
10
+ ## Table of contents
11
+
12
+ - [Table of contents](#table-of-contents)
13
+ - [Installation](#installation)
14
+ - [Utilities](#utilities)
15
+ - [Now](#now)
16
+ - [Flux points](#flux-points)
17
+ - [Flux queries](#flux-queries)
18
+ - [From](#from)
19
+ - [Range](#range)
20
+ - [Query data with Flux](#query-data-with-flux)
21
+ - [From](#from-1)
22
+ - [Range](#range-1)
23
+ - [Query fields and tags](#query-fields-and-tags)
24
+ - [Group](#group)
25
+ - [Sort and limit](#sort-and-limit)
26
+ - [Window & aggregate](#window--aggregate)
27
+ - [Increase](#increase)
28
+ - [Moving Average](#moving-average)
29
+ - [Rate](#rate)
30
+ - [Histograms](#histograms)
31
+ - [Fill](#fill)
32
+ - [Median](#median)
33
+ - [Percentile & quantile](#percentile--quantile)
34
+ - [Join (TBD)](#join-tbd)
35
+ - [Cumulative sum](#cumulative-sum)
36
+ - [First & last](#first--last)
37
+ - [Contributing](#contributing)
38
+ - [License](#license)
39
+ - [Code of Conduct](#code-of-conduct)
6
40
 
7
41
  ## Installation
8
42
 
@@ -14,15 +48,290 @@ If bundler is not being used to manage dependencies, install the gem by executin
14
48
 
15
49
  $ gem install influx
16
50
 
17
- ## Usage
51
+ ## Utilities
52
+
53
+ Here are some utility methods provided by the gem.
54
+
55
+ ### Now
56
+
57
+ The gem provides a method to return the Clock timestamp in nanoseconds.
58
+
59
+ ```Ruby
60
+ Influx.now # Default precision is Nanoseconds
61
+ ```
62
+
63
+ You can also pass other precisions if needed:
64
+
65
+ ```Ruby
66
+ Influx.now(:second)
67
+ Influx.now(:millisecond)
68
+ Influx.now(:microsecond)
69
+ Influx.now(:nanosecond)
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Flux points
75
+
76
+ ```Ruby
77
+ Influx::Point.new(
78
+ 'h2o', # measurement
79
+ tags: { location: 'west' },
80
+ fields: { value: 33 },
81
+ time: Influx.now # The default value is Influx.now, you can also use Time or Integer
82
+ ).to_flux # h2o,location=west value=33 1652720908000000
83
+ ```
84
+
85
+ ## Flux queries
86
+
87
+ The gem acts as an ORM therefore you can chain methods to build your `Flux` query string.
88
+
89
+ You can always call the `to_flux` method to see a preview or your query:
90
+
91
+ ```Ruby
92
+ flux_query = Influx.from(bucket: 'my-bucket').range(start: '-1d')
93
+ flux_query.to_flux # from(bucket: "my-bucket") |> range(start: -1d)
94
+ ```
95
+
96
+ ### From
97
+
98
+ The `from` method is the starting point of all queries, it allows you to specify the InfluxDB bucket.
99
+
100
+ ```Ruby
101
+ Influx.from(bucket: 'my-bucket')
102
+ ```
103
+ > ⚠️ This is mandatory to perform any query.
104
+
105
+ ### Range
106
+
107
+ The `range` method allows you to specify the time-range you want to query.
108
+
109
+ ```Ruby
110
+ Influx.from(bucket: 'my-bucket').range(start: '-1d', stop: 'now()')
111
+ ```
112
+
113
+ It supports the `Flux` sytanx as well as `Time`.
114
+
115
+ ```Ruby
116
+ Influx.from(bucket: 'my-bucket').range(start: Time.new.yesterday, stop: Time.new)
117
+ ```
118
+
119
+ > ⚠️ This is mandatory to perform any query.
120
+
121
+ ---
122
+
123
+ ## Query data with Flux
124
+
125
+ The following guides are based on top of the original InfluxData Flux Documentation, available [here](https://docs.influxdata.com/influxdb/cloud/query-data/flux/).
126
+
127
+ **Example data variable**
128
+ Many of the examples provided in the following guides use a **data** variable, which represents a basic query that filters data by measurement and field. **data** is defined as:
129
+
130
+ ```Ruby
131
+ data = Influx.from(bucket: 'my-bucket').range(start: '-1d', stop: 'now()')
132
+
133
+ # from(bucket: "my-bucket")
134
+ # |> range(start: -1d, stop: now())
135
+ ```
136
+
137
+ ### From
138
+
139
+ The `from` method allows you to specify the InfluxDB bucket. Every query starts with the `from` method.
140
+
141
+ ```Ruby
142
+ Influx.from(bucket: 'my-bucket')
143
+
144
+ # from(bucket: "my-bucket")
145
+ ```
146
+
147
+ ### Range
148
+
149
+ The `range` method allows you to bind your query to a time range, it supports native Flux syntax as well as the Ruby `Time` class and `Integer`.
150
+
151
+ ```Ruby
152
+ Influx.from(bucket: 'my-bucket').range(start: '-1d', stop: 'now()')
153
+
154
+ # from(bucket: "my-bucket")
155
+ # |> range(start: -1d, stop: now())
156
+ ```
157
+ ```Ruby
158
+ Influx.from(bucket: 'my-bucket').range(start: Time.new(2018, 1, 1, 0, 0, 0, '+00:00').utc, stop: 1514768400)
159
+
160
+ # from(bucket: "my-bucket")
161
+ # |> range(start: 2018-01-01T00:00:00Z, stop: 2018-01-01T01:00:00Z)
162
+ ```
163
+
164
+ ---
165
+
166
+ ### Query fields and tags
167
+
168
+ Use `filter()` to query data based on fields, tags, or any other column value.
169
+
170
+ ```Ruby
171
+ data.filter("_measurement": "example-measurement", tag: "example-tag")
172
+
173
+ # data
174
+ # |> filter(fn: (r) => r._measurement == "example-measurement" and r.tag == "example-tag")
175
+ ```
176
+
177
+ ### Group
178
+
179
+ Use `group()` to group data with common values in specific columns.
180
+
181
+ ```Ruby
182
+ data.group(columns: ["host"], mode: "by")
183
+
184
+ # data
185
+ # |> group(columns: ["host"], mode: "by")
186
+ ```
187
+
188
+ ### Sort and limit
189
+
190
+ Use `sort()` to order records within each table by specific columns and `limit()` to limit the number of records in output tables to a fixed number, `n`.
191
+
192
+ ```Ruby
193
+ data.sort(columns: ["host", "_value"]).limit(4)
194
+
195
+ # data
196
+ # |> sort(columns: ["host","_value"])
197
+ # |> limit(n: 4)
198
+ ```
199
+
200
+ ### Window & aggregate
201
+
202
+ ```Ruby
203
+ data.aggregate_window(every: "20m", fn: "mean")
204
+
205
+ # data
206
+ # |> aggregateWindow(every: 20m, fn: mean)
207
+ ```
208
+
209
+ ### Increase
210
+
211
+ Use `increase()` to track increases across multiple columns in a table.
212
+
213
+ ```Ruby
214
+ data.increase
215
+
216
+ # data
217
+ # |> increase()
218
+ ```
219
+
220
+ ### Moving Average
221
+
222
+ Use `moving_average()` or `timed_moving_average()` to return the moving average of data.
223
+
224
+ ```Ruby
225
+ data.moving_average(5)
226
+
227
+ # data
228
+ # |> movingAverage(n: 5)
229
+ ```
230
+ ```Ruby
231
+ data.timed_moving_average(every: "2m", period: "4m")
232
+
233
+ # data
234
+ # |> timedMovingAverage(every: 2m, period: 4m)
235
+ ```
236
+
237
+ ### Rate
238
+
239
+ Use `derivative()` to calculate the rate of change between subsequent values.
240
+
241
+ ```Ruby
242
+ data.derivative(unit: "1m", non_negative: true)
243
+
244
+ # data
245
+ # |> derivative(unit: 1m, nonNegative: true)
246
+ ```
247
+
248
+ ### Histograms
249
+
250
+ Use `histogram()` to create cumulative histograms with Flux.
251
+
252
+ ```Ruby
253
+ data.histogram(column: "_value", upper_bound_column: "le", count_column: "_value", bins: [100.0, 200.0, 300.0, 400.0])
254
+
255
+ # data
256
+ # |> histogram(
257
+ # column: "_value",
258
+ # upperBoundColumn: "le",
259
+ # countColumn: "_value",
260
+ # bins: [100.0,200.0,300.0,400.0]
261
+ # )
262
+ ```
263
+ ### Fill
264
+
265
+ Use `fill()` function to replace null values.
266
+
267
+ ```Ruby
268
+ data.fill(use_previous: true)
269
+
270
+ # data
271
+ # |> fill(usePrevious: true)
272
+ ```
273
+ ```Ruby
274
+ data.fill(value: 0.0)
275
+ # data
276
+ # |> fill(value: 0.0)
277
+ ```
278
+
279
+ ### Median
280
+
281
+ Use `median()` to return a value representing the 0.5 quantile (50th percentile) or median of input data.
282
+
283
+ ```Ruby
284
+ data.median
285
+
286
+ # data
287
+ # |> median()
288
+ ```
289
+
290
+ ### Percentile & quantile
291
+
292
+ Use the `quantile()` function to return all values within the `q` quantile or percentile of input data.
293
+
294
+ ```Ruby
295
+ data.quantile(q: 0.99, method: "estimate_tdigest")
296
+
297
+ # data
298
+ # |> quantile(q: 0.99, method: "estimate_tdigest")
299
+ ```
300
+
301
+
302
+ ### Join (TBD)
303
+
304
+ TBD
305
+
306
+ ### Cumulative sum
307
+
308
+ Use the `cumulativeSum()` function to calculate a running total of values.
309
+
310
+ ```Ruby
311
+ data.cumulative_sum
312
+
313
+ # data
314
+ # |> cumulativeSum()
315
+ ```
316
+
317
+ ### First & last
318
+
319
+ Use `first()` or `last()` to return the first or last point in an input table.
18
320
 
19
- TODO: Write usage instructions here
321
+ ```Ruby
322
+ data.first
20
323
 
21
- ## Development
324
+ # data
325
+ # |> first()
326
+ ```
327
+ ```Ruby
328
+ data.last
22
329
 
23
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
330
+ # data
331
+ # |> last()
332
+ ```
24
333
 
25
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
334
+ ---
26
335
 
27
336
  ## Contributing
28
337
 
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rubocop/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rubocop/rake_task'
5
5
 
6
6
  RuboCop::RakeTask.new
7
7
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> aggregateWindow(every: 20m, fn: mean)
4
+
5
+ module Influx
6
+ module Flux
7
+ class AggregateWindow
8
+ def initialize(every:, fn:)
9
+ @every = every
10
+ @fn = fn
11
+ end
12
+
13
+ def to_flux
14
+ <<~FLUX.chomp
15
+ |> aggregateWindow(every: #{@every}, fn: #{@fn})
16
+ FLUX
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> cumulativeSum()
4
+
5
+ module Influx
6
+ module Flux
7
+ class CumulativeSum
8
+ def self.to_flux
9
+ <<~FLUX.chomp
10
+ |> cumulativeSum()
11
+ FLUX
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> derivative(unit: 1m, nonNegative: true)
4
+
5
+ module Influx
6
+ module Flux
7
+ class Derivative
8
+ def initialize(unit:, non_negative:)
9
+ @unit = unit
10
+ @non_negative = non_negative
11
+ end
12
+
13
+ def to_flux
14
+ <<~FLUX.chomp
15
+ |> derivative(unit: #{@unit}, nonNegative: #{@non_negative})
16
+ FLUX
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> fill(usePrevious: true)
4
+ # |> fill(value: 0.0)
5
+
6
+ module Influx
7
+ module Flux
8
+ class Fill
9
+ def initialize(use_previous: false, value: nil)
10
+ @use_previous = use_previous
11
+ @value = value
12
+ end
13
+
14
+ def to_flux
15
+ if @use_previous
16
+ <<~FLUX.chomp
17
+ |> fill(usePrevious: #{@use_previous})
18
+ FLUX
19
+ else
20
+ <<~FLUX.chomp
21
+ |> fill(value: #{@value})
22
+ FLUX
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> filter(fn: (r) => r._measurement == "example-measurement" and r._field == "example-field")
4
+
5
+ module Influx
6
+ module Flux
7
+ class Filter
8
+ def initialize(**params)
9
+ @params = params
10
+ end
11
+
12
+ def to_flux
13
+ <<~FLUX.chomp
14
+ |> filter(fn: (r) => #{@params.map { |k, v| "r.#{k} == #{v.to_json}" }.join(' and ')})
15
+ FLUX
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> first()
4
+
5
+ module Influx
6
+ module Flux
7
+ class First
8
+ def self.to_flux
9
+ <<~FLUX.chomp
10
+ |> first()
11
+ FLUX
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Influx
4
+ module Flux
5
+ class From
6
+ attr_accessor :bucket
7
+
8
+ def initialize(bucket:)
9
+ @bucket = bucket
10
+ end
11
+
12
+ def to_flux
13
+ <<~FLUX.chomp
14
+ from(bucket: "#{@bucket}")
15
+ FLUX
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> group(columns: ["host"], mode: "by")
4
+
5
+ module Influx
6
+ module Flux
7
+ class Group
8
+ def initialize(columns: [], mode:)
9
+ raise Influx::Error.new('Columns value has to be Array of Strings!') unless columns.is_a?(Array) && columns.all? { |c| c.is_a?(String) }
10
+
11
+ @columns = columns
12
+ @mode = mode
13
+ end
14
+
15
+ def to_flux
16
+ <<~FLUX.chomp
17
+ |> group(columns: #{@columns.to_json}, mode: "#{@mode}")
18
+ FLUX
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> histogram(
4
+ # column: "_value",
5
+ # upperBoundColumn: "le",
6
+ # countColumn: "_value",
7
+ # bins: [100.0, 200.0, 300.0, 400.0],
8
+ # )
9
+
10
+ module Influx
11
+ module Flux
12
+ class Histogram
13
+ def initialize(column:, upper_bound_column:, count_column:, bins: [])
14
+ @column = column
15
+ @upper_bound_column = upper_bound_column
16
+ @count_column = count_column
17
+ @bins = bins
18
+ end
19
+
20
+ def to_flux
21
+ <<~FLUX.chomp
22
+ |> histogram(column: "#{@column}", upperBoundColumn: "#{@upper_bound_column}", countColumn: "#{@count_column}", bins: #{@bins.to_json})
23
+ FLUX
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> increase()
4
+
5
+ module Influx
6
+ module Flux
7
+ class Increase
8
+ def self.to_flux
9
+ <<~FLUX.chomp
10
+ |> increase()
11
+ FLUX
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> last()
4
+
5
+ module Influx
6
+ module Flux
7
+ class Last
8
+ def self.to_flux
9
+ <<~FLUX.chomp
10
+ |> last()
11
+ FLUX
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> limit(n: 4)
4
+
5
+ module Influx
6
+ module Flux
7
+ class Limit
8
+ def initialize(n:)
9
+ raise Influx::Error.new('Limit value has to be Integer!') unless n.is_a?(Integer)
10
+
11
+ @n = n
12
+ end
13
+
14
+ def to_flux
15
+ <<~FLUX.chomp
16
+ |> limit(n: #{@n})
17
+ FLUX
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> median()
4
+
5
+ module Influx
6
+ module Flux
7
+ class Median
8
+ def self.to_flux
9
+ <<~FLUX.chomp
10
+ |> median()
11
+ FLUX
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> movingAverage(n: 5)
4
+
5
+ module Influx
6
+ module Flux
7
+ class MovingAverage
8
+ def initialize(n:)
9
+ raise Influx::Error.new('N value has to be Integer!') unless n.is_a?(Integer)
10
+
11
+ @n = n
12
+ end
13
+
14
+ def to_flux
15
+ <<~FLUX.chomp
16
+ |> movingAverage(n: #{@n})
17
+ FLUX
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> quantile(q: 0.99, method: "estimate_tdigest")
4
+
5
+ module Influx
6
+ module Flux
7
+ class Quantile
8
+ def initialize(q:, method:)
9
+ @q = q
10
+ @method = method
11
+ end
12
+
13
+ def to_flux
14
+ <<~FLUX.chomp
15
+ |> quantile(q: #{@q}, method: "#{@method}")
16
+ FLUX
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> range(start: -1h)
4
+
5
+ module Influx
6
+ module Flux
7
+ class Range
8
+ attr_accessor :start, :stop
9
+
10
+ def initialize(start: nil, stop: nil)
11
+ @start = cast_value(start)
12
+ @stop = cast_value(stop)
13
+ end
14
+
15
+ def to_flux
16
+ params = []
17
+
18
+ params << "start: #{@start}" if @start
19
+ params << "stop: #{@stop}" if @stop
20
+
21
+ <<~FLUX.chomp
22
+ |> range(#{params.join(', ')})
23
+ FLUX
24
+ end
25
+
26
+ private
27
+
28
+ def cast_value(time)
29
+ return if time.nil?
30
+
31
+ case time.class.to_s
32
+ when 'Time'
33
+ time.iso8601
34
+ when 'String'
35
+ time
36
+ when 'Integer'
37
+ Time.at(time).iso8601
38
+ else
39
+ raise ArgumentError, 'Invalid time format, expected Time, String or Integer'
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> sort(columns: ["host", "_value"])
4
+
5
+ module Influx
6
+ module Flux
7
+ class Sort
8
+ def initialize(columns:)
9
+ raise Influx::Error.new('Columns value has to be Array of Strings!') unless columns.is_a?(Array) && columns.all? { |c| c.is_a?(String) }
10
+
11
+ @columns = columns
12
+ end
13
+
14
+ def to_flux
15
+ <<~FLUX.chomp
16
+ |> sort(columns: #{@columns.to_json})
17
+ FLUX
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # |> timedMovingAverage(every: 2m, period: 4m)
4
+
5
+ module Influx
6
+ module Flux
7
+ class TimedMovingAverage
8
+ def initialize(every:, period:)
9
+ @every = every
10
+ @period = period
11
+ end
12
+
13
+ def to_flux
14
+ <<~FLUX.chomp
15
+ |> timedMovingAverage(every: #{@every}, period: #{@period})
16
+ FLUX
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Influx
4
+ class Point
5
+ def initialize(measurement, tags: {}, fields: {}, time: Influx.now)
6
+ @measurement = measurement
7
+ @tags = tags
8
+ @fields = fields
9
+ @time = time.to_i
10
+ end
11
+
12
+ def to_flux
13
+ "#{@measurement},#{hash_to_flux(@tags)} #{hash_to_flux(@fields)} #{@time}"
14
+ end
15
+
16
+ private
17
+
18
+ def hash_to_flux(hash)
19
+ hash.map { |key, value| "#{key}=#{value}" }.join(',')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Influx
4
+ class Query
5
+ def initialize(bucket:)
6
+ @from = Influx::Flux::From.new(bucket: bucket)
7
+ @statements = []
8
+ end
9
+
10
+ def aggregate_window(every:, fn:)
11
+ @statements << Influx::Flux::AggregateWindow.new(every: every, fn: fn)
12
+ self
13
+ end
14
+
15
+ def cumulative_sum
16
+ @statements << Influx::Flux::CumulativeSum
17
+ self
18
+ end
19
+
20
+ def derivative(unit:, non_negative: true)
21
+ @statements << Influx::Flux::Derivative.new(unit: unit, non_negative: non_negative)
22
+ self
23
+ end
24
+
25
+ def fill(use_previous: false, value: nil)
26
+ @statements << Influx::Flux::Fill.new(use_previous: use_previous, value: value)
27
+ self
28
+ end
29
+
30
+ def filter(**params)
31
+ @statements << Influx::Flux::Filter.new(**params)
32
+ self
33
+ end
34
+
35
+ def first
36
+ @statements << Influx::Flux::First
37
+ self
38
+ end
39
+
40
+ def group(columns: [], mode:)
41
+ @statements << Influx::Flux::Group.new(columns: columns, mode: mode)
42
+ self
43
+ end
44
+
45
+ def histogram(column:, upper_bound_column:, count_column:, bins: [])
46
+ @statements << Influx::Flux::Histogram.new(column: column, upper_bound_column: upper_bound_column, count_column: count_column, bins: bins)
47
+ self
48
+ end
49
+
50
+ def increase
51
+ @statements << Influx::Flux::Increase
52
+ self
53
+ end
54
+
55
+ def last
56
+ @statements << Influx::Flux::Last
57
+ self
58
+ end
59
+
60
+ def limit(n)
61
+ @statements << Influx::Flux::Limit.new(n: n)
62
+ self
63
+ end
64
+
65
+ def median
66
+ @statements << Influx::Flux::Median
67
+ self
68
+ end
69
+
70
+ def moving_average(n)
71
+ @statements << Influx::Flux::MovingAverage.new(n: n)
72
+ self
73
+ end
74
+
75
+ def quantile(q:, method:)
76
+ @statements << Influx::Flux::Quantile.new(q: q, method: method)
77
+ self
78
+ end
79
+
80
+ def range(start: nil, stop: nil)
81
+ @statements << Influx::Flux::Range.new(start: start, stop: stop)
82
+ self
83
+ end
84
+
85
+ def sort(columns:)
86
+ @statements << Influx::Flux::Sort.new(columns: columns)
87
+ self
88
+ end
89
+
90
+ def timed_moving_average(every:, period:)
91
+ @statements << Influx::Flux::TimedMovingAverage.new(every: every, period: period)
92
+ self
93
+ end
94
+
95
+ def to_flux
96
+ "#{@from.to_flux} #{@statements.map(&:to_flux).join(' ')}"
97
+ end
98
+ end
99
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Influx
4
- VERSION = "0.1.0.alpha"
4
+ VERSION = '0.1.0'
5
5
  end
data/lib/influx.rb CHANGED
@@ -1,8 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "influx/version"
3
+ require 'json'
4
+
5
+ require_relative 'influx/point'
6
+ require_relative 'influx/query'
7
+ require_relative 'influx/version'
8
+
9
+ require_relative 'influx/flux/aggregate_window'
10
+ require_relative 'influx/flux/cumulative_sum'
11
+ require_relative 'influx/flux/derivative'
12
+ require_relative 'influx/flux/fill'
13
+ require_relative 'influx/flux/filter'
14
+ require_relative 'influx/flux/first'
15
+ require_relative 'influx/flux/from'
16
+ require_relative 'influx/flux/group'
17
+ require_relative 'influx/flux/histogram'
18
+ require_relative 'influx/flux/increase'
19
+ require_relative 'influx/flux/last'
20
+ require_relative 'influx/flux/limit'
21
+ require_relative 'influx/flux/median'
22
+ require_relative 'influx/flux/moving_average'
23
+ require_relative 'influx/flux/quantile'
24
+ require_relative 'influx/flux/range'
25
+ require_relative 'influx/flux/sort'
26
+ require_relative 'influx/flux/timed_moving_average'
4
27
 
5
28
  module Influx
6
29
  class Error < StandardError; end
7
- # Your code goes here...
30
+
31
+ class << self
32
+ def from(bucket:)
33
+ Influx::Query.new(bucket: bucket)
34
+ end
35
+
36
+ def now(precision = :nanosecond)
37
+ Process.clock_gettime(Process::CLOCK_REALTIME, precision)
38
+ end
39
+ end
8
40
  end
metadata CHANGED
@@ -1,30 +1,52 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: influx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lapo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-23 00:00:00.000000000 Z
11
+ date: 2022-05-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: InfluxDB Flux ORM for Ruby
13
+ description: InfluxDB Flux queries builder for Ruby
14
14
  email:
15
15
  - lapoelisacci@gmail.com
16
16
  executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - ".rspec"
20
21
  - ".rubocop.yml"
21
22
  - CHANGELOG.md
22
23
  - CODE_OF_CONDUCT.md
23
24
  - Gemfile
25
+ - Gemfile.lock
24
26
  - LICENSE.txt
25
27
  - README.md
26
28
  - Rakefile
27
29
  - lib/influx.rb
30
+ - lib/influx/flux/aggregate_window.rb
31
+ - lib/influx/flux/cumulative_sum.rb
32
+ - lib/influx/flux/derivative.rb
33
+ - lib/influx/flux/fill.rb
34
+ - lib/influx/flux/filter.rb
35
+ - lib/influx/flux/first.rb
36
+ - lib/influx/flux/from.rb
37
+ - lib/influx/flux/group.rb
38
+ - lib/influx/flux/histogram.rb
39
+ - lib/influx/flux/increase.rb
40
+ - lib/influx/flux/last.rb
41
+ - lib/influx/flux/limit.rb
42
+ - lib/influx/flux/median.rb
43
+ - lib/influx/flux/moving_average.rb
44
+ - lib/influx/flux/quantile.rb
45
+ - lib/influx/flux/range.rb
46
+ - lib/influx/flux/sort.rb
47
+ - lib/influx/flux/timed_moving_average.rb
48
+ - lib/influx/point.rb
49
+ - lib/influx/query.rb
28
50
  - lib/influx/version.rb
29
51
  - sig/influx.rbs
30
52
  homepage: https://github.com/LapoElisacci/influx
@@ -45,12 +67,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
45
67
  version: 2.6.0
46
68
  required_rubygems_version: !ruby/object:Gem::Requirement
47
69
  requirements:
48
- - - ">"
70
+ - - ">="
49
71
  - !ruby/object:Gem::Version
50
- version: 1.3.1
72
+ version: '0'
51
73
  requirements: []
52
- rubygems_version: 3.3.9
74
+ rubygems_version: 3.2.22
53
75
  signing_key:
54
76
  specification_version: 4
55
- summary: InfluxDB Flux ORM for Ruby
77
+ summary: InfluxDB Flux queries builder for Ruby
56
78
  test_files: []