Class: Mouth::SequenceQuery

Inherits:
Object
  • Object
show all
Defined in:
lib/mouth/sequence_query.rb

Overview

Usage: SequenceQuery.new().sequences # => => [4, 9, 0, …]

SequenceQuery.new([“namespace.foobar_occurances”, “namespace.baz”], :kind => :timer).sequences # => => [{:count => 3, :min => 1, …, …], “baz” => […]}

s = SequenceQuery.new(…) s.time_sequence # => [Time.new(first datapoint), Time.new(second datapoint), …, Time.new(last datapoint)]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(keys, opts = {}) ⇒ SequenceQuery

Returns a new instance of SequenceQuery.

Raises:

  • (StandardError)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/mouth/sequence_query.rb', line 23

def initialize(keys, opts = {})
  opts = {
    :kind => :counter,
    :granularity_in_minutes => 1,
    :start_time => Time.now - (119 * 60),
    :end_time => Time.now,
  }.merge(opts)
  
  self.keys = Array(keys)
  self.kind = opts[:kind]
  self.granularity_in_minutes = opts[:granularity_in_minutes]
  self.start_time = opts[:start_time]
  self.end_time = opts[:end_time]
  
  self.metrics = []
  namespaces = []
  self.keys.each do |k|
    namespace, metric = Mouth.parse_key(k)
    namespaces << namespace
    self.metrics << metric
  end
  raise StandardError.new("Batch calculation must come from the same namespace") if namespaces.uniq.length > 1
  self.namespace = namespaces.first
end

Instance Attribute Details

#end_timeObject

Returns the value of attribute end_time.



19
20
21
# File 'lib/mouth/sequence_query.rb', line 19

def end_time
  @end_time
end

#granularity_in_minutesObject

Returns the value of attribute granularity_in_minutes.



17
18
19
# File 'lib/mouth/sequence_query.rb', line 17

def granularity_in_minutes
  @granularity_in_minutes
end

#keysObject

Returns the value of attribute keys.



15
16
17
# File 'lib/mouth/sequence_query.rb', line 15

def keys
  @keys
end

#kindObject

Returns the value of attribute kind.



16
17
18
# File 'lib/mouth/sequence_query.rb', line 16

def kind
  @kind
end

#metricsObject

Returns the value of attribute metrics.



21
22
23
# File 'lib/mouth/sequence_query.rb', line 21

def metrics
  @metrics
end

#namespaceObject

Returns the value of attribute namespace.



20
21
22
# File 'lib/mouth/sequence_query.rb', line 20

def namespace
  @namespace
end

#start_timeObject

Returns the value of attribute start_time.



18
19
20
# File 'lib/mouth/sequence_query.rb', line 18

def start_time
  @start_time
end

Class Method Details

.generate_sample(opts = {}) ⇒ Object

Generates a sample sequence of both counter and timing



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/mouth/sequence_query.rb', line 307

def self.generate_sample(opts = {})
  opts = {
    :namespace => "sample",
    :metric => "sample",
    :start_time => (Mouth.current_timestamp - 300),
    :end_time => (Mouth.current_timestamp / 60),
  }.merge(opts)
  
  collection = Mouth.collection_for(opts[:namespace])
  
  counter = 99
  gauge = 50
  (opts[:start_time]..opts[:end_time]).each do |t|
    
    # Generate garbage data for the sample
    # NOTE: candidate for improvement
    m_count = rand(20) + 1
    m_mean = rand(20) + 40
    m_doc = {
      "count" => m_count,
      "min" => rand(20),
      "max" => rand(20) + 80,
      "mean" => m_mean,
      "sum" => m_mean * m_count,
      "median" => m_mean + rand(5),
      "stddev" => rand(10)
    }
    
    set = {"c.#{opts[:metric]}" => counter, "m.#{opts[:metric]}" => m_doc}
    if rand(4) == 0
      set["g.#{opts[:metric]}"] = gauge
    end
    
    # Insert the document into mongo
    collection.update({"t" => t}, {"$set" => set}, :upsert => true)
    
    # Update counter randomly
    counter += rand(10) - 5
    gauge += rand(10) - 5
    counter = 0 if counter < 0
    gauge = 0 if gauge < 0
  end
  
  true
end

Instance Method Details

#epoch_sequenceObject

Epoch in seconds



82
83
84
# File 'lib/mouth/sequence_query.rb', line 82

def epoch_sequence
  time_sequence.collect(&:to_i)
end

#sequenceObject



48
49
50
# File 'lib/mouth/sequence_query.rb', line 48

def sequence
  sequences.values.first
end

#sequencesObject



52
53
54
55
# File 'lib/mouth/sequence_query.rb', line 52

def sequences
  return sequences_for_minute if self.granularity_in_minutes == 1
  sequences_for_x_minutes(self.granularity_in_minutes)
end

#start_time_epochObject



57
58
59
60
61
62
63
# File 'lib/mouth/sequence_query.rb', line 57

def start_time_epoch
  if self.granularity_in_minutes == 1
    (self.start_time.to_i / 60) * 60
  else
    timestamp_to_nearest(self.start_time, self.granularity_in_minutes, :down) * 60
  end
end

#time_sequenceObject



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/mouth/sequence_query.rb', line 65

def time_sequence
  if self.granularity_in_minutes == 1
    start_timestamp = self.start_time.to_i / 60
    end_timestamp = self.end_time.to_i / 60
  else
    start_timestamp = timestamp_to_nearest(self.start_time, self.granularity_in_minutes, :down)
    end_timestamp = timestamp_to_nearest(self.end_time, self.granularity_in_minutes, :up) - 1
  end
  
  seq = []
  (start_timestamp..end_timestamp).step(self.granularity_in_minutes) do |ts|
    seq << Time.at(ts * 60)
  end
  seq
end