Class: ScoutApm::NumericHistogram

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_apm/histogram.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_bins) ⇒ NumericHistogram

Returns a new instance of NumericHistogram.



21
22
23
24
25
26
# File 'lib/scout_apm/histogram.rb', line 21

def initialize(max_bins)
  @max_bins = max_bins
  @bins = []
  @total = 0
  @mutex = Mutex.new
end

Instance Attribute Details

#binsObject (readonly)

Returns the value of attribute bins.



9
10
11
# File 'lib/scout_apm/histogram.rb', line 9

def bins
  @bins
end

#max_binsObject (readonly)

Returns the value of attribute max_bins.



8
9
10
# File 'lib/scout_apm/histogram.rb', line 8

def max_bins
  @max_bins
end

#mutexObject (readonly)

This class should be threadsafe.



6
7
8
# File 'lib/scout_apm/histogram.rb', line 6

def mutex
  @mutex
end

#totalObject

Returns the value of attribute total.



10
11
12
# File 'lib/scout_apm/histogram.rb', line 10

def total
  @total
end

Instance Method Details

#add(new_value) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/scout_apm/histogram.rb', line 28

def add(new_value)
  mutex.synchronize do
    @total += 1
    create_new_bin(new_value.to_f)
    trim
  end
end

#approximate_quantile_of_value(v) ⇒ Object

Given a value, where in this histogram does it fall? Returns a float between 0 and 1



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/scout_apm/histogram.rb', line 61

def approximate_quantile_of_value(v)
  mutex.synchronize do
    return 100 if total == 0

    count_examined = 0

    bins.each_with_index do |bin, index|
      if v <= bin.value
        break
      end

      count_examined += bin.count
    end

    count_examined / total.to_f
  end
end

#as_jsonObject



105
106
107
108
109
110
111
112
113
114
# File 'lib/scout_apm/histogram.rb', line 105

def as_json
  mutex.synchronize do
    bins.map{ |b|
      [
        ScoutApm::Utils::Numbers.round(b.value, 4),
        b.count
      ]
    }
  end
end

#combine!(other) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/scout_apm/histogram.rb', line 90

def combine!(other)
  mutex.synchronize do
    other.mutex.synchronize do
      @bins = (other.bins + @bins).
        group_by {|b| b.value }.
        map {|val, bs| [val, bs.inject(0) {|sum, b| sum + b.count }] }.
        map {|val, sum| HistogramBin.new(val,sum) }.
        sort_by { |b| b.value }
      @total += other.total
      trim
      self
    end
  end
end

#marshal_dumpObject



12
13
14
# File 'lib/scout_apm/histogram.rb', line 12

def marshal_dump
  [@max_bins, @bins, @total]
end

#marshal_load(array) ⇒ Object



16
17
18
19
# File 'lib/scout_apm/histogram.rb', line 16

def marshal_load(array)
  @max_bins, @bins, @total = array
  @mutex = Mutex.new
end

#meanObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/scout_apm/histogram.rb', line 79

def mean
  mutex.synchronize do
    if total == 0
      return 0
    end

    sum = bins.inject(0) { |s, bin| s + (bin.value * bin.count) }
    return sum.to_f / total.to_f
  end
end

#quantile(q) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/scout_apm/histogram.rb', line 36

def quantile(q)
  mutex.synchronize do
    return 0 if total == 0

    if q > 1
      q = q / 100.0
    end

    count = q.to_f * total.to_f

    bins.each_with_index do |bin, index|
      count -= bin.count

      if count <= 0
        return bin.value
      end
    end

    # If we fell through, we were asking for the last (max) value
    return bins[-1].value
  end
end