influxer 0.0.1 → 0.1.0
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/.gitignore +1 -2
- data/.travis.yml +3 -2
- data/Changelog.md +19 -0
- data/Gemfile +0 -13
- data/MIT-LICENSE +1 -1
- data/README.md +51 -6
- data/gemfiles/rails42.gemfile +7 -0
- data/influxer.gemspec +7 -5
- data/lib/influxer/client.rb +46 -0
- data/lib/influxer/config.rb +10 -0
- data/lib/influxer/metrics/fanout.rb +53 -0
- data/lib/influxer/metrics/metrics.rb +33 -5
- data/lib/influxer/metrics/relation/fanout_query.rb +33 -0
- data/lib/influxer/metrics/relation/time_query.rb +73 -0
- data/lib/influxer/metrics/relation.rb +177 -39
- data/lib/influxer/metrics/scoping/default.rb +28 -0
- data/lib/influxer/metrics/scoping/named.rb +18 -0
- data/lib/influxer/metrics/scoping.rb +56 -0
- data/lib/influxer/model.rb +3 -1
- data/lib/influxer/version.rb +1 -1
- data/spec/client_spec.rb +34 -0
- data/spec/dummy/app/metrics/testo_metrics.rb +1 -1
- data/spec/dummy/app/models/testo.rb +2 -0
- data/spec/dummy/config/application.rb +1 -0
- data/spec/dummy/config/environments/test.rb +0 -1
- data/spec/metrics/fanout_spec.rb +46 -0
- data/spec/metrics/metrics_spec.rb +42 -7
- data/spec/metrics/relation_spec.rb +199 -51
- data/spec/metrics/scoping_spec.rb +68 -0
- data/spec/model/testo_spec.rb +12 -3
- data/spec/spec_helper.rb +1 -1
- metadata +78 -26
@@ -1,12 +1,72 @@
|
|
1
|
+
require 'influxer/metrics/relation/time_query'
|
2
|
+
require 'influxer/metrics/relation/fanout_query'
|
3
|
+
|
1
4
|
module Influxer
|
2
5
|
class Relation
|
6
|
+
attr_reader :values
|
7
|
+
|
8
|
+
include Influxer::TimeQuery
|
9
|
+
include Influxer::FanoutQuery
|
3
10
|
|
11
|
+
MULTI_VALUE_METHODS = [:select, :where, :group]
|
12
|
+
|
13
|
+
MULTI_KEY_METHODS = [:fanout]
|
14
|
+
|
15
|
+
SINGLE_VALUE_METHODS = [:fill, :limit, :merge, :time]
|
16
|
+
|
17
|
+
MULTI_VALUE_SIMPLE_METHODS = [:select, :group]
|
18
|
+
|
19
|
+
SINGLE_VALUE_SIMPLE_METHODS = [:fill, :limit, :merge]
|
20
|
+
|
21
|
+
MULTI_VALUE_METHODS.each do |name|
|
22
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
23
|
+
def #{name}_values # def select_values
|
24
|
+
@values[:#{name}] ||= [] # @values[:select] || []
|
25
|
+
end # end
|
26
|
+
CODE
|
27
|
+
end
|
28
|
+
|
29
|
+
MULTI_KEY_METHODS.each do |name|
|
30
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
31
|
+
def #{name}_values # def fanout_values
|
32
|
+
@values[:#{name}] ||= {} # @values[:fanout] || {}
|
33
|
+
end # end
|
34
|
+
CODE
|
35
|
+
end
|
36
|
+
|
37
|
+
SINGLE_VALUE_METHODS.each do |name|
|
38
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
39
|
+
def #{name}_value # def limit_value
|
40
|
+
@values[:#{name}] # @values[:limit]
|
41
|
+
end # end
|
42
|
+
CODE
|
43
|
+
end
|
44
|
+
|
45
|
+
SINGLE_VALUE_SIMPLE_METHODS.each do |name|
|
46
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
47
|
+
def #{name}(val) # def limit(val)
|
48
|
+
@values[:#{name}] = val # @value[:limit] = val
|
49
|
+
self # self
|
50
|
+
end # end
|
51
|
+
CODE
|
52
|
+
end
|
53
|
+
|
54
|
+
MULTI_VALUE_SIMPLE_METHODS.each do |name|
|
55
|
+
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
56
|
+
def #{name}(*args) # def select(*args)
|
57
|
+
#{name}_values.concat args.map(&:to_s) # select_values.concat args.map(&:to_s)
|
58
|
+
self # self
|
59
|
+
end # end
|
60
|
+
CODE
|
61
|
+
end
|
62
|
+
|
4
63
|
# Initialize new Relation for 'klass' (Class) metrics.
|
5
64
|
#
|
6
65
|
# Available params:
|
7
66
|
# :attributes - hash of attributes to be included to new Metrics object and where clause of Relation
|
8
67
|
#
|
9
68
|
def initialize(klass, params = {})
|
69
|
+
@klass = klass
|
10
70
|
@instance = klass.new params[:attributes]
|
11
71
|
self.reset
|
12
72
|
self.where(params[:attributes]) if params[:attributes].present?
|
@@ -26,59 +86,46 @@ module Influxer
|
|
26
86
|
@instance
|
27
87
|
end
|
28
88
|
|
29
|
-
# accepts strings and symbols only
|
30
|
-
def select(*args)
|
31
|
-
return self if args.empty?
|
32
|
-
@select_values.concat args
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
89
|
# accepts hash or strings conditions
|
37
|
-
# TODO: add sanitization and array support
|
38
|
-
|
39
90
|
def where(*args,**hargs)
|
40
|
-
|
41
|
-
|
42
|
-
unless hargs.empty?
|
43
|
-
hargs.each do |key, val|
|
44
|
-
@where_values << "(#{key}=#{quoted(val)})"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
def group(*args)
|
51
|
-
return self if args.empty?
|
52
|
-
@group_values.concat args
|
91
|
+
build_where(args, hargs, false)
|
53
92
|
self
|
54
93
|
end
|
55
94
|
|
56
|
-
def
|
57
|
-
|
95
|
+
def not(*args, **hargs)
|
96
|
+
build_where(args, hargs, true)
|
58
97
|
self
|
59
98
|
end
|
60
99
|
|
61
100
|
def to_sql
|
62
101
|
sql = ["select"]
|
63
102
|
|
64
|
-
if
|
103
|
+
if select_values.empty?
|
65
104
|
sql << "*"
|
66
105
|
else
|
67
|
-
sql <<
|
106
|
+
sql << select_values.uniq.join(",")
|
68
107
|
end
|
69
108
|
|
70
|
-
sql << "from #{
|
109
|
+
sql << "from #{ build_series_name }"
|
110
|
+
|
111
|
+
unless merge_value.nil?
|
112
|
+
sql << "merge #{ @instance.quote_series(merge_value) }"
|
113
|
+
end
|
114
|
+
|
115
|
+
unless group_values.empty? and time_value.nil?
|
116
|
+
sql << "group by #{ (time_value.nil? ? [] : ['time('+@values[:time]+')']).concat(group_values).uniq.join(",") }"
|
117
|
+
end
|
71
118
|
|
72
|
-
unless
|
73
|
-
sql << "
|
119
|
+
unless fill_value.nil?
|
120
|
+
sql << "fill(#{ fill_value })"
|
74
121
|
end
|
75
122
|
|
76
|
-
unless
|
77
|
-
sql << "where #{
|
123
|
+
unless where_values.empty?
|
124
|
+
sql << "where #{ where_values.join(" and ") }"
|
78
125
|
end
|
79
126
|
|
80
|
-
unless
|
81
|
-
sql << "limit #{
|
127
|
+
unless limit_value.nil?
|
128
|
+
sql << "limit #{ limit_value }"
|
82
129
|
end
|
83
130
|
sql.join " "
|
84
131
|
end
|
@@ -101,12 +148,96 @@ module Influxer
|
|
101
148
|
end
|
102
149
|
|
103
150
|
def delete_all
|
151
|
+
sql = ["delete"]
|
152
|
+
|
153
|
+
sql << "from #{@instance.series}"
|
154
|
+
|
155
|
+
unless where_values.empty?
|
156
|
+
sql << "where #{where_values.join(" and ")}"
|
157
|
+
end
|
158
|
+
|
159
|
+
sql = sql.join " "
|
160
|
+
|
161
|
+
@instance.client.query sql
|
162
|
+
end
|
163
|
+
|
164
|
+
def scoping
|
165
|
+
previous, @klass.current_scope = @klass.current_scope, self
|
166
|
+
yield
|
167
|
+
ensure
|
168
|
+
@klass.current_scope = previous
|
169
|
+
end
|
170
|
+
|
171
|
+
def merge!(rel)
|
172
|
+
return self if rel.nil?
|
173
|
+
MULTI_VALUE_METHODS.each do |method|
|
174
|
+
(@values[method]||=[]).concat(rel.values[method]).uniq! unless rel.values[method].nil?
|
175
|
+
end
|
176
|
+
|
177
|
+
MULTI_KEY_METHODS.each do |method|
|
178
|
+
(@values[method]||={}).merge!(rel.values[method]) unless rel.values[method].nil?
|
179
|
+
end
|
180
|
+
|
181
|
+
SINGLE_VALUE_METHODS.each do |method|
|
182
|
+
@values[method] = rel.values[method] unless rel.values[method].nil?
|
183
|
+
end
|
104
184
|
|
185
|
+
self
|
105
186
|
end
|
106
187
|
|
107
188
|
protected
|
189
|
+
def build_where(args, hargs, negate)
|
190
|
+
case
|
191
|
+
when (args.present? and args[0].is_a?(String))
|
192
|
+
where_values.concat args.map{|str| "(#{str})"}
|
193
|
+
when hargs.present?
|
194
|
+
build_hash_where(hargs, negate)
|
195
|
+
else
|
196
|
+
false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def build_hash_where(hargs, negate = false)
|
201
|
+
hargs.each do |key, val|
|
202
|
+
if @klass.fanout?(key)
|
203
|
+
build_fanout(key,val)
|
204
|
+
else
|
205
|
+
where_values << "(#{ build_eql(key,val,negate) })"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def build_eql(key,val,negate)
|
211
|
+
case val
|
212
|
+
when Regexp
|
213
|
+
"#{key}#{ negate ? '!~' : '=~'}#{val.inspect}"
|
214
|
+
when Array
|
215
|
+
build_in(key,val,negate)
|
216
|
+
when Range
|
217
|
+
build_range(key,val,negate)
|
218
|
+
else
|
219
|
+
"#{key}#{ negate ? '<>' : '='}#{quoted(val)}"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def build_in(key, arr, negate)
|
224
|
+
buf = []
|
225
|
+
arr.each do |val|
|
226
|
+
buf << build_eql(key,val,negate)
|
227
|
+
end
|
228
|
+
"#{ buf.join( negate ? ' and ' : ' or ') }"
|
229
|
+
end
|
230
|
+
|
231
|
+
def build_range(key,val,negate)
|
232
|
+
unless negate
|
233
|
+
"#{key}>#{quoted(val.begin)} and #{key}<#{quoted(val.end)}"
|
234
|
+
else
|
235
|
+
"#{key}<#{quoted(val.begin)} and #{key}>#{quoted(val.end)}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
108
239
|
def load
|
109
|
-
@records = @instance.client.
|
240
|
+
@records = get_points(@instance.client.cached_query(to_sql))
|
110
241
|
@loaded = true
|
111
242
|
end
|
112
243
|
|
@@ -115,10 +246,7 @@ module Influxer
|
|
115
246
|
end
|
116
247
|
|
117
248
|
def reset
|
118
|
-
@
|
119
|
-
@select_values = []
|
120
|
-
@group_values = []
|
121
|
-
@where_values = []
|
249
|
+
@values = {}
|
122
250
|
@records = nil
|
123
251
|
@loaded = false
|
124
252
|
self
|
@@ -131,7 +259,7 @@ module Influxer
|
|
131
259
|
end
|
132
260
|
|
133
261
|
def quoted(val)
|
134
|
-
if val.is_a?(String)
|
262
|
+
if val.is_a?(String) or val.is_a?(Symbol)
|
135
263
|
"'#{val}'"
|
136
264
|
elsif val.kind_of?(Time) or val.kind_of?(DateTime)
|
137
265
|
"#{val.to_i}s"
|
@@ -139,5 +267,15 @@ module Influxer
|
|
139
267
|
val.to_s
|
140
268
|
end
|
141
269
|
end
|
270
|
+
|
271
|
+
def method_missing(method, *args, &block)
|
272
|
+
if @klass.respond_to?(method)
|
273
|
+
merge!(scoping { @klass.public_send(method, *args, &block) })
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def get_points(hash)
|
278
|
+
hash.values.reduce([],:+)
|
279
|
+
end
|
142
280
|
end
|
143
281
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Influxer
|
2
|
+
module Scoping
|
3
|
+
module Default
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :default_scopes
|
8
|
+
self.default_scopes = []
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def default_scope(scope)
|
13
|
+
self.default_scopes += [scope] unless scope.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def unscoped
|
17
|
+
Relation.new self
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_scoped
|
21
|
+
self.default_scopes.inject(Relation.new(self)) do |rel, scope|
|
22
|
+
rel.merge!(rel.scoping{ scope.call })
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Influxer
|
2
|
+
module Scoping
|
3
|
+
module Named
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def scope(name, scope)
|
8
|
+
raise Error.new("Scope not defined: #{name}") if scope.nil? or !scope.respond_to?(:call)
|
9
|
+
singleton_class.send(:define_method, name) do |*args|
|
10
|
+
rel = all
|
11
|
+
rel.merge!(rel.scoping { scope.call(*args) })
|
12
|
+
rel
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_support/per_thread_registry'
|
2
|
+
require 'influxer/metrics/scoping/default'
|
3
|
+
require 'influxer/metrics/scoping/named'
|
4
|
+
|
5
|
+
module Influxer
|
6
|
+
module Scoping
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
class Error < StandardError; end;
|
10
|
+
|
11
|
+
included do
|
12
|
+
include Default
|
13
|
+
include Named
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def current_scope #:nodoc:
|
18
|
+
ScopeRegistry.value_for(:current_scope, name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_scope=(scope) #:nodoc:
|
22
|
+
ScopeRegistry.set_value_for(:current_scope, name, scope)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ScopeRegistry # :nodoc:
|
27
|
+
extend ActiveSupport::PerThreadRegistry
|
28
|
+
|
29
|
+
VALID_SCOPE_TYPES = [:current_scope]
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@registry = Hash.new { |hash, key| hash[key] = {} }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Obtains the value for a given +scope_name+ and +variable_name+.
|
36
|
+
def value_for(scope_type, variable_name)
|
37
|
+
raise_invalid_scope_type!(scope_type)
|
38
|
+
@registry[scope_type][variable_name]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets the +value+ for a given +scope_type+ and +variable_name+.
|
42
|
+
def set_value_for(scope_type, variable_name, value)
|
43
|
+
raise_invalid_scope_type!(scope_type)
|
44
|
+
@registry[scope_type][variable_name] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def raise_invalid_scope_type!(scope_type)
|
50
|
+
if !VALID_SCOPE_TYPES.include?(scope_type)
|
51
|
+
raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/influxer/model.rb
CHANGED
@@ -17,8 +17,10 @@ module Influxer
|
|
17
17
|
attrs = params[:inherits]
|
18
18
|
end
|
19
19
|
|
20
|
+
_foreign_key = params.key?(:foreign_key) ? params[:foreign_key] : self.to_s.foreign_key
|
21
|
+
|
20
22
|
define_method(metrics_name) do
|
21
|
-
rel_attrs = {
|
23
|
+
rel_attrs = _foreign_key ? {_foreign_key => self.id} : {}
|
22
24
|
|
23
25
|
unless attrs.nil?
|
24
26
|
attrs.each do |key|
|
data/lib/influxer/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -2,6 +2,10 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Influxer::Client do
|
4
4
|
|
5
|
+
after(:each) do
|
6
|
+
Rails.cache.clear
|
7
|
+
end
|
8
|
+
|
5
9
|
let(:conf) { Influxer.config }
|
6
10
|
let(:client) { Influxer.client }
|
7
11
|
|
@@ -11,4 +15,34 @@ describe Influxer::Client do
|
|
11
15
|
expect(client.database).to eq conf.database
|
12
16
|
end
|
13
17
|
|
18
|
+
describe "cache" do
|
19
|
+
before do
|
20
|
+
allow_any_instance_of(Influxer::Client).to receive(:query) do |_, sql|
|
21
|
+
sql
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:q) { "list series" }
|
26
|
+
|
27
|
+
after(:each) do
|
28
|
+
conf.cache = false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should write data to cache" do
|
32
|
+
conf.cache = {}
|
33
|
+
|
34
|
+
client.cached_query(q)
|
35
|
+
expect(Rails.cache.exist?("influxer:listseries")).to be_truthy
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should write data to cache with expiration" do
|
39
|
+
conf.cache = {expires_in: 1}
|
40
|
+
|
41
|
+
client.cached_query(q)
|
42
|
+
expect(Rails.cache.exist?("influxer:listseries")).to be_truthy
|
43
|
+
|
44
|
+
sleep 2
|
45
|
+
expect(Rails.cache.exist?("influxer:listseries")).to be_falsey
|
46
|
+
end
|
47
|
+
end
|
14
48
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class Testo < ActiveRecord::Base
|
2
2
|
has_metrics
|
3
3
|
has_metrics :testo_metrics, class_name: "TestoMetrics", inherits: [:receipt_id]
|
4
|
+
has_metrics :testo2_metrics, class_name: "TestoMetrics", foreign_key: :testo
|
5
|
+
has_metrics :custom_metrics, class_name: "TestoMetrics", foreign_key: nil
|
4
6
|
end
|
@@ -7,6 +7,7 @@ require "influxer"
|
|
7
7
|
|
8
8
|
module Dummy
|
9
9
|
class Application < Rails::Application
|
10
|
+
config.cache_store = :memory_store
|
10
11
|
# Settings in config/environments/* take precedence over those specified here.
|
11
12
|
# Application configuration should go into files in config/initializers
|
12
13
|
# -- all .rb files in that directory are automatically loaded.
|
@@ -1,6 +1,5 @@
|
|
1
1
|
Dummy::Application.configure do
|
2
2
|
# Settings specified here will take precedence over those in config/application.rb.
|
3
|
-
|
4
3
|
# The test environment is used exclusively to run your application's
|
5
4
|
# test suite. You never need to work with it otherwise. Remember that
|
6
5
|
# your test database is "scratch space" for the test suite and is wiped
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Influxer::Metrics do
|
4
|
+
before do
|
5
|
+
allow_any_instance_of(Influxer::Client).to receive(:query) do |_, sql|
|
6
|
+
sql
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:dummy) do
|
11
|
+
Class.new(Influxer::Metrics) do
|
12
|
+
set_series 'dummy'
|
13
|
+
default_scope -> { time(:hour) }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:doomy) do
|
18
|
+
Class.new(dummy) do
|
19
|
+
scope :by_user, -> (id) { where(user: id) if id.present? }
|
20
|
+
scope :hourly, -> { where(by: :hour).time(nil) }
|
21
|
+
scope :daily, -> { where(by: :day).time(nil) }
|
22
|
+
|
23
|
+
fanout :by, :user, :account, delimeter: "."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
let(:dappy) do
|
28
|
+
Class.new(doomy) do
|
29
|
+
fanout :user, delimeter: "_"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "fanouts" do
|
34
|
+
it "should work with one fanout" do
|
35
|
+
expect(doomy.by_user(1).to_sql).to eq "select * from \"dummy.user.1\" group by time(1h)"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should work with several fanouts" do
|
39
|
+
expect(dappy.by_user(1).hourly.to_sql).to eq "select * from \"dummy_by_hour_user_1\""
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should work with regexp fanouts" do
|
43
|
+
expect(dappy.where(dummy_id: 100).by_user(/[1-3]/).daily.to_sql).to eq "select * from merge(/^dummy_by_day_user_[1-3]$/) where (dummy_id=100)"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Influxer::Metrics do
|
4
|
+
before do
|
5
|
+
allow_any_instance_of(Influxer::Client).to receive(:query) do |_, sql|
|
6
|
+
sql
|
7
|
+
end
|
8
|
+
end
|
4
9
|
|
5
10
|
let(:metrics) { Influxer::Metrics.new }
|
6
11
|
let(:metrics_class) { Influxer::Metrics }
|
@@ -16,7 +21,10 @@ describe Influxer::Metrics do
|
|
16
21
|
|
17
22
|
specify { expect(metrics_class).to respond_to :all}
|
18
23
|
specify { expect(metrics_class).to respond_to :where}
|
19
|
-
specify { expect(metrics_class).to respond_to :
|
24
|
+
specify { expect(metrics_class).to respond_to :merge}
|
25
|
+
specify { expect(metrics_class).to respond_to :time}
|
26
|
+
specify { expect(metrics_class).to respond_to :past}
|
27
|
+
specify { expect(metrics_class).to respond_to :since}
|
20
28
|
specify { expect(metrics_class).to respond_to :limit}
|
21
29
|
specify { expect(metrics_class).to respond_to :select}
|
22
30
|
specify { expect(metrics_class).to respond_to :delete_all}
|
@@ -86,12 +94,30 @@ describe Influxer::Metrics do
|
|
86
94
|
end
|
87
95
|
end
|
88
96
|
|
97
|
+
let(:dummy_metrics_2) do
|
98
|
+
Class.new(Influxer::Metrics) do
|
99
|
+
set_series "dummy \"A\""
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
let(:dummy_metrics_3) do
|
104
|
+
Class.new(Influxer::Metrics) do
|
105
|
+
set_series /^.*$/
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
89
109
|
let(:dummy_with_2_series) do
|
90
110
|
Class.new(Influxer::Metrics) do
|
91
111
|
set_series :events, :errors
|
92
112
|
end
|
93
113
|
end
|
94
114
|
|
115
|
+
let(:dummy_with_2_series_quoted) do
|
116
|
+
Class.new(Influxer::Metrics) do
|
117
|
+
set_series "dummy \"A\"", "dummy \"B\""
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
95
121
|
let(:dummy_with_proc_series) do
|
96
122
|
Class.new(Influxer::Metrics) do
|
97
123
|
attributes :user_id, :test_id
|
@@ -99,27 +125,36 @@ describe Influxer::Metrics do
|
|
99
125
|
end
|
100
126
|
end
|
101
127
|
|
102
|
-
|
103
|
-
|
104
128
|
describe "set_series" do
|
105
129
|
it "should set series name from class name by default" do
|
106
|
-
expect(DummyMetrics.series).to eq
|
130
|
+
expect(DummyMetrics.new.series).to eq "\"dummy\""
|
107
131
|
end
|
108
132
|
|
109
133
|
it "should set series from subclass" do
|
110
|
-
expect(dummy_metrics.series).to eq
|
134
|
+
expect(dummy_metrics.new.series).to eq "\"dummies\""
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should set series as regexp" do
|
138
|
+
expect(dummy_metrics_3.new.series).to eq '/^.*$/'
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should set series with quotes" do
|
142
|
+
expect(dummy_metrics_2.new.series).to eq "\"dummy \\\"A\\\"\""
|
111
143
|
end
|
112
144
|
|
113
145
|
it "should set several series" do
|
114
|
-
expect(dummy_with_2_series.series).to eq
|
146
|
+
expect(dummy_with_2_series.new.series).to eq "merge(\"events\",\"errors\")"
|
115
147
|
end
|
116
148
|
|
149
|
+
it "should set several series with quotes" do
|
150
|
+
expect(dummy_with_2_series_quoted.new.series).to eq "merge(\"dummy \\\"A\\\"\",\"dummy \\\"B\\\"\")"
|
151
|
+
end
|
117
152
|
|
118
153
|
it "should set series from proc" do
|
119
154
|
expect(dummy_with_proc_series.series).to be_an_instance_of Proc
|
120
155
|
|
121
156
|
m = dummy_with_proc_series.new user_id: 2, test_id:123
|
122
|
-
expect(
|
157
|
+
expect(m.series).to eq "\"test/123/user/2\""
|
123
158
|
end
|
124
159
|
end
|
125
160
|
|