statsite-instrumental 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c57c114d02cc341b0687f5e93a7b5cb111af66e6
4
+ data.tar.gz: e54dd2e8522956afc976117cbad78a4b43c17210
5
+ SHA512:
6
+ metadata.gz: bcfcade12f92470be75acb6dcc9009e129969b75538a774f1c07aef45664bf831ebc4b5a3d74ca72a7b1e7d26a2a28a0469d1cca22951634fa973fed12dd4ec5
7
+ data.tar.gz: c8e129cb190edf4f221d7de6d62ef8e71d589bade7cb9537b9276add0041458e36775bf6c077bf6d76891d80d0c46fb3949d2c7cb6b42ef59a8f0a56bdf2c2d2
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Chris Gaffney
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # statsite-instrumental
2
+
3
+ Data sink for [Statsite](https://github.com/armon/statsite) and
4
+ [Instrumental](https://instrumentalapp.com/)
5
+
6
+ ## Install
7
+
8
+ ```console
9
+ $ gem install instrumental-statsite
10
+ ```
11
+
12
+ ## Configuration
13
+
14
+ To use the sink you need to set `stream_cmd` in your config for statsite. Make
15
+ sure you're using the correct path to the executable and supply your
16
+ instrumental API key as the only argument to the script.
17
+
18
+ ```
19
+ [statsite]
20
+ stream_cmd = /usr/bin/statsite-instrumental [api key]
21
+ ```
22
+
23
+ ## Note on Patches/Pull Requests
24
+
25
+ * Fork the project.
26
+ * Add tests to show the problem or test your feature
27
+ * Make your feature addition or bug fix.
28
+ * Send me a pull request. Bonus points for topic branches.
29
+
30
+ Please don't make changes to the Rakefile, version, or history.
31
+
32
+ ## Development
33
+
34
+ ```console
35
+ $ gem install bundler
36
+ $ bundle
37
+ $ guard
38
+ ```
39
+
40
+ ## Copyright
41
+
42
+ See LICENSE for details.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ require "instrumental/statsite"
4
+
5
+ client = ::Instrumental::Statsite::Client.new(ARGV[0])
6
+
7
+ collector = ::Instrumental::Statsite::Collector.new
8
+ parser = ::Instrumental::Statsite::Parser.new(STDIN)
9
+
10
+ parser.parse(collector)
11
+ client.push(collector)
@@ -0,0 +1,8 @@
1
+ module Instrumental
2
+ module Statsite
3
+ require "instrumental/statsite/version"
4
+ require "instrumental/statsite/client"
5
+ require "instrumental/statsite/parser"
6
+ require "instrumental/statsite/collector"
7
+ end
8
+ end
@@ -0,0 +1,29 @@
1
+ require "socket"
2
+
3
+ module Instrumental
4
+ module Statsite
5
+ class Client
6
+ def initialize(token, host = "collector.instrumentalapp.com", port = 8000)
7
+ @token = token
8
+ @host = host
9
+ @port = port
10
+ end
11
+
12
+ def push(collector)
13
+ ::TCPSocket.open(@host, @port) do |socket|
14
+ socket.puts("hello version 1.0")
15
+ socket.puts("authenticate #{@token}")
16
+
17
+ if socket.readpartial(32) == "ok\nok\n"
18
+ collector.each do |line|
19
+ socket.puts(line)
20
+ end
21
+
22
+ collector.flush
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ module Instrumental
2
+ module Statsite
3
+ # The collector generates the protocol to be sent to instrumental
4
+ class Collector
5
+ def initialize
6
+ @buffer = []
7
+ end
8
+
9
+ def increment(key, value, timestamp)
10
+ @buffer << "increment #{key} #{value} #{timestamp}"
11
+ end
12
+
13
+ def gauge(key, value, timestamp)
14
+ @buffer << "gauge #{key} #{value} #{timestamp}"
15
+ end
16
+
17
+ def gauge_absolute(key, value, timestamp)
18
+ @buffer << "gauge_absolute #{key} #{value} #{timestamp}"
19
+ end
20
+
21
+ def flush
22
+ @buffer.clear
23
+ end
24
+
25
+ def each(&block)
26
+ @buffer.each(&block)
27
+ end
28
+
29
+ def to_s
30
+ @buffer.join("\n")
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,35 @@
1
+ module Instrumental
2
+ module Statsite
3
+ class Parser
4
+ FORMAT = /\A(?<type>counts|gauges|sets|timers)\.(?<data>.+)\n?\z/
5
+
6
+ attr_reader :errors
7
+
8
+ def initialize(stream)
9
+ @stream = stream
10
+ @errors = []
11
+ end
12
+
13
+ # Parse the input and pass along the proper calls to the collector
14
+ def parse(collector)
15
+ @stream.each_line do |line|
16
+ if match = FORMAT.match(line)
17
+
18
+ key, value, timestamp = match[:data].split("|")
19
+
20
+ case match[:type]
21
+ when "counts"
22
+ collector.increment(key, value, timestamp)
23
+ when "gauges"
24
+ collector.gauge(key, value, timestamp)
25
+ when "sets", "timers"
26
+ collector.gauge_absolute(key, value, timestamp)
27
+ end
28
+ else
29
+ @errors << "Unable to process: #{line}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ module Instrumental
2
+ module Statsite
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ require "spec_helper"
2
+
3
+ describe Instrumental::Statsite::Collector do
4
+ subject(:collector) do
5
+ Instrumental::Statsite::Collector.new
6
+ end
7
+
8
+ describe "basic api" do
9
+ it "can increment a value" do
10
+ collector.increment("test", "15.822", "127000001")
11
+ expect(collector.to_s).to eq("increment test 15.822 127000001")
12
+ end
13
+
14
+ it "can record a gauge" do
15
+ collector.gauge("test100", "37", "127000002")
16
+ expect(collector.to_s).to eq("gauge test100 37 127000002")
17
+ end
18
+
19
+ it "can record an absolute gauge" do
20
+ collector.gauge_absolute("absolute", "99", "127000003")
21
+ expect(collector.to_s).to eq("gauge_absolute absolute 99 127000003")
22
+ end
23
+ end
24
+
25
+ describe "buffering" do
26
+ it "buffers multiple calls together" do
27
+ collector.increment("test", "15.822", "127000001")
28
+ collector.gauge("test100", "37", "127000002")
29
+ collector.gauge_absolute("absolute", "99", "127000003")
30
+
31
+ data = collector.to_s.split("\n")
32
+ expect(data.size).to be(3)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ require "stringio"
2
+ require "spec_helper"
3
+
4
+ describe Instrumental::Statsite::Parser do
5
+ it "parses counts as increments" do
6
+ collector = mock
7
+ collector.should_receive(:increment).with("harmony.spam", "8", "410083200")
8
+
9
+ data = StringIO.new("counts.harmony.spam|8|410083200\n")
10
+ parser = Instrumental::Statsite::Parser.new(data)
11
+ parser.parse(collector)
12
+ end
13
+
14
+ it "parses gauges as a gauge" do
15
+ collector = mock
16
+ collector.should_receive(:gauge).with("harmony.ham", "47.1111", "410083200")
17
+
18
+ data = StringIO.new("gauges.harmony.ham|47.1111|410083200\n")
19
+ parser = Instrumental::Statsite::Parser.new(data)
20
+ parser.parse(collector)
21
+ end
22
+
23
+ it "parses sets as absolute gauges" do
24
+ collector = mock
25
+ collector.should_receive(:gauge_absolute).with(
26
+ "harmony.render.time", "7222", "410083200"
27
+ )
28
+
29
+ data = StringIO.new("sets.harmony.render.time|7222|410083200\n")
30
+ parser = Instrumental::Statsite::Parser.new(data)
31
+ parser.parse(collector)
32
+ end
33
+
34
+ it "parses timers as absolute gauges" do
35
+ collector = mock
36
+ collector.should_receive(:gauge_absolute).with(
37
+ "harmony.render.time", "7222", "410083200"
38
+ )
39
+
40
+ data = StringIO.new("timers.harmony.render.time|7222|410083200\n")
41
+ parser = Instrumental::Statsite::Parser.new(data)
42
+ parser.parse(collector)
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ require "instrumental/statsite"
4
+
5
+ RSpec.configure do |config|
6
+ # Run specs in random order to surface order dependencies.
7
+ config.order = "random"
8
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: statsite-instrumental
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Expected Behavior
8
+ - Chris Gaffney
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '2.11'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.11'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rb-fsevent
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: guard
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: guard-rspec
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: guard-bundler
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ description:
99
+ email:
100
+ - support@instrumentalapp.com
101
+ executables:
102
+ - statsite-instrumental
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - LICENSE
107
+ - README.md
108
+ - bin/statsite-instrumental
109
+ - lib/instrumental/statsite.rb
110
+ - lib/instrumental/statsite/client.rb
111
+ - lib/instrumental/statsite/collector.rb
112
+ - lib/instrumental/statsite/parser.rb
113
+ - lib/instrumental/statsite/version.rb
114
+ - spec/collector_spec.rb
115
+ - spec/parser_spec.rb
116
+ - spec/spec_helper.rb
117
+ homepage: https://github.com/expectedbehavior/statsite-instrumental-ruby
118
+ licenses: []
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.5.1
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Statsite sink for instrumentalapp.com
140
+ test_files: []