rrd-grapher 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/.gitignore +9 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +11 -0
  4. data/Guardfile +123 -0
  5. data/README.md +91 -0
  6. data/Rakefile +42 -0
  7. data/example_app/Gemfile +9 -0
  8. data/example_app/Guardfile +18 -0
  9. data/example_app/app.rb +38 -0
  10. data/example_app/assets/javascripts/available_rrds.coffee +13 -0
  11. data/example_app/assets/javascripts/collectd.coffee +48 -0
  12. data/example_app/config.ru +9 -0
  13. data/example_app/public/.gitignore +1 -0
  14. data/example_app/public/chosen/chosen-sprite.png +0 -0
  15. data/example_app/public/chosen/chosen.css +340 -0
  16. data/example_app/public/chosen/chosen.jquery.js +786 -0
  17. data/example_app/public/chosen/chosen.jquery.min.js +10 -0
  18. data/example_app/public/javascripts/available_rrds.js +16 -0
  19. data/example_app/public/javascripts/collectd.js +64 -0
  20. data/example_app/public/javascripts/jquery.timeago.js +148 -0
  21. data/example_app/public/stylesheets/Aristo/images/bg_fallback.png +0 -0
  22. data/example_app/public/stylesheets/Aristo/images/icon_sprite.png +0 -0
  23. data/example_app/public/stylesheets/Aristo/images/progress_bar.gif +0 -0
  24. data/example_app/public/stylesheets/Aristo/images/slider_handles.png +0 -0
  25. data/example_app/public/stylesheets/Aristo/images/ui-icons_222222_256x240.png +0 -0
  26. data/example_app/public/stylesheets/Aristo/images/ui-icons_454545_256x240.png +0 -0
  27. data/example_app/public/stylesheets/Aristo/theme.css +738 -0
  28. data/example_app/views/available_rrds.haml +26 -0
  29. data/example_app/views/collectd.haml +30 -0
  30. data/example_app/views/layout.haml +19 -0
  31. data/example_app/views/stylesheets/available_rrds.scss +7 -0
  32. data/example_notifier/Gemfile +2 -0
  33. data/example_notifier/notifier.rb +25 -0
  34. data/lib/rrd-grapher/assets/javascripts/app-dev.js +20 -0
  35. data/lib/rrd-grapher/assets/javascripts/app.js +20 -0
  36. data/lib/rrd-grapher/assets/javascripts/classes/format.coffee +35 -0
  37. data/lib/rrd-grapher/assets/javascripts/classes/graph.coffee +306 -0
  38. data/lib/rrd-grapher/assets/javascripts/classes/graph_definition.coffee +216 -0
  39. data/lib/rrd-grapher/assets/javascripts/classes/serie.coffee +13 -0
  40. data/lib/rrd-grapher/assets/javascripts/classes/size.coffee +5 -0
  41. data/lib/rrd-grapher/assets/javascripts/classes/static_line.coffee +44 -0
  42. data/lib/rrd-grapher/assets/javascripts/classes/time.coffee +17 -0
  43. data/lib/rrd-grapher/notifier/alarm_manager.rb +190 -0
  44. data/lib/rrd-grapher/notifier/alarm_trigger.rb +187 -0
  45. data/lib/rrd-grapher/notifier/alarms.rb +79 -0
  46. data/lib/rrd-grapher/notifier/collectdrb.rb +86 -0
  47. data/lib/rrd-grapher/notifier/data_struct.rb +46 -0
  48. data/lib/rrd-grapher/notifier/default_user_handler.rb +36 -0
  49. data/lib/rrd-grapher/notifier/parsers/bindata_parser.rb +144 -0
  50. data/lib/rrd-grapher/notifier/parsers/ruby_parser.rb +134 -0
  51. data/lib/rrd-grapher/notifier/structures.rb +80 -0
  52. data/lib/rrd-grapher/notifier.rb +87 -0
  53. data/lib/rrd-grapher/public/favicon.ico +0 -0
  54. data/lib/rrd-grapher/public/javascripts/app-dev.js +13709 -0
  55. data/lib/rrd-grapher/public/javascripts/app.js +4057 -0
  56. data/lib/rrd-grapher/public/javascripts/backbone/backbone.js +1155 -0
  57. data/lib/rrd-grapher/public/javascripts/backbone/backbone.min.js +32 -0
  58. data/lib/rrd-grapher/public/javascripts/backbone/underscore.js +841 -0
  59. data/lib/rrd-grapher/public/javascripts/backbone/underscore.min.js +27 -0
  60. data/lib/rrd-grapher/public/javascripts/classes/format.js +42 -0
  61. data/lib/rrd-grapher/public/javascripts/classes/graph.js +360 -0
  62. data/lib/rrd-grapher/public/javascripts/classes/graph_definition.js +298 -0
  63. data/lib/rrd-grapher/public/javascripts/classes/serie.js +32 -0
  64. data/lib/rrd-grapher/public/javascripts/classes/size.js +7 -0
  65. data/lib/rrd-grapher/public/javascripts/classes/static_line.js +48 -0
  66. data/lib/rrd-grapher/public/javascripts/classes/time.js +17 -0
  67. data/lib/rrd-grapher/public/javascripts/flot/.gitignore +4 -0
  68. data/lib/rrd-grapher/public/javascripts/flot/excanvas.min.js +1 -0
  69. data/lib/rrd-grapher/public/javascripts/flot/jquery.colorhelpers.min.js +1 -0
  70. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.crosshair.min.js +1 -0
  71. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.fillbetween.min.js +1 -0
  72. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.image.min.js +1 -0
  73. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.js +2604 -0
  74. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.navigate.min.js +1 -0
  75. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.pie.min.js +1 -0
  76. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.resize.min.js +1 -0
  77. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.js +345 -0
  78. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.selection.min.js +1 -0
  79. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.stack.min.js +1 -0
  80. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.symbol.min.js +1 -0
  81. data/lib/rrd-grapher/public/javascripts/flot/jquery.flot.threshold.min.js +1 -0
  82. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.js +8981 -0
  83. data/lib/rrd-grapher/public/javascripts/jquery/jquery-1.6.2.min.js +18 -0
  84. data/lib/rrd-grapher/public/javascripts/jquery/jquery-ui-1.8.11.min.js +783 -0
  85. data/lib/rrd-grapher/public/javascripts/jquery/jquery.showtime.js +63 -0
  86. data/lib/rrd-grapher/public/javascripts/jquery/jquery.tpl.min.js +10 -0
  87. data/lib/rrd-grapher/resources.rb +14 -0
  88. data/lib/rrd-grapher/rrd.rb +238 -0
  89. data/lib/rrd-grapher/rrd_server.rb +78 -0
  90. data/lib/rrd-grapher/version.rb +4 -0
  91. data/lib/rrd-grapher/views/stylesheets/app.scss +111 -0
  92. data/lib/rrd-grapher.rb +12 -0
  93. data/rrd-grapher.gemspec +47 -0
  94. data/spec/common.rb +70 -0
  95. data/spec/data/myrouter.rrd +0 -0
  96. data/spec/data/subdata.rrd +0 -0
  97. data/spec/data/test.rrd +0 -0
  98. data/spec/factories.rb +23 -0
  99. data/spec/javascripts/helpers/jasmine-jquery-1.3.0.js +283 -0
  100. data/spec/javascripts/source/format_spec.coffee +18 -0
  101. data/spec/javascripts/source/graph_def_spec.coffee +27 -0
  102. data/spec/javascripts/source/graph_spec.coffee +63 -0
  103. data/spec/javascripts/source/serie_spec.coffee +28 -0
  104. data/spec/javascripts/source/static_line_spec.coffee +13 -0
  105. data/spec/javascripts/source/time_spec.coffee +26 -0
  106. data/spec/javascripts/support/jasmine.yml +78 -0
  107. data/spec/javascripts/support/jasmine_config.rb +23 -0
  108. data/spec/javascripts/support/jasmine_runner.rb +32 -0
  109. data/spec/unit/alarm_manager_spec.rb +252 -0
  110. data/spec/unit/alarm_trigger_spec.rb +26 -0
  111. data/spec/unit/data_struct_spec.rb +55 -0
  112. data/spec/unit/notifier_spec.rb +45 -0
  113. data/spec/unit/parsers/bindata_parser_spec.rb +184 -0
  114. data/spec/unit/parsers/ruby_parser_spec.rb +184 -0
  115. data/spec/unit/rrd_spec.rb +50 -0
  116. data/spec/unit/structures_spec.rb +28 -0
  117. data/tests/4series.rrd +0 -0
  118. data/tests/analyze_rrd.rb +62 -0
  119. data/tests/exact.rrd +0 -0
  120. data/tests/exact2.rrd +0 -0
  121. data/tests/filler.rb +46 -0
  122. metadata +414 -0
@@ -0,0 +1,252 @@
1
+
2
+ require 'eventmachine'
3
+
4
+ require File.expand_path('../../common', __FILE__)
5
+ require File.expand_path('../../../lib/rrd-grapher/notifier/alarm_manager', __FILE__)
6
+
7
+
8
+ describe 'AlarmManager' do
9
+ before do
10
+ @manager = RRDNotifier::AlarmManager.new
11
+ end
12
+
13
+ should 'create the manager' do
14
+ @manager.should.not == nil
15
+ end
16
+
17
+ describe 'with a user notification handler' do
18
+ before do
19
+ @handler_class = Class.new do
20
+ def dispatch_notification(notification); end
21
+ def alarm_started(alarm); end
22
+ def alarm_stopped(alarm); end
23
+ end
24
+
25
+ @handler = @handler_class.new
26
+
27
+ @manager = RRDNotifier::AlarmManager.new(:notification_handler => @handler)
28
+ end
29
+
30
+ should 'dispatch notification as is' do
31
+ notif = Factory(:notification)
32
+ @handler.expects(:dispatch_notification).with(notif)
33
+ @manager.packet_received(notif)
34
+ end
35
+
36
+ should 'notify the user handler when an alarm is raised' do
37
+ packet = Factory(:data_point)
38
+ alarm = RRDNotifier::AlarmTooLow.new(packet, 10)
39
+
40
+ @handler.expects(:alarm_started).with(alarm)
41
+ @manager.raise_alarm(packet.measure_id, alarm)
42
+ end
43
+
44
+ should 'notify the user handler when an alarm is stopped' do
45
+ p = Factory(:data_point)
46
+ alarm = RRDNotifier::AlarmTooLow.new(p, 10)
47
+
48
+ @handler.expects(:alarm_stopped).with(alarm)
49
+ @manager.stop_specific_alarm(p.measure_id, alarm)
50
+ end
51
+ end
52
+
53
+ describe 'a trigger on low value' do
54
+ before do
55
+ @manager.register_alarm('*', "memory/*", "memory/active", :min => 10)
56
+ end
57
+
58
+ should 'raise an alarm for a value below the threshold' do
59
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
60
+
61
+ @manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::AlarmTooLow) )
62
+
63
+ @manager.packet_received(p)
64
+ end
65
+
66
+ should 'not raise an alarm for a value above the threshold' do
67
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
68
+
69
+ @manager.expects(:raise_alarm).never
70
+
71
+ @manager.packet_received(p)
72
+ end
73
+
74
+ should 'not reraise another alarm if the value stays below the threshold' do
75
+ p_alarm = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
76
+ p_alarm2 = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [5])
77
+
78
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmTooLow.new(p_alarm, 10)] )
79
+ @manager.expects(:raise_alarm).never
80
+
81
+ @manager.packet_received(p_alarm2)
82
+ end
83
+
84
+ should 'stop the alarm when the value comes back above the threshold' do
85
+ p_alarm = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
86
+ p_normal = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
87
+
88
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmTooLow.new(p_alarm, 10)] )
89
+
90
+ @manager.expects(:raise_alarm).never
91
+ @manager.expects(:stop_specific_alarm).with( p_normal.measure_id, kind_of(RRDNotifier::AlarmTooLow) )
92
+
93
+ @manager.packet_received(p_normal)
94
+ end
95
+
96
+ end
97
+
98
+ describe 'a trigger on high value' do
99
+ before do
100
+ @manager.register_alarm('*', "memory/*", "memory/active", :max => 10)
101
+ end
102
+
103
+ should 'raise an alarm for a value above the threshold' do
104
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
105
+
106
+ @manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::AlarmTooHigh) )
107
+
108
+ @manager.packet_received(p)
109
+ end
110
+
111
+ should 'not raise an alarm for a value below the threshold' do
112
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
113
+
114
+ @manager.expects(:raise_alarm).never
115
+
116
+ @manager.packet_received(p)
117
+ end
118
+
119
+ should 'not reraise another alarm if the value stays above the threshold' do
120
+ p_alarm = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
121
+ p_alarm2 = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
122
+
123
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmTooLow.new(p_alarm, 10)] )
124
+ @manager.expects(:raise_alarm).never
125
+
126
+ @manager.packet_received(p_alarm2)
127
+ end
128
+
129
+ should 'stop the alarm when the value comes back below the threshold' do
130
+ p_alarm = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
131
+ p_normal = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
132
+
133
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmTooHigh.new(p_alarm, 10)] )
134
+
135
+ @manager.expects(:raise_alarm).never
136
+ @manager.expects(:stop_specific_alarm).with( p_normal.measure_id, kind_of(RRDNotifier::AlarmTooHigh) )
137
+
138
+ @manager.packet_received(p_normal)
139
+ end
140
+ end
141
+
142
+ describe 'a trigger on clock drift' do
143
+ before do
144
+ @manager.stubs(:send_gauge)
145
+ @manager.register_alarm('*', "memory/*", "memory/active",
146
+ :monitor_drift => 30 # allow 30s of drift
147
+ )
148
+ end
149
+
150
+ should 'raise an alarm if time difference is higher than threshold' do
151
+ p = Factory(:data_point, :time => Time.now - 60, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
152
+ @manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::AlarmClockDrift) )
153
+
154
+ @manager.packet_received(p)
155
+
156
+ p = Factory(:data_point, :time => Time.now + 60, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
157
+ @manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::AlarmClockDrift) )
158
+
159
+ @manager.packet_received(p)
160
+ end
161
+
162
+ should 'not raise an alarm if time difference is below the threshold' do
163
+ p = Factory(:data_point, :time => Time.now - 20, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
164
+ @manager.expects(:raise_alarm).never
165
+
166
+ @manager.packet_received(p)
167
+
168
+ p = Factory(:data_point, :time => Time.now + 20, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
169
+ @manager.expects(:raise_alarm).never
170
+
171
+ @manager.packet_received(p)
172
+ end
173
+
174
+ should 'not reraise another alarm if time difference stays above the threshold' do
175
+ p_alarm = Factory(:data_point, :time => Time.now - 60, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
176
+ p_alarm2 = Factory(:data_point, :time => Time.now - 50, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
177
+
178
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmClockDrift.new(p_alarm, 30)] )
179
+ @manager.expects(:raise_alarm).never
180
+
181
+ @manager.packet_received(p_alarm2)
182
+ end
183
+
184
+ should 'stop the alarm if time difference moves below the threshold' do
185
+ p_alarm = Factory(:data_point, :time => Time.now - 60, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
186
+ p_normal = Factory(:data_point, :time => Time.now - 10, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [81])
187
+
188
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmClockDrift.new(p_alarm, 30)] )
189
+
190
+ @manager.expects(:raise_alarm).never
191
+ @manager.expects(:stop_specific_alarm).with( p_normal.measure_id, kind_of(RRDNotifier::AlarmClockDrift) )
192
+
193
+ @manager.packet_received(p_normal)
194
+ end
195
+
196
+ end
197
+
198
+ describe 'a trigger on presence' do
199
+ before do
200
+ @interval = 0.5 # seconds
201
+ @manager.register_alarm('*', "memory/*", "memory/active",
202
+ :monitor_presence => @interval
203
+ )
204
+ end
205
+
206
+ should 'raise an alarm if value is missing for more than the threshold' do
207
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
208
+
209
+ # force the timer to be called
210
+ EM::expects(:add_timer).with(@interval).yields()
211
+
212
+ @manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::AlarmMissingData) )
213
+ @manager.packet_received(p)
214
+ end
215
+
216
+ should 'not raise an alarm is value missing for less than the threshold' do
217
+ p = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
218
+
219
+ # catch the timer creation but do not execute its callback
220
+ EM::expects(:add_timer).with(@interval)
221
+
222
+ @manager.expects(:raise_alarm).never
223
+ @manager.packet_received(p)
224
+ end
225
+
226
+ should 'stop the alarm when a value is received' do
227
+ p_alarm = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
228
+ p_normal = Factory(:data_point, :plugin => "memory", :type => "memory", :type_instance => "active", :values => [8])
229
+
230
+ alarm_time = Time.now - 60
231
+ @manager.stubs(:last_update_for).with(p_alarm.measure_id).returns(alarm_time)
232
+
233
+
234
+ # catch the timer creation and execute the calback to raise an alarm
235
+ timer_id = stub()
236
+ EM::expects(:add_timer).with(@interval).yields.returns(timer_id).once
237
+ @manager.expects(:raise_alarm).with(p_alarm.measure_id, kind_of(RRDNotifier::AlarmMissingData) )
238
+ @manager.packet_received(p_alarm)
239
+
240
+
241
+ EM::expects(:cancel_timer).with(timer_id)
242
+ EM::expects(:add_timer).with(@interval)
243
+ @manager.expects(:active_alarms_for).with(p_alarm.measure_id).returns( [RRDNotifier::AlarmMissingData.new(p_alarm, @interval, alarm_time)] )
244
+ @manager.expects(:stop_specific_alarm).with( p_normal.measure_id, kind_of(RRDNotifier::AlarmMissingData) )
245
+ @manager.expects(:raise_alarm).never
246
+
247
+ @manager.packet_received(p_normal)
248
+ end
249
+
250
+ end
251
+
252
+ end
@@ -0,0 +1,26 @@
1
+ require File.expand_path('../../common', __FILE__)
2
+ require File.expand_path('../../../lib/rrd-grapher/notifier/alarm_trigger', __FILE__)
3
+
4
+ describe 'AlarmTrigger' do
5
+ it 'can can parse initialize parameters' do
6
+ RRDNotifier::AlarmTrigger.load_param("*").should == nil
7
+ RRDNotifier::AlarmTrigger.load_param("memory").should == "memory"
8
+ RRDNotifier::AlarmTrigger.load_param("memory/*").should == ["memory", nil]
9
+ RRDNotifier::AlarmTrigger.load_param("*/*").should == [nil, nil]
10
+ RRDNotifier::AlarmTrigger.load_param("*/memory").should == [nil, "memory"]
11
+ end
12
+
13
+ it 'can handle packets with multiple counters' do
14
+ manager = stub('manager', :active_alarm? => nil)
15
+ trigger = RRDNotifier::AlarmTrigger.new(manager, "*", "*/*", "*/*", :max => 10, :index => 1)
16
+
17
+ # we are not testing matching code, bypass
18
+ trigger.expects(:match?).returns(true)
19
+ p = Factory(:data_point, :values => [1, 45, 5])
20
+
21
+ manager.expects(:raise_alarm).with(p.measure_id, kind_of(RRDNotifier::Alarm))
22
+ trigger.check_alarms(p)
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,55 @@
1
+ require File.expand_path('../../common', __FILE__)
2
+ require File.expand_path('../../../lib/rrd-grapher/notifier/data_struct', __FILE__)
3
+
4
+ describe 'DataStruct' do
5
+ before do
6
+ @s1 = Class.new(DataStruct) do
7
+ properties :one, :two
8
+ end
9
+
10
+ @s2 = Class.new(DataStruct) do
11
+ properties :name, :host
12
+ end
13
+ end
14
+
15
+ should 'have disctinct attributes set for each child class' do
16
+ @s1.attributes.should == [:one, :two]
17
+ @s2.attributes.should == [:name, :host]
18
+ end
19
+
20
+ it "can merge data from multiple Hash sources" do
21
+ obj = @s1.new(:one => 12)
22
+ obj.merge_data_from(:two => 34, :one => nil)
23
+
24
+ obj.one.should == 12
25
+ obj.two.should == 34
26
+ end
27
+
28
+ it "can merge data from multiple Object sources" do
29
+ dummy_class = Struct.new(:one, :two)
30
+
31
+ d1 = dummy_class.new(23)
32
+ d2 = dummy_class.new(nil, 56)
33
+
34
+ obj = @s1.new(d1)
35
+ obj.merge_data_from(d2)
36
+
37
+ obj.one.should == 23
38
+ obj.two.should == 56
39
+ end
40
+
41
+ it "can merge data selectively from multiple Object sources" do
42
+ dummy_class = Struct.new(:one, :two)
43
+
44
+ d1 = dummy_class.new(23)
45
+ d2 = dummy_class.new(67, 56)
46
+
47
+ obj = @s1.new(d1)
48
+ obj.merge_data_from(d2, [:two])
49
+
50
+ obj.one.should == 23
51
+ obj.two.should == 56
52
+ end
53
+
54
+ end
55
+
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../../common', __FILE__)
2
+ require File.expand_path('../../../lib/rrd-grapher/notifier', __FILE__)
3
+
4
+ # require 'eventmachine'
5
+
6
+ describe 'Notifier::Server' do
7
+ should 'bind an udp socket on start' do
8
+ EM::expects(:open_datagram_socket).with('local', 7777, RRDNotifier::Server, kind_of(RRDNotifier::AlarmManager), nil, nil)
9
+ RRDNotifier::Server.start(:host => 'local', :port => 7777)
10
+ end
11
+
12
+ should 'raise an error on unknown constructor option' do
13
+ err = proc{
14
+ RRDNotifier::Server.start(:i_am_invalid => "yes really !")
15
+ }.should.raise()
16
+ err.message.should.include?("Unknown arguments")
17
+ end
18
+
19
+ describe 'an existing notifier' do
20
+ before do
21
+ @alarm_manager = stub('alarm_manager')
22
+
23
+ EM::stubs(:open_datagram_socket)
24
+ @notifier = RRDNotifier::Server.new(nil, @alarm_manager)
25
+ end
26
+
27
+ should "delegate register_alarm to the alarm manager" do
28
+ @alarm_manager.expects(:register_alarm).with(12, "a useless message")
29
+ @notifier.register_alarm(12, "a useless message")
30
+ end
31
+
32
+ should 'dispatch parsed packets when data is received' do
33
+ data = ""
34
+ packets = [ Factory(:data_point), Factory(:data_point), Factory(:notification) ]
35
+
36
+ @alarm_manager.expects(:packet_received).with(packets[0])
37
+ @alarm_manager.expects(:packet_received).with(packets[1])
38
+ @alarm_manager.expects(:packet_received).with(packets[2])
39
+
40
+ RRDNotifier::RubyParser::expects(:parse).with(data).returns(packets)
41
+ @notifier.receive_data(data)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,184 @@
1
+ require File.expand_path('../../../common', __FILE__)
2
+ require File.expand_path('../../../../lib/rrd-grapher/notifier/parsers/bindata_parser', __FILE__)
3
+
4
+ # as helper to build packets
5
+ require File.expand_path('../../../helpers/collectdrb', __FILE__)
6
+
7
+ describe 'Collectd Bindata parser' do
8
+ describe 'Simple packets' do
9
+ before do
10
+ @parser = RRDNotifier::BindataParser::Part.new
11
+ end
12
+
13
+ it 'can parse numbers' do
14
+ data = @parser.read( Collectd::number(1, 122) )
15
+ data.get_value.should == 122
16
+
17
+ data = @parser.read( Collectd::number(1, -2500) )
18
+ data.get_value.should == -2500
19
+
20
+ data = @parser.read( Collectd::number(1, 356798) )
21
+ data.get_value.should == 356798
22
+ end
23
+
24
+ should 'parse strings' do
25
+ data = @parser.read( Collectd::string(0, "hostname1") )
26
+ data.get_value.should == 'hostname1'
27
+
28
+ data = @parser.read( Collectd::string(0, "string with spaces") )
29
+ data.get_value.should == 'string with spaces'
30
+
31
+ data = @parser.read( Collectd::string(0, "a really long string with many words in it") )
32
+ data.get_value.should == 'a really long string with many words in it'
33
+ end
34
+ end
35
+
36
+ describe 'One notification in buffer' do
37
+ before do
38
+ @now = Time.new.to_i
39
+
40
+ @pkt = ""
41
+ @pkt << Collectd.number(1, @now)
42
+ @pkt << Collectd.string(0, 'hostname')
43
+
44
+ @pkt << Collectd.string(2, 'plugin')
45
+ @pkt << Collectd.string(3, 'plugin_inst')
46
+ @pkt << Collectd.string(4, 'type')
47
+ @pkt << Collectd.string(5, 'type_inst')
48
+ @pkt << Collectd.number(257, 2) # severity
49
+ @pkt << Collectd.string(256, 'a message')
50
+ end
51
+
52
+ should 'parse the notification' do
53
+ data = RRDNotifier::BindataParser.parse(@pkt)
54
+
55
+ data.size.should == 1
56
+
57
+ data[0].class.should == RRDNotifier::Packet
58
+ data[0].host.should == 'hostname'
59
+ data[0].time.should == @now
60
+ data[0].plugin.should == 'plugin'
61
+ data[0].plugin_instance.should == 'plugin_inst'
62
+ data[0].type.should == 'type'
63
+ data[0].type_instance.should == 'type_inst'
64
+ data[0].message.should == 'a message'
65
+ data[0].severity.should == 2
66
+
67
+ end
68
+ end
69
+
70
+ describe 'One packet in buffer' do
71
+ before do
72
+ @now = Time.new.to_i
73
+ @interval = 10
74
+ @pkt = ""
75
+ @pkt << Collectd.number(1, @now)
76
+ @pkt << Collectd.string(0, 'hostname')
77
+ @pkt << Collectd.number(7, @interval)
78
+
79
+ @pkt << Collectd.string(2, 'plugin')
80
+ @pkt << Collectd.string(3, 'plugin_inst')
81
+ @pkt << Collectd.string(4, 'type')
82
+ @pkt << Collectd.string(5, 'type_inst')
83
+
84
+ @pkt << Collectd.values([[:counter, 1034], [:gauge, 3.45]])
85
+ end
86
+
87
+ should 'parse it' do
88
+ data = nil
89
+ # BinData::trace_reading do
90
+ data = RRDNotifier::BindataParser.parse(@pkt)
91
+ # end
92
+
93
+ data.size.should == 1
94
+
95
+ data[0].class.should == RRDNotifier::Packet
96
+ data[0].host.should == 'hostname'
97
+ data[0].time.should == @now
98
+ data[0].interval.should == @interval
99
+ data[0].plugin.should == 'plugin'
100
+ data[0].plugin_instance.should == 'plugin_inst'
101
+ data[0].type.should == 'type'
102
+ data[0].type_instance.should == 'type_inst'
103
+
104
+ data[0].values.size.should == 2
105
+ data[0].values[0].should == 1034
106
+ data[0].values[1].should == 3.45
107
+ end
108
+ end
109
+
110
+ describe "Multiple packets in buffer" do
111
+ before do
112
+ @now = Time.new.to_i
113
+ @interval = 10
114
+
115
+ @pkt = Collectd.string(0, 'hostname')
116
+ @pkt << Collectd.number(1, @now)
117
+ @pkt << Collectd.number(7, @interval)
118
+
119
+ @pkt << Collectd.string(2, 'plugin')
120
+ @pkt << Collectd.string(3, 'plugin_inst')
121
+ @pkt << Collectd.string(4, 'type')
122
+ @pkt << Collectd.string(5, 'type_inst')
123
+
124
+ @pkt << Collectd.values([[:counter, 1034], [:gauge, 3.45]])
125
+
126
+ @pkt << Collectd.string(2, 'plugin2')
127
+ @pkt << Collectd.string(3, 'plugin2_inst')
128
+ @pkt << Collectd.string(4, 'type2')
129
+ @pkt << Collectd.string(5, 'type2_inst')
130
+
131
+ @pkt << Collectd.values([[:counter, 42]])
132
+
133
+
134
+ @pkt << Collectd.string(5, 'type21_inst')
135
+ @pkt << Collectd.values([[:gauge, 3.1415927]])
136
+ end
137
+
138
+ should 'parse it' do
139
+ data = nil
140
+ # BinData::trace_reading do
141
+ data = RRDNotifier::BindataParser.parse(@pkt)
142
+ # end
143
+
144
+ data.size.should == 3
145
+
146
+ data[0].class.should == RRDNotifier::Packet
147
+
148
+ # data.packets.size.should == 8
149
+
150
+ data[0].host.should == 'hostname'
151
+ data[0].time.should == @now
152
+ data[0].interval.should == @interval
153
+ data[0].plugin.should == 'plugin'
154
+ data[0].plugin_instance.should == 'plugin_inst'
155
+ data[0].type.should == 'type'
156
+ data[0].type_instance.should == 'type_inst'
157
+ data[0].values.size.should == 2
158
+ data[0].values[0].should == 1034
159
+ data[0].values[1].should == 3.45
160
+
161
+ data[1].host.should == 'hostname'
162
+ data[1].time.should == @now
163
+ data[1].interval.should == @interval
164
+ data[1].plugin.should == 'plugin2'
165
+ data[1].plugin_instance.should == 'plugin2_inst'
166
+ data[1].type.should == 'type2'
167
+ data[1].type_instance.should == 'type2_inst'
168
+ data[1].values.size.should == 1
169
+ data[1].values[0].should == 42
170
+
171
+ data[2].host.should == 'hostname'
172
+ data[2].time.should == @now
173
+ data[2].interval.should == @interval
174
+ data[2].plugin.should == 'plugin2'
175
+ data[2].plugin_instance.should == 'plugin2_inst'
176
+ data[2].type.should == 'type2'
177
+ data[2].type_instance.should == 'type21_inst'
178
+ data[2].values.size.should == 1
179
+ data[2].values[0].should == 3.1415927
180
+
181
+ end
182
+ end
183
+
184
+ end