1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
module Riemann
class Event
require 'set'
include Beefcake::Message
optional :time, :int64, 1
optional :state, :string, 2
optional :service, :string, 3
optional :host, :string, 4
optional :description, :string, 5
repeated :tags, :string, 7
optional :ttl, :float, 8
repeated :attributes, Attribute, 9
optional :metric_sint64, :sint64, 13
optional :metric_d, :double, 14
optional :metric_f, :float, 15
# Fields which don't really exist in protobufs, but which are reserved
# and can't be used as attributes.
VIRTUAL_FIELDS = Set.new([:metric])
# Fields which are specially encoded in the Event protobuf--that is, they
# can't be used as attributes.
RESERVED_FIELDS = fields.map do |i, field|
field.name.to_sym
end.reduce(VIRTUAL_FIELDS) do |set, field|
set << field
end
# Average a set of states together. Chooses the mean metric, the mode
# state, mode service, and the mean time. If init is provided, its values
# override (where present) the computed ones.
def self.average(states, init = Event.new)
init = case init
when Event
init.dup
else
Event.new init
end
# Metric
init.metric_f ||= states.inject(0.0) { |a, state|
a + (state.metric || 0)
} / states.size
if init.metric_f.nan?
init.metric_f = 0.0
end
# Event
init.state ||= mode states.map(&:state)
init.service ||= mode states.map(&:service)
# Time
init.time = begin
times = states.map(&:time).compact
(times.inject(:+) / times.size).to_i
rescue
end
init.time ||= Time.now.to_i
init
end
# Sum a set of states together. Adds metrics, takes the mode state, mode
# service and the mean time. If init is provided, its values override
# (where present) the computed ones.
def self.sum(states, init = Event.new)
init = case init
when Event
init.dup
else
Event.new init
end
# Metric
init.metric_f ||= states.inject(0.0) { |a, state|
a + (state.metric || 0)
}
if init.metric_f.nan?
init.metric_f = 0.0
end
# Event
init.state ||= mode states.map(&:state)
init.service ||= mode states.map(&:service)
# Time
init.time = begin
times = states.map(&:time).compact
(times.inject(:+) / times.size).to_i
rescue
end
init.time ||= Time.now.to_i
init
end
# Finds the maximum of a set of states. Metric is the maximum. Event is the
# highest, as defined by Dash.config.state_order. Time is the mean.
def self.max(states, init = Event.new)
init = case init
when Event
init.dup
else
Event.new init
end
# Metric
init.metric_f ||= states.inject(0.0) { |a, state|
a + (state.metric || 0)
}
if init.metric.nan?
init.metric = 0.0
end
# Event
init.state ||= states.inject(nil) do |max, state|
state.state if Dash.config[:state_order][state.state] > Dash.config[:state_order][max]
end
# Time
init.time = begin
times = states.map(&:time).compact
(times.inject(:+) / times.size).to_i
rescue
end
init.time ||= Time.now.to_i
init
end
def self.mode(array)
array.inject(Hash.new(0)) do |counts, e|
counts[e] += 1
counts
end.sort_by { |e, count| count }.last.first rescue nil
end
# Partition a list of states by a field
# Returns a hash of field_value => state
def self.partition(states, field)
states.inject({}) do |p, state|
k = state.send field
if p.include? k
p[k] << state
else
p[k] = [state]
end
p
end
end
# Sorts states by a field. nil values first.
def self.sort(states, field)
states.sort do |a, b|
a = a.send field
b = b.send field
if a.nil?
-1
elsif b.nil?
1
else
a <=> b
end
end
end
def initialize(hash = nil)
if hash
if hash[:metric]
super hash
self.metric = hash[:metric]
else
super hash
end
# Add extra attributes to the event as Attribute instances with values
# converted to String
self.attributes = hash.map do |key, value|
unless RESERVED_FIELDS.include? key.to_sym
Attribute.new(:key => key.to_s,
:value => (hash[key] || hash[key.to_sym]).to_s)
end
end.compact
else
super()
end
@time ||= Time.now.to_i
end
def metric
metric_d ||
metric_sint64 ||
metric_f
end
def metric=(m)
if Integer === m and (-(2**63)...2**63) === m
# Long
self.metric_sint64 = m
self.metric_f = m.to_f
else
self.metric_d = m.to_f
self.metric_f = m.to_f
end
end
# Look up attributes
def [](k)
if RESERVED_FIELDS.include? k.to_sym
super
else
r = attributes.find {|a| a.key.to_s == k.to_s }.value
end
end
# Set attributes
def []=(k, v)
if RESERVED_FIELDS.include? k.to_sym
super
else
a = self.attributes.find {|a| a.key == k.to_s }
if(a)
a.value = v.to_s
else
self.attributes << Attribute.new(:key => k.to_s, :value => v.to_s)
end
end
end
end
end
|