influxer 1.1.4 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +98 -0
  3. data/{MIT-LICENSE → LICENSE.txt} +1 -1
  4. data/README.md +106 -47
  5. data/lib/influxer.rb +10 -9
  6. data/lib/influxer/client.rb +1 -1
  7. data/lib/influxer/config.rb +19 -6
  8. data/lib/influxer/engine.rb +1 -1
  9. data/lib/influxer/metrics/active_model3/model.rb +2 -4
  10. data/lib/influxer/metrics/metrics.rb +10 -13
  11. data/lib/influxer/metrics/quoting/timestamp.rb +23 -11
  12. data/lib/influxer/metrics/relation.rb +33 -17
  13. data/lib/influxer/metrics/relation/calculations.rb +1 -1
  14. data/lib/influxer/metrics/relation/time_query.rb +15 -13
  15. data/lib/influxer/metrics/relation/where_clause.rb +19 -11
  16. data/lib/influxer/metrics/scoping.rb +4 -4
  17. data/lib/influxer/metrics/scoping/current_scope.rb +2 -1
  18. data/lib/influxer/metrics/scoping/default.rb +1 -1
  19. data/lib/influxer/metrics/scoping/named.rb +2 -1
  20. data/lib/influxer/model.rb +4 -9
  21. data/lib/influxer/rails/client.rb +6 -6
  22. data/lib/influxer/version.rb +1 -1
  23. metadata +30 -95
  24. data/.gitignore +0 -37
  25. data/.rspec +0 -2
  26. data/.rubocop.yml +0 -77
  27. data/.travis.yml +0 -10
  28. data/Changelog.md +0 -111
  29. data/Gemfile +0 -10
  30. data/Rakefile +0 -13
  31. data/gemfiles/rails32.gemfile +0 -7
  32. data/gemfiles/rails42.gemfile +0 -7
  33. data/gemfiles/rails5.gemfile +0 -7
  34. data/influxer.gemspec +0 -33
  35. data/spec/cases/points_spec.rb +0 -36
  36. data/spec/cases/write_points_spec.rb +0 -85
  37. data/spec/client_spec.rb +0 -46
  38. data/spec/fixtures/empty_result.json +0 -21
  39. data/spec/fixtures/single_series.json +0 -29
  40. data/spec/metrics/metrics_spec.rb +0 -283
  41. data/spec/metrics/relation_spec.rb +0 -477
  42. data/spec/metrics/scoping_spec.rb +0 -66
  43. data/spec/model/user_spec.rb +0 -46
  44. data/spec/spec_helper.rb +0 -64
  45. data/spec/support/metrics/action_metrics.rb +0 -5
  46. data/spec/support/metrics/custom_metrics.rb +0 -6
  47. data/spec/support/metrics/dummy_metrics.rb +0 -12
  48. data/spec/support/metrics/user_metrics.rb +0 -6
  49. data/spec/support/metrics/visits_metrics.rb +0 -8
  50. data/spec/support/shared_contexts/shared_query.rb +0 -16
  51. data/spec/support/user.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 34d7516d9e613074dcc24cf1c401bf69af544fa8
4
- data.tar.gz: ea286c505a09b55058dc00fa05bebd1786c2de20
2
+ SHA256:
3
+ metadata.gz: cee4a4e35b41eda0936d8f7344a2a06d1dc251a0c9a7303723413f1c3a702d25
4
+ data.tar.gz: 8d027da03e9bae2a76351f1cdd0a21f7f5ccf32eb73282fac95a09fbd8771aad
5
5
  SHA512:
6
- metadata.gz: 96fbc0c09e0127c7be545ffab4e0108a9ea26c7d471678c74095d35ce55827103357ce584b371e86cdd82200ff0ea86a63fb1f4ff61890e6d841b59de1618d35
7
- data.tar.gz: 5e580bcbfebb8ca2d731cd658e81d7cd418dc90a4e423aac8ea47d5cb06ccdd409b4e938d6752be4f9b5955bbcede839a004c3ee77dd7fd103c01471a51e1a22
6
+ metadata.gz: 34fab113906dfeb113cff12cc6bfb0654891502d8ee8382717a1cae7b90d484cdf2933d283a9497a9fd2c2b946ad77f647c0096822d5c61f41368f21fd898f68
7
+ data.tar.gz: 8c30816022d49e8aa74db8945fc9f7bcd5cf73334cf92f886d469f6cc6ca7b11bbe855a876a17bd3898b2db434c2e5b29712606b5c5685ed1bb93e0982e959f6
@@ -0,0 +1,98 @@
1
+ # Change log
2
+
3
+ ## master (unreleased)
4
+
5
+ ## 1.2.2 (2020-10-27)
6
+
7
+ - Fixes [#49](https://github.com/palkan/influxer/issues/49) Cache hash configuration cannot be applied.([@AlexanderShvaykin][])
8
+ - Fixes [#47](https://github.com/palkan/influxer/issues/47) Can't delete data when retention policy is set for a metric. ([@MPursche][])
9
+
10
+ ## 1.2.1 (2020-07-09)
11
+
12
+ - Support for setting timezone in queries to configure influx time calculations, e.g., time epoch aggregation ([@jklimke][])
13
+
14
+ [PR](https://github.com/palkan/influxer/pull/46)
15
+
16
+ ## 1.2.0 (2019-05-20)
17
+
18
+ - **Require Ruby 2.4+**
19
+
20
+ ## 1.1.6
21
+
22
+ - [Fixes [#41](https://github.com/palkan/influxer/issues/41)] Fix query building with empty arrays in `where` clause ([@dimiii][])
23
+
24
+ [PR](https://github.com/palkan/influxer/pull/44)
25
+
26
+ **BREAKING:** `where.not` now returns non-empty result for an empty array.
27
+
28
+ - Support of year alias in queries ([@dimiii][])
29
+
30
+ - [Fixes [#40](https://github.com/palkan/influxer/issues/40)] Avoid adding precision suffix to write queries. ([@palkan][])
31
+
32
+ ## 1.1.5
33
+
34
+ - [Fixes [#37](https://github.com/palkan/influxer/issues/37)] Timestamp ranges are quoted again. ([@jklimke][])
35
+
36
+ ## 1.1.4
37
+
38
+ - [Fixes [#35](https://github.com/palkan/influxer/issues/35)] Support time duration suffix and handle `'s'` and `'ms'` precision. ([@palkan][])
39
+
40
+ [PR](https://github.com/palkan/influxer/pull/36)
41
+
42
+ **BREAKING:** `Time`-like value are only type-casted for `time` key.
43
+
44
+ ## 1.1.2
45
+
46
+ - Support exclusive ranges as `where` arguments. ([@MPursche][])
47
+
48
+ ```ruby
49
+ # range including the end
50
+ where(a: 1..4)
51
+ #=> ... WHERE a >= 1 AND a <= 4
52
+
53
+ #range excluding the end
54
+ where(a: 1...4)
55
+ #=> ... WHERE a >= 1 AND a < 4
56
+ ```
57
+
58
+ ## 1.1.1
59
+
60
+ - [Fixes [#31](https://github.com/palkan/influxer/issues/31)] Fix bug with empty arrays in `where` clause
61
+
62
+ - Introduce `Relation#none` method
63
+
64
+ ## 1.1.0
65
+
66
+ ### Features
67
+
68
+ - Add ability to specify per-metrics retention-policy, precision and database
69
+
70
+ Now you can override default configuration for a specific metrics class:
71
+
72
+ ```ruby
73
+ class CustomMetrics < Influxer::Metrics
74
+ set_database "custom_db"
75
+ set_retention_policy :yearly
76
+ set_precision "ms"
77
+ end
78
+ ```
79
+
80
+ ### Fixes
81
+
82
+ - [Fixes [#30](https://github.com/palkan/influxer/issues/30)] Fix writing points with custom retention policy
83
+
84
+ ### Misc
85
+
86
+ - Update Rubocop configuration and add Rubocop Rake task to defaults
87
+
88
+ ## 1.0.1
89
+
90
+ - Fix missing `#delegate` in ActiveRecord 3.2
91
+
92
+ See [changelog](https://github.com/palkan/influxer/blob/1.0.0/Changelog.md) for earlier versions.
93
+
94
+ [@palkan]: https://github.com/palkan
95
+ [@MPursche]: https://github.com/MPursche
96
+ [@jklimke]: https://github.com/jklimke
97
+ [@dimiii]: https://github.com/dimiii
98
+ [@AlexanderShvaykin]: https://github.com/AlexanderShvaykin
@@ -1,4 +1,4 @@
1
- Copyright 2014 palkan
1
+ Copyright 2014-2020 Vladimir Dementyev
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,50 +1,109 @@
1
- [![Gem Version](https://badge.fury.io/rb/influxer.svg)](https://rubygems.org/gems/influxer) [![Build Status](https://travis-ci.org/palkan/influxer.svg?branch=master)](https://travis-ci.org/palkan/influxer) [![Dependency Status](https://dependencyci.com/github/palkan/influxer/badge)](https://dependencyci.com/github/palkan/influxer)
2
- ## Influxer
1
+ ![Build](https://github.com/palkan/influxer/workflows/Build/badge.svg)
3
2
 
4
- **NOTE**: Version 0.3.x supports InfluxDB >= 0.9.0. For InfluxDB 0.8.x use [version 0.2.5](https://github.com/palkan/influxer/tree/0.2.5).
5
-
6
- **NOTE**: Influxer is Rails 3, 4, 5 compatible!
3
+ # Influxer
7
4
 
8
5
  Influxer provides an ActiveRecord-style way to work with [InfluxDB](https://influxdb.com/) with many useful features, such as:
9
- - Familar query language (use `select`, `where`, `not`, `group` etc).
10
- - Support for Regex conditions: `where(page_id: /^home\/.*/) #=> select * ... where page_id=~/^home\/.*/`.
11
- - Special query methods for InfluxDB:
12
- - `time` - group by time (e.g. `Metrics.time(:hour) => # select * ... group by time(1h)`);
13
- - `past` - get only points for last hour/minute/whatever (e.g. `Metrics.past(:day) => # select * ... where time > now() - 1d`);
14
- - `since` - get only points since date (e.g. `Metrics.since(Time.utc(2014,12,31)) => # select * ... where time > 1419984000s`);
15
- - `merge` - merge series.
16
- - Scopes support
17
- ```ruby
18
- class Metrics < Influxer::Metrics
19
- default_scope -> { time(:hour).limit(1000) }
20
- tags :account_id
21
- attributes :value
22
- scope :unlimited, -> { limit(nil) }
23
- scope :by_account, -> (id) { where(account_id: id) if id.present? }
24
- end
25
-
26
- Metrics.by_account(1)
27
- # => select * from "metrics" group by time(1h) where account_id=1 limit 1000
28
-
29
- Metrics.unlimited.by_account(1).time(:week)
30
- # => select * from "metrics" group by time(1w) where account_id=1
31
-
32
- ```
33
- - Integrate with your model:
34
- ```ruby
35
- class UserVisits < Influxer::Metrics
36
- end
37
-
38
- class User < ActiveRecord::Base
39
- has_metrics :visits
40
- end
41
-
42
- user = User.find(1)
43
- user.visits.write(page_id: 'home')
44
- #=> < creates point {user_id: 1, page_id: 'home'} in 'user_visits' series >
45
-
46
- user.visits.where(page_id: 'home')
47
- #=> select * from user_visits where page_id='home'
48
- ```
49
-
50
- Find more on [Wiki](https://github.com/palkan/influxer/wiki).
6
+
7
+ ## Installation
8
+
9
+ Adding to a gem:
10
+
11
+ ```ruby
12
+ # my-cool-gem.gemspec
13
+ Gem::Specification.new do |spec|
14
+ # ...
15
+ spec.add_dependency "influxer", ">= 1.2.0"
16
+ # ...
17
+ end
18
+ ```
19
+
20
+ Or adding to your project:
21
+
22
+ ```ruby
23
+ # Gemfile
24
+ gem "influxer", "~> 1.2"
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### Metrics classes
30
+
31
+ To query InfluxDB or write to it, you should define a metrics class first. Each metrics class represents a measurement/series (or multiple related measurements):
32
+
33
+ ```ruby
34
+ class VisitsMetrics < Influxer::Metrics
35
+ # Define tags...
36
+ tags :account_id, :page_id
37
+ # ...and attributes
38
+ attributes :user_id, :browser
39
+ end
40
+ ```
41
+
42
+ ### Querying
43
+
44
+ Now you can use your metrics classes in a similar way to Active Record models to build queries. For example:
45
+
46
+ ```ruby
47
+ VisitsMetrics.select(:account_id, :user_id).where(page_id: /^home\/.*/)
48
+ ```
49
+
50
+ Influxer provides special query methods for dealing with time series:
51
+
52
+ - Group by time: `Metrics.time(:hour) => # select * ... group by time(1h)`.
53
+ - Select only points for the last hour/minute/whatever: `Metrics.past(:day) => # select * ... where time > now() - 1d`.
54
+ - Select only points since the specified time: `Metrics.since(Time.utc(2014,12,31)) => # select * ... where time > 1419984000s`.
55
+ - and more.
56
+
57
+ See [our Wiki](https://github.com/palkan/influxer/wiki/Query-methods) for more.
58
+
59
+ ### Scopes support
60
+
61
+ You can define scopes to re-use query conditions:
62
+
63
+ ```ruby
64
+ class Metrics < Influxer::Metrics
65
+ tags :account_id
66
+ attributes :value
67
+
68
+ default_scope -> { time(:hour).limit(1000) }
69
+
70
+ scope :unlimited, -> { limit(nil) }
71
+ scope :by_account, ->(id) { where(account_id: id) if id.present? }
72
+ end
73
+
74
+ Metrics.by_account(1)
75
+ # => select * from "metrics" group by time(1h) where account_id=1 limit 1000
76
+
77
+ Metrics.unlimited.by_account(1).time(:week)
78
+ # => select * from "metrics" group by time(1w) where account_id=1
79
+ ```
80
+
81
+ ### Active Record integration
82
+
83
+ You can association metrics with Active Record models:
84
+
85
+ ```ruby
86
+ class UserVisits < Influxer::Metrics
87
+ end
88
+
89
+ class User < ActiveRecord::Base
90
+ has_metrics :visits
91
+ end
92
+
93
+ user = User.find(1)
94
+ user.visits.write(page_id: "home")
95
+ #=> < creates point {user_id: 1, page_id: 'home'} in 'user_visits' series >
96
+
97
+ user.visits.where(page_id: "home")
98
+ #=> select * from user_visits where page_id='home'
99
+ ```
100
+
101
+ Find more on [Wiki](https://github.com/palkan/influxer/wiki/ActiveRecord-integration).
102
+
103
+ ## Contributing
104
+
105
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/influxer](https://github.com/palkan/influxer).
106
+
107
+ ## License
108
+
109
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'influxer/version'
4
- require 'active_model'
3
+ require "influxer/version"
4
+ require "active_model"
5
+ require "active_support/core_ext"
5
6
 
6
7
  # Rails client for InfluxDB
7
8
  module Influxer
@@ -9,16 +10,16 @@ module Influxer
9
10
  ActiveModel::VERSION::MAJOR == 3
10
11
  end
11
12
 
12
- require 'influxer/config'
13
- require 'influxer/client'
14
- require 'influxer/metrics/metrics'
13
+ require "influxer/config"
14
+ require "influxer/client"
15
+ require "influxer/metrics/metrics"
15
16
 
16
17
  module Model # :nodoc:
17
- require 'influxer/model'
18
+ require "influxer/model"
18
19
  end
19
20
 
20
- require 'influxer/rails/client' if defined?(Rails)
21
- require 'influxer/engine' if defined?(Rails)
21
+ require "influxer/rails/client" if defined?(Rails)
22
+ require "influxer/engine" if defined?(Rails)
22
23
 
23
24
  def self.config
24
25
  @config ||= Config.new
@@ -33,7 +34,7 @@ module Influxer
33
34
  end
34
35
 
35
36
  def self.reset!
36
- @client.stop! unless @client.nil?
37
+ @client&.stop!
37
38
  @config = nil
38
39
  @client = nil
39
40
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'influxdb'
3
+ require "influxdb"
4
4
 
5
5
  module Influxer
6
6
  # InfluxDB API client
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'anyway_config'
3
+ require "anyway_config"
4
4
 
5
5
  module Influxer
6
6
  # Influxer configuration
@@ -28,15 +28,28 @@ module Influxer
28
28
  :denormalize,
29
29
  :udp,
30
30
  :async,
31
- database: 'db',
32
- time_precision: 'ns',
33
- cache: false,
31
+ :cache_enabled,
32
+ :cache,
33
+ database: "db",
34
+ time_precision: "ns",
34
35
  time_duration_suffix_enabled: false
35
36
 
36
37
  def load(*)
37
38
  super
38
- # we want pass @cache value as options to cache store, so we want it to be a Hash
39
- @cache = {}.with_indifferent_access if @cache == true
39
+ if cache_enabled.nil?
40
+ self.cache_enabled = cache_enabled_value
41
+ end
42
+ end
43
+
44
+ def cache=(value)
45
+ super
46
+ self.cache_enabled = cache_enabled_value
47
+ end
48
+
49
+ private
50
+
51
+ def cache_enabled_value
52
+ !!cache
40
53
  end
41
54
  end
42
55
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'influxer'
3
+ require "influxer"
4
4
 
5
5
  module Influxer
6
6
  class Engine < Rails::Engine # :nodoc:
@@ -5,10 +5,8 @@ module Influxer
5
5
  # Replacement of ActiveModel::Model for ActiveModel 3
6
6
  module Model
7
7
  def initialize(attributes = {})
8
- if attributes
9
- attributes.each do |attr, value|
10
- public_send("#{attr}=", value)
11
- end
8
+ attributes&.each do |attr, value|
9
+ public_send("#{attr}=", value)
12
10
  end
13
11
 
14
12
  super()
@@ -1,16 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'influxer/metrics/relation'
4
- require 'influxer/metrics/scoping'
5
- require 'influxer/metrics/quoting/timestamp'
6
- require 'influxer/metrics/active_model3/model'
3
+ require "influxer/metrics/relation"
4
+ require "influxer/metrics/scoping"
5
+ require "influxer/metrics/quoting/timestamp"
6
+ require "influxer/metrics/active_model3/model"
7
7
 
8
8
  module Influxer
9
9
  class MetricsError < StandardError; end
10
10
  class MetricsInvalid < MetricsError; end
11
11
 
12
12
  # Base class for InfluxDB querying and writing
13
- # rubocop:disable Metrics/ClassLength
14
13
  class Metrics
15
14
  TIME_FACTOR = 1_000_000_000
16
15
  if Influxer.active_model3?
@@ -18,7 +17,6 @@ module Influxer
18
17
  else
19
18
  include ActiveModel::Model
20
19
  end
21
- # rubocop:enable Style/MixinUsage
22
20
 
23
21
  include ActiveModel::Validations
24
22
  extend ActiveModel::Callbacks
@@ -35,7 +33,7 @@ module Influxer
35
33
  [
36
34
  :write, :write!, :select, :where,
37
35
  :group, :time, :past, :since,
38
- :limit, :offset, :fill, :delete_all, :epoch
36
+ :limit, :offset, :fill, :delete_all, :epoch, :timezone
39
37
  ] + Influxer::Calculations::CALCULATION_METHODS
40
38
  ),
41
39
  to: :all
@@ -125,7 +123,7 @@ module Influxer
125
123
  quoted_series(val.call(instance), write: write)
126
124
  when Array
127
125
  if val.length > 1
128
- "merge(#{val.map { |s| quoted_series(s, write: write) }.join(',')})"
126
+ "merge(#{val.map { |s| quoted_series(s, write: write) }.join(",")})"
129
127
  else
130
128
  quoted_series(val.first, write: write)
131
129
  end
@@ -133,7 +131,7 @@ module Influxer
133
131
  # Only add retention policy when selecting points
134
132
  # and not writing
135
133
  if !write && retention_policy.present?
136
- [quote(@retention_policy), quote(val)].join('.')
134
+ [quote(@retention_policy), quote(val)].join(".")
137
135
  else
138
136
  quote(val)
139
137
  end
@@ -169,6 +167,7 @@ module Influxer
169
167
 
170
168
  def write!
171
169
  raise MetricsInvalid if invalid?
170
+
172
171
  write
173
172
  end
174
173
 
@@ -225,13 +224,11 @@ module Influxer
225
224
  end
226
225
 
227
226
  def parsed_timestamp
228
- quote_timestamp @timestamp, client
227
+ quote_timestamp_for_write @timestamp, client
229
228
  end
230
- # rubocop:enable Metrics/MethodLength
231
- # rubocop:enable Metrics/AbcSize
232
229
 
233
230
  def unquote(name)
234
- name.gsub(/(\A['"]|['"]\z)/, '')
231
+ name.gsub(/(\A['"]|['"]\z)/, "")
235
232
  end
236
233
  end
237
234
  end