pulse-meter 0.4.2 → 0.4.3

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.
data/lib/cmd.rb CHANGED
@@ -157,5 +157,15 @@ module Cmd
157
157
  end
158
158
  end
159
159
 
160
+ desc "udp_proxy HOST PORT", "Start UDP proxy for sensor data"
161
+ common_options
162
+ def udp_proxy(host, port)
163
+ with_redis do
164
+ puts 'Starting UDP server'
165
+ server = PulseMeter::UDPServer.new(host, port)
166
+ server.start
167
+ end
168
+ end
169
+
160
170
  end
161
171
  end
data/lib/pulse-meter.rb CHANGED
@@ -10,6 +10,9 @@ require "pulse-meter/sensor/configuration"
10
10
 
11
11
  require "pulse-meter/command_aggregator/async"
12
12
  require "pulse-meter/command_aggregator/sync"
13
+ require "pulse-meter/command_aggregator/udp"
14
+
15
+ require "pulse-meter/udp_server"
13
16
 
14
17
  module PulseMeter
15
18
  @@redis = nil
@@ -37,7 +40,7 @@ module PulseMeter
37
40
  @@command_aggregator = case command_aggregator
38
41
  when :sync; PulseMeter::CommandAggregator::Sync.instance
39
42
  when :async; PulseMeter::CommandAggregator::Async.instance
40
- else raise ArgumentError
43
+ else command_aggregator
41
44
  end
42
45
  end
43
46
 
@@ -0,0 +1,42 @@
1
+ require 'socket'
2
+
3
+ module PulseMeter
4
+ module CommandAggregator
5
+ class UDP
6
+
7
+ def initialize(host, port)
8
+ @host, @port = host, port
9
+ @buffer = []
10
+ @in_multi = false
11
+ end
12
+
13
+ def multi
14
+ @in_multi = true
15
+ yield
16
+ ensure
17
+ @in_multi = false
18
+ send_buffer
19
+ end
20
+
21
+ def method_missing(*args)
22
+ @buffer << args
23
+ send_buffer unless @in_multi
24
+ end
25
+
26
+ private
27
+
28
+ def send_buffer
29
+ data = @buffer.to_json
30
+ sock = UDPSocket.new
31
+ sock.send(data, 0, @host, @port)
32
+ sock.close
33
+ rescue StandardError
34
+ PulseMeter.error "error sending data: #{e}, #{e.backtrace.join("\n")}"
35
+ ensure
36
+ @buffer = []
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,43 @@
1
+ require 'socket'
2
+ require 'timeout'
3
+
4
+ module PulseMeter
5
+ class UDPServer
6
+ MAX_PACKET = 1024
7
+
8
+ def initialize(host, port)
9
+ @socket = UDPSocket.new
10
+ @socket.do_not_reverse_lookup = true
11
+ @socket.bind(host, port)
12
+ end
13
+
14
+ def start(max_packets = nil)
15
+ while true do
16
+ if max_packets
17
+ break if max_packets <= 0
18
+ max_packets -= 1
19
+ end
20
+ process_packet
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def process_packet
27
+ raw_data, _ = @socket.recvfrom(MAX_PACKET)
28
+ data = parse_data(raw_data)
29
+ data.each do |command|
30
+ PulseMeter.redis.send(*command)
31
+ end
32
+ rescue StandardError => e
33
+ PulseMeter.error "Error processing packet: #{e}"
34
+ end
35
+
36
+ def parse_data(data)
37
+ JSON.parse(data)
38
+ rescue
39
+ PulseMeter.error "Bad redis data: #{data.inspect}"
40
+ []
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,3 @@
1
1
  module PulseMeter
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe PulseMeter::CommandAggregator::UDP do
4
+ let(:host){'127.0.0.1'}
5
+ let(:port){33333}
6
+ let(:udp_sock){mock(:socket)}
7
+ before do
8
+ UDPSocket.stub!(:new).and_return(udp_sock)
9
+ udp_sock.stub!(:close).and_return(nil)
10
+ @ca = described_class.new(host, port)
11
+ end
12
+
13
+ describe "#multi" do
14
+ it "should accumulate redis commands and send them in a bulk" do
15
+ data = [
16
+ ["set", "xxxx", "zzzz"],
17
+ ["set", "yyyy", "zzzz"]
18
+ ].to_json
19
+ udp_sock.should_receive(:send).with(data, 0, host, port).and_return(0)
20
+ @ca.multi do
21
+ @ca.set("xxxx", "zzzz")
22
+ @ca.set("yyyy", "zzzz")
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "any other redis instance method" do
28
+ it "should send data imediately" do
29
+ data = [
30
+ ["set", "xxxx", "zzzz"]
31
+ ].to_json
32
+ udp_sock.should_receive(:send).with(data, 0, host, port).and_return(0)
33
+ @ca.set("xxxx", "zzzz")
34
+ end
35
+ end
36
+
37
+ end
38
+
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe PulseMeter::UDPServer do
4
+ let(:host){'127.0.0.1'}
5
+ let(:port){33333}
6
+ let(:udp_sock){mock(:socket)}
7
+ let(:redis){PulseMeter.redis}
8
+ before do
9
+ UDPSocket.should_receive(:new).and_return(udp_sock)
10
+ udp_sock.should_receive(:bind).with(host, port).and_return(nil)
11
+ udp_sock.should_receive("do_not_reverse_lookup=").with(true).and_return(nil)
12
+ @server = described_class.new(host, port)
13
+ end
14
+
15
+ describe "#start" do
16
+ let(:data){
17
+ [
18
+ ["set", "xxxx", "zzzz"],
19
+ ["set", "yyyy", "zzzz"]
20
+ ].to_json
21
+ }
22
+ it "should process proper incoming commands" do
23
+ udp_sock.should_receive(:recvfrom).with(described_class::MAX_PACKET).and_return(data)
24
+ @server.start(1)
25
+ redis.get("xxxx").should == "zzzz"
26
+ redis.get("yyyy").should == "zzzz"
27
+ end
28
+
29
+ it "should suppress JSON errors" do
30
+ udp_sock.should_receive(:recvfrom).with(described_class::MAX_PACKET).and_return("xxx")
31
+ expect{ @server.start(1) }.not_to raise_exception
32
+ end
33
+ end
34
+
35
+ end
36
+
@@ -27,8 +27,9 @@ describe PulseMeter do
27
27
  end
28
28
  end
29
29
  context "otherwise" do
30
- it "should raise ArgumentError" do
31
- expect{ PulseMeter.command_aggregator = :xxx }.to raise_exception(ArgumentError)
30
+ it "should set command_aggregator to the passed value" do
31
+ PulseMeter.command_aggregator = :xxx
32
+ PulseMeter.command_aggregator.should == :xxx
32
33
  end
33
34
  end
34
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pulse-meter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-02-02 00:00:00.000000000 Z
13
+ date: 2013-02-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gon-sinatra
@@ -415,6 +415,7 @@ files:
415
415
  - lib/pulse-meter.rb
416
416
  - lib/pulse-meter/command_aggregator/async.rb
417
417
  - lib/pulse-meter/command_aggregator/sync.rb
418
+ - lib/pulse-meter/command_aggregator/udp.rb
418
419
  - lib/pulse-meter/extensions/enumerable.rb
419
420
  - lib/pulse-meter/mixins/cmd.rb
420
421
  - lib/pulse-meter/mixins/dumper.rb
@@ -447,6 +448,7 @@ files:
447
448
  - lib/pulse-meter/server/command_line_options.rb
448
449
  - lib/pulse-meter/server/config_options.rb
449
450
  - lib/pulse-meter/server/sensors.rb
451
+ - lib/pulse-meter/udp_server.rb
450
452
  - lib/pulse-meter/version.rb
451
453
  - lib/pulse-meter/visualize/app.rb
452
454
  - lib/pulse-meter/visualize/base.rb
@@ -537,6 +539,7 @@ files:
537
539
  - pulse-meter.gemspec
538
540
  - spec/pulse_meter/command_aggregator/async_spec.rb
539
541
  - spec/pulse_meter/command_aggregator/sync_spec.rb
542
+ - spec/pulse_meter/command_aggregator/udp_spec.rb
540
543
  - spec/pulse_meter/extensions/enumerable_spec.rb
541
544
  - spec/pulse_meter/mixins/cmd_spec.rb
542
545
  - spec/pulse_meter/mixins/dumper_spec.rb
@@ -562,6 +565,7 @@ files:
562
565
  - spec/pulse_meter/sensor/timelined/percentile_spec.rb
563
566
  - spec/pulse_meter/sensor/timelined/uniq_counter_spec.rb
564
567
  - spec/pulse_meter/sensor/uniq_counter_spec.rb
568
+ - spec/pulse_meter/udp_server_spec.rb
565
569
  - spec/pulse_meter/visualize/app_spec.rb
566
570
  - spec/pulse_meter/visualize/dsl/layout_spec.rb
567
571
  - spec/pulse_meter/visualize/dsl/page_spec.rb
@@ -607,9 +611,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
607
611
  - - ! '>='
608
612
  - !ruby/object:Gem::Version
609
613
  version: '0'
610
- segments:
611
- - 0
612
- hash: -1795310197501122422
613
614
  requirements: []
614
615
  rubyforge_project:
615
616
  rubygems_version: 1.8.23
@@ -620,6 +621,7 @@ summary: Lightweight Redis-based metrics aggregator and processor with CLI and s
620
621
  test_files:
621
622
  - spec/pulse_meter/command_aggregator/async_spec.rb
622
623
  - spec/pulse_meter/command_aggregator/sync_spec.rb
624
+ - spec/pulse_meter/command_aggregator/udp_spec.rb
623
625
  - spec/pulse_meter/extensions/enumerable_spec.rb
624
626
  - spec/pulse_meter/mixins/cmd_spec.rb
625
627
  - spec/pulse_meter/mixins/dumper_spec.rb
@@ -645,6 +647,7 @@ test_files:
645
647
  - spec/pulse_meter/sensor/timelined/percentile_spec.rb
646
648
  - spec/pulse_meter/sensor/timelined/uniq_counter_spec.rb
647
649
  - spec/pulse_meter/sensor/uniq_counter_spec.rb
650
+ - spec/pulse_meter/udp_server_spec.rb
648
651
  - spec/pulse_meter/visualize/app_spec.rb
649
652
  - spec/pulse_meter/visualize/dsl/layout_spec.rb
650
653
  - spec/pulse_meter/visualize/dsl/page_spec.rb