gmetric 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ = GMetric
2
+
3
+ A pure Ruby client for generating Ganglia 3.1.x+ gmetric meta and metric packets and talking to your gmond / gmetad nodes over UDP protocol. Supports host spoofing, and all the same parameters as the gmetric command line executable.
4
+
5
+ == Example: Sending a gmetric to a gmond over UDP
6
+
7
+ Ganglia::GMetric.send("127.0.0.1", 8670, {
8
+ :name => 'pageviews',
9
+ :units => 'req/min',
10
+ :type => 'uint8',
11
+ :value => 7000,
12
+ :tmax => 60,
13
+ :dmax => 300
14
+ })
15
+
16
+ == Example: Generating the Meta and Metric packets
17
+
18
+ g = Ganglia::GMetric.pack(
19
+ :slope => 'positive',
20
+ :name => 'ruby',
21
+ :value => rand(100),
22
+ :tmax => 60,
23
+ :units => '',
24
+ :dmax => 60,
25
+ :type => 'uint8'
26
+ )
27
+
28
+ # g[0] = meta packet
29
+ # g[1] = gmetric packet
30
+
31
+ s = UDPSocket.new
32
+ s.connect("127.0.0.1", 8670)
33
+ s.send g[0], 0
34
+ s.send g[1], 0
35
+
36
+ == License
37
+
38
+ (The MIT License)
39
+
40
+ Copyright (c) 2009 Ilya Grigorik
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining
43
+ a copy of this software and associated documentation files (the
44
+ 'Software'), to deal in the Software without restriction, including
45
+ without limitation the rights to use, copy, modify, merge, publish,
46
+ distribute, sublicense, and/or sell copies of the Software, and to
47
+ permit persons to whom the Software is furnished to do so, subject to
48
+ the following conditions:
49
+
50
+ The above copyright notice and this permission notice shall be
51
+ included in all copies or substantial portions of the Software.
52
+
53
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
54
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
56
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
57
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
58
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
59
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gemspec|
7
+ gemspec.name = "gmetric"
8
+ gemspec.summary = "Pure Ruby interface for generating Ganglia gmetric packets"
9
+ gemspec.description = gemspec.summary
10
+ gemspec.email = "ilya@igvita.com"
11
+ gemspec.homepage = "http://github.com/igrigorik/gmetric"
12
+ gemspec.authors = ["Ilya Grigorik"]
13
+ gemspec.rubyforge_project = "gmetric"
14
+ end
15
+
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
19
+ end
20
+
21
+ task :default => :spec
22
+
23
+ Spec::Rake::SpecTask.new do |t|
24
+ t.ruby_opts = ['-rtest/unit']
25
+ t.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,91 @@
1
+ require "stringio"
2
+ require "socket"
3
+
4
+ module Ganglia
5
+ class GMetric
6
+
7
+ SLOPE = {
8
+ 'zero' => 0,
9
+ 'positive' => 1,
10
+ 'negative' => 2,
11
+ 'both' => 3,
12
+ 'unspecified' => 4
13
+ }
14
+
15
+ def self.send(host, port, metric)
16
+ conn = UDPSocket.new
17
+ conn.connect(host, port)
18
+ gmetric = self.pack(metric)
19
+
20
+ conn.send gmetric[0], 0
21
+ conn.send gmetric[1], 0
22
+ end
23
+
24
+ def self.pack(metric)
25
+ metric = {
26
+ :hostname => '',
27
+ :spoof => 0,
28
+ :units => '',
29
+ :slope => 'both',
30
+ :tmax => 60,
31
+ :dmax => 0
32
+ }.merge(metric)
33
+
34
+ raise "Missing key, value, type" if not metric.key? :name or not metric.key? :value or not metric.key? :type
35
+ raise "Invalid metric type" if not %w(string int8 uint8 int16 uint16 int32 uint32 float double).include? metric[:type]
36
+
37
+ meta = XDRPacket.new
38
+ data = XDRPacket.new
39
+
40
+ # METADATA payload
41
+ meta.pack_int(128) # gmetadata_full
42
+ meta.pack_string(metric[:hostname]) # hostname
43
+ meta.pack_string(metric[:name].to_s) # name of the metric
44
+ meta.pack_int(metric[:spoof].to_i) # spoof hostname flag
45
+
46
+ meta.pack_string(metric[:type].to_s) # one of: string, int8, uint8, int16, uint16, int32, uint32, float, double
47
+ meta.pack_string(metric[:name].to_s) # name of the metric
48
+ meta.pack_string(metric[:units].to_s) # units for the value, e.g. 'kb/sec'
49
+ meta.pack_int(SLOPE[metric[:slope]]) # sign of the derivative of the value over time, one of zero, positive, negative, both, default both
50
+ meta.pack_uint(metric[:tmax].to_i) # maximum time in seconds between gmetric calls, default 60
51
+ meta.pack_uint(metric[:dmax].to_i) # lifetime in seconds of this metric, default=0, meaning unlimited
52
+ meta.pack_int(0)
53
+
54
+ # DATA payload
55
+ data.pack_int(128+5) # string message
56
+ data.pack_string(metric[:hostname].to_s) # hostname
57
+ data.pack_string(metric[:name].to_s) # name of the metric
58
+ data.pack_int(metric[:spoof].to_i) # spoof hostname flag
59
+ data.pack_string("%s") #
60
+ data.pack_string(metric[:value].to_s) # value of the metric
61
+
62
+ [meta.data, data.data]
63
+ end
64
+ end
65
+
66
+ class XDRPacket
67
+ def initialize
68
+ @data = StringIO.new
69
+ end
70
+
71
+ def pack_uint(data)
72
+ # big endian unsigned long
73
+ @data << [data].pack("N")
74
+ end
75
+ alias :pack_int :pack_uint
76
+
77
+ def pack_string(data)
78
+ len = data.size
79
+ pack_uint(len)
80
+
81
+ # pad the string
82
+ len = ((len+3) / 4) * 4
83
+ data = data + ("\0" * (len - data.size))
84
+ @data << data
85
+ end
86
+
87
+ def data
88
+ @data.string
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,67 @@
1
+ require "helper"
2
+
3
+ describe Ganglia::GMetric do
4
+
5
+ describe Ganglia::XDRPacket do
6
+ def hex(data)
7
+ [data].pack("H")
8
+ end
9
+
10
+ it "should pack an int & uint into XDR format" do
11
+ xdr = Ganglia::XDRPacket.new
12
+ xdr.pack_int(1)
13
+ xdr.data.should == "\000\000\000\001"
14
+
15
+ xdr = Ganglia::XDRPacket.new
16
+ xdr.pack_uint(8)
17
+ xdr.data.should == "\000\000\000\b"
18
+ end
19
+
20
+ it "should pack string" do
21
+ xdr = Ganglia::XDRPacket.new
22
+ xdr.pack_string("test")
23
+ xdr.data.should == "\000\000\000\004test"
24
+ end
25
+ end
26
+
27
+ it "should pack GMetric into XDR format from Ruby hash" do
28
+ data = {
29
+ :slope => 'both',
30
+ :name => 'foo',
31
+ :value => 'bar',
32
+ :tmax => 60,
33
+ :units => '',
34
+ :dmax => 0,
35
+ :type => 'string'
36
+ }
37
+
38
+ g = Ganglia::GMetric.pack(data)
39
+ g.size.should == 2
40
+ g[0].should == "\000\000\000\200\000\000\000\000\000\000\000\003foo\000\000\000\000\000\000\000\000\006string\000\000\000\000\000\003foo\000\000\000\000\000\000\000\000\003\000\000\000<\000\000\000\000\000\000\000\000"
41
+ g[1].should == "\000\000\000\205\000\000\000\000\000\000\000\003foo\000\000\000\000\000\000\000\000\002%s\000\000\000\000\000\003bar\000"
42
+ end
43
+
44
+ it "should raise an error on missing name, value, type" do
45
+ %w(name value type).each do |key|
46
+ lambda {
47
+ data = {:name => 'a', :type => 'b', :value => 'c'}
48
+ data.delete key.to_sym
49
+ Ganglia::GMetric.pack(data)
50
+ }.should raise_error
51
+ end
52
+ end
53
+
54
+ it "should verify type and raise error on invalid type" do
55
+ %w(string int8 uint8 int16 uint16 int32 uint32 float double).each do |type|
56
+ lambda {
57
+ data = {:name => 'a', :type => type, :value => 'c'}
58
+ Ganglia::GMetric.pack(data)
59
+ }.should_not raise_error
60
+ end
61
+
62
+ lambda {
63
+ data = {:name => 'a', :type => 'int', :value => 'c'}
64
+ Ganglia::GMetric.pack(data)
65
+ }.should raise_error
66
+ end
67
+ end
@@ -0,0 +1,2 @@
1
+ require "lib/gmetric"
2
+ require "spec"
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gmetric
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ilya Grigorik
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-28 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Pure Ruby interface for generating Ganglia gmetric packets
17
+ email: ilya@igvita.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - VERSION
28
+ - lib/gmetric.rb
29
+ - spec/gmetric_spec.rb
30
+ - spec/helper.rb
31
+ has_rdoc: true
32
+ homepage: http://github.com/igrigorik/gmetric
33
+ licenses: []
34
+
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --charset=UTF-8
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project: gmetric
55
+ rubygems_version: 1.3.5
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Pure Ruby interface for generating Ganglia gmetric packets
59
+ test_files:
60
+ - spec/gmetric_spec.rb
61
+ - spec/helper.rb