statsd 0.0.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +80 -61
- data/bin/statsd +56 -0
- data/config.yml +6 -3
- data/lib/statsd/echos.rb +2 -2
- data/lib/statsd/graphite.rb +1 -1
- data/lib/statsd/mongo.rb +0 -3
- data/lib/statsd/server.rb +68 -2
- data/lib/statsd/test.rb +3 -0
- data/{em-server.rb → stats.rb} +0 -0
- data/statsd.gemspec +4 -3
- metadata +19 -29
- data/LICENSE +0 -22
- data/config.js +0 -39
- data/exampleConfig.js +0 -8
- data/php-example.php +0 -96
- data/python_example.py +0 -89
- data/stats.js +0 -128
- data/webapp/Gemfile +0 -5
- data/webapp/Gemfile.lock +0 -21
- data/webapp/README.md +0 -2
- data/webapp/app.rb +0 -12
- data/webapp/bin/rackup +0 -16
- data/webapp/bin/statsd-web +0 -15
- data/webapp/config.yml +0 -3
- data/webapp/public/jquery-1.4.4.js +0 -7179
- data/webapp/public/jquery.flot.js +0 -2119
- data/webapp/public/jquery.flot.selection.js +0 -299
- data/webapp/vendor/cache/SystemTimer-1.2.2.gem +0 -0
- data/webapp/vendor/cache/rack-1.2.1.gem +0 -0
- data/webapp/vendor/cache/redis-2.1.1.gem +0 -0
- data/webapp/vendor/cache/sinatra-1.1.3.gem +0 -0
- data/webapp/vendor/cache/tilt-1.2.2.gem +0 -0
- data/webapp/vendor/cache/vegas-0.1.8.gem +0 -0
- data/webapp/views/chart.erb +0 -94
data/README.md
CHANGED
@@ -1,10 +1,80 @@
|
|
1
1
|
StatsD
|
2
2
|
======
|
3
3
|
|
4
|
-
A network daemon for aggregating statistics (counters and timers), rolling them up, then sending them to [graphite][graphite].
|
4
|
+
A network daemon for aggregating statistics (counters and timers), rolling them up, then sending them to [graphite][graphite] or [mongodb][mongodb].
|
5
5
|
|
6
|
-
We ([Etsy][etsy]) [blogged][blog post] about how it works and why we created it.
|
7
6
|
|
7
|
+
### Installation
|
8
|
+
|
9
|
+
gem install statsd
|
10
|
+
|
11
|
+
### Configuration
|
12
|
+
|
13
|
+
Create config.yml to your liking. There are 2 flush protocols: graphite and mongo. The former simple sends to carbon every flush interval. The latter flushes to MongoDB capped collections for 10s and 1min intervals.
|
14
|
+
|
15
|
+
Example config.yml
|
16
|
+
---
|
17
|
+
bind: 127.0.0.1
|
18
|
+
port: 8125
|
19
|
+
|
20
|
+
# Flush interval should be your finest retention in seconds
|
21
|
+
flush_interval: 10
|
22
|
+
|
23
|
+
# Graphite
|
24
|
+
graphite_host: localhost
|
25
|
+
graphite_port: 2003
|
26
|
+
|
27
|
+
# Mongo
|
28
|
+
mongo_host: localhost
|
29
|
+
mongo_database: statsdb
|
30
|
+
|
31
|
+
# If you change these, you need to delete the capped collections yourself!
|
32
|
+
# Average mongo record size is 152 bytes
|
33
|
+
# 10s or 1min data is transient so we'll use MongoDB's capped collections. These collections are fixed in size.
|
34
|
+
# 5min and 1d data is interesting to preserve long-term. These collections are not capped.
|
35
|
+
retentions:
|
36
|
+
- name: stats_per_10s
|
37
|
+
seconds: 10
|
38
|
+
capped: true
|
39
|
+
cap_bytes: 268_435_456 # 2**28
|
40
|
+
- name: stats_per_1min
|
41
|
+
seconds: 60
|
42
|
+
capped: true
|
43
|
+
cap_bytes: 1_073_741_824 # 2**30
|
44
|
+
- name: stats_per_5min
|
45
|
+
seconds: 600
|
46
|
+
cap_bytes: 0
|
47
|
+
capped: false
|
48
|
+
- name: stats_per_day
|
49
|
+
seconds: 86400
|
50
|
+
cap_bytes: 0
|
51
|
+
capped: false
|
52
|
+
|
53
|
+
|
54
|
+
### Server
|
55
|
+
Run the server:
|
56
|
+
|
57
|
+
Flush to Graphite (default):
|
58
|
+
statsd -c config.yml
|
59
|
+
|
60
|
+
Flush and aggregate to MongoDB:
|
61
|
+
statsd -c config.yml -m
|
62
|
+
|
63
|
+
### Client
|
64
|
+
In your client code:
|
65
|
+
|
66
|
+
require 'rubygems'
|
67
|
+
require 'statsd'
|
68
|
+
STATSD = Statsd::Client.new('localhost',8125)
|
69
|
+
|
70
|
+
STATSD.increment('some_counter') # basic incrementing
|
71
|
+
STATSD.increment('system.nested_counter', 0.1) # incrementing with sampling (10%)
|
72
|
+
|
73
|
+
STATSD.decrement(:some_other_counter) # basic decrememting using a symbol
|
74
|
+
STATSD.decrement('system.nested_counter', 0.1) # decrementing with sampling (10%)
|
75
|
+
|
76
|
+
STATSD.timing('some_job_time', 20) # reporting job that took 20ms
|
77
|
+
STATSD.timing('some_job_time', 20, 0.05) # reporting job that took 20ms with sampling (5% sampling)
|
8
78
|
|
9
79
|
Concepts
|
10
80
|
--------
|
@@ -47,10 +117,15 @@ Guts
|
|
47
117
|
* [UDP][udp]
|
48
118
|
Client libraries use UDP to send information to the StatsD daemon.
|
49
119
|
|
50
|
-
* [
|
120
|
+
* [EventMachine][eventmachine]
|
51
121
|
* [Graphite][graphite]
|
122
|
+
* [MongoDB][mongodb]
|
123
|
+
|
124
|
+
|
125
|
+
Graphite
|
126
|
+
--------
|
52
127
|
|
53
|
-
Graphite uses "schemas" to define the different round robin datasets it houses (analogous to RRAs in rrdtool)
|
128
|
+
Graphite uses "schemas" to define the different round robin datasets it houses (analogous to RRAs in rrdtool):
|
54
129
|
|
55
130
|
[stats]
|
56
131
|
priority = 110
|
@@ -65,73 +140,17 @@ That translates to:
|
|
65
140
|
|
66
141
|
This has been a good tradeoff so far between size-of-file (round robin databases are fixed size) and data we care about. Each "stats" database is about 3.2 megs with these retentions.
|
67
142
|
|
68
|
-
Ruby
|
69
|
-
----
|
70
|
-
A ruby version of statsd.
|
71
|
-
|
72
|
-
### Installation
|
73
|
-
|
74
|
-
gem install statsd
|
75
|
-
|
76
|
-
### Configuration
|
77
|
-
|
78
|
-
Edit the example config.yml and em-server.rb to your liking. There are 2 flush protocols: graphite and mongo (experimental).
|
79
|
-
|
80
|
-
### Server
|
81
|
-
Run the server:
|
82
|
-
|
83
|
-
ruby em-server.rb
|
84
|
-
|
85
|
-
### Client
|
86
|
-
In your client code:
|
87
|
-
|
88
|
-
require 'rubygems'
|
89
|
-
require 'statsd'
|
90
|
-
STATSD = Statsd::Client.new('localhost',8125)
|
91
|
-
|
92
|
-
STATSD.increment('some_counter') # basic incrementing
|
93
|
-
STATSD.increment('system.nested_counter', 0.1) # incrementing with sampling (10%)
|
94
|
-
|
95
|
-
STATSD.decrement(:some_other_counter) # basic decrememting using a symbol
|
96
|
-
STATSD.decrement('system.nested_counter', 0.1) # decrementing with sampling (10%)
|
97
|
-
|
98
|
-
STATSD.timing('some_job_time', 20) # reporting job that took 20ms
|
99
|
-
STATSD.timing('some_job_time', 20, 0.05) # reporting job that took 20ms with sampling (5% sampling)
|
100
|
-
|
101
143
|
|
102
144
|
Inspiration
|
103
145
|
-----------
|
104
146
|
|
105
147
|
StatsD was inspired (heavily) by the project (of the same name) at Flickr. Here's a post where Cal Henderson described it in depth:
|
106
148
|
[Counting and timing](http://code.flickr.com/blog/2008/10/27/counting-timing/). Cal re-released the code recently: [Perl StatsD](https://github.com/iamcal/Flickr-StatsD)
|
107
|
-
|
108
|
-
|
109
|
-
Contribute
|
110
|
-
---------------------
|
111
|
-
|
112
|
-
You're interested in contributing to StatsD? *AWESOME*. Here are the basic steps:
|
113
|
-
|
114
|
-
fork StatsD from here: http://github.com/etsy/statsd
|
115
|
-
|
116
|
-
1. Clone your fork
|
117
|
-
2. Hack away
|
118
|
-
3. If you are adding new functionality, document it in the README
|
119
|
-
4. If necessary, rebase your commits into logical chunks, without errors
|
120
|
-
5. Push the branch up to GitHub
|
121
|
-
6. Send a pull request to the etsy/statsd project.
|
122
|
-
|
123
|
-
We'll do our best to get your changes in!
|
149
|
+
Inspired by [Etsy's][etsy] [blog post][blog post].
|
124
150
|
|
125
151
|
[graphite]: http://graphite.wikidot.com
|
126
152
|
[etsy]: http://www.etsy.com
|
127
153
|
[blog post]: http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/
|
128
|
-
[node]: http://nodejs.org
|
129
154
|
[udp]: http://enwp.org/udp
|
130
155
|
[eventmachine]: http://rubyeventmachine.com/
|
131
156
|
[mongodb]: http://www.mongodb.org/
|
132
|
-
|
133
|
-
Contributors
|
134
|
-
-----------------
|
135
|
-
|
136
|
-
In lieu of a list of contributors, check out the commit history for the project:
|
137
|
-
http://github.com/etsy/statsd/commits/master
|
data/bin/statsd
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
require 'yaml'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
begin
|
8
|
+
ORIGINAL_ARGV = ARGV.dup
|
9
|
+
|
10
|
+
options = {:graphite => true, :mongo => false}
|
11
|
+
|
12
|
+
parser = OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: statsd [options]"
|
14
|
+
|
15
|
+
opts.separator ""
|
16
|
+
opts.separator "Options:"
|
17
|
+
|
18
|
+
opts.on("-cCONFIG", "--config-file CONFIG", "Configuration file") do |x|
|
19
|
+
options[:config] = x
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-m", "--mongo", "Flush and aggregate stats to MongoDB") do
|
23
|
+
options[:mongo] = true
|
24
|
+
options[:graphite] = false
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("-g", "--graphite", "Flush stats to Graphite") do
|
28
|
+
options[:graphite] = true
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("-h", "--help", "Show this message") do
|
32
|
+
puts opts
|
33
|
+
exit
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
parser.parse!
|
39
|
+
|
40
|
+
# dispatch
|
41
|
+
if !options[:config]
|
42
|
+
puts parser.help
|
43
|
+
else
|
44
|
+
require 'statsd'
|
45
|
+
require 'statsd/server'
|
46
|
+
Statsd::Server::Daemon.new.run(options)
|
47
|
+
end
|
48
|
+
rescue Exception => e
|
49
|
+
if e.instance_of?(SystemExit)
|
50
|
+
raise
|
51
|
+
else
|
52
|
+
puts 'Uncaught exception'
|
53
|
+
puts e.message
|
54
|
+
puts e.backtrace.join("\n")
|
55
|
+
end
|
56
|
+
end
|
data/config.yml
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
---
|
2
|
+
bind: 127.0.0.1
|
3
|
+
port: 8125
|
4
|
+
|
2
5
|
# Flush interval should be your finest retention in seconds
|
3
6
|
flush_interval: 10
|
4
7
|
|
5
8
|
# Graphite
|
6
9
|
graphite_host: localhost
|
7
|
-
graphite_port:
|
10
|
+
graphite_port: 2003
|
8
11
|
|
9
12
|
# Mongo
|
10
|
-
mongo_host:
|
11
|
-
mongo_database:
|
13
|
+
mongo_host: localhost
|
14
|
+
mongo_database: statsdb
|
12
15
|
|
13
16
|
# If you change these, you need to delete the capped collections yourself!
|
14
17
|
# Average mongo record size is 152 bytes
|
data/lib/statsd/echos.rb
CHANGED
@@ -16,6 +16,6 @@ module EchoServer
|
|
16
16
|
end
|
17
17
|
|
18
18
|
EventMachine::run {
|
19
|
-
EventMachine::start_server "127.0.0.1",
|
20
|
-
puts 'running dummy graphite echo server on
|
19
|
+
EventMachine::start_server "127.0.0.1", 2003, EchoServer
|
20
|
+
puts 'running dummy graphite echo server on 2003'
|
21
21
|
}
|
data/lib/statsd/graphite.rb
CHANGED
@@ -27,7 +27,7 @@ module Statsd
|
|
27
27
|
# end
|
28
28
|
|
29
29
|
def flush_stats
|
30
|
-
print "#{Time.now} Flushing #{counters.count} counters and #{timers.count} timers to Graphite"
|
30
|
+
print "#{Time.now} Flushing #{counters.count} counters and #{timers.count} timers to Graphite."
|
31
31
|
stat_string = ''
|
32
32
|
time = ::Benchmark.realtime do
|
33
33
|
ts = Time.now.to_i
|
data/lib/statsd/mongo.rb
CHANGED
@@ -26,8 +26,6 @@ module Statsd
|
|
26
26
|
value /= flush_interval
|
27
27
|
doc = {:stat => key, :value => value, :ts => ts_bucket, :type => "counter" }
|
28
28
|
docs.push(doc)
|
29
|
-
message = "stats.#{key} #{value} #{ts}\n"
|
30
|
-
stat_string += message
|
31
29
|
counters[key] = 0
|
32
30
|
|
33
31
|
num_stats += 1
|
@@ -75,7 +73,6 @@ module Statsd
|
|
75
73
|
num_stats += 1
|
76
74
|
end
|
77
75
|
end
|
78
|
-
stat_string += "statsd.numStats #{num_stats} #{ts}\n"
|
79
76
|
coll.insert(docs)
|
80
77
|
|
81
78
|
aggregate(ts_bucket)
|
data/lib/statsd/server.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
+
require 'yaml'
|
3
|
+
require 'erb'
|
2
4
|
module Statsd
|
3
5
|
module Server #< EM::Connection
|
4
|
-
Version = '0.0
|
6
|
+
Version = '0.5.0'
|
5
7
|
|
6
8
|
FLUSH_INTERVAL = 10
|
7
9
|
COUNTERS = {}
|
8
10
|
TIMERS = {}
|
11
|
+
|
9
12
|
def post_init
|
10
13
|
puts "statsd server started!"
|
11
14
|
end
|
15
|
+
|
12
16
|
def self.get_and_clear_stats!
|
13
17
|
counters = COUNTERS.dup
|
14
18
|
timers = TIMERS.dup
|
@@ -16,6 +20,7 @@ module Statsd
|
|
16
20
|
TIMERS.clear
|
17
21
|
[counters,timers]
|
18
22
|
end
|
23
|
+
|
19
24
|
def receive_data(msg)
|
20
25
|
msg.split("\n").each do |row|
|
21
26
|
# puts row
|
@@ -37,5 +42,66 @@ module Statsd
|
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
45
|
+
|
46
|
+
class Daemon
|
47
|
+
def run(options)
|
48
|
+
config = YAML::load(ERB.new(IO.read(options[:config])).result)
|
49
|
+
|
50
|
+
if options[:mongo]
|
51
|
+
require 'statsd/mongo'
|
52
|
+
# Setup retention store
|
53
|
+
db = ::Mongo::Connection.new(config['mongo_host']).db(config['mongo_database'])
|
54
|
+
config['retentions'].each do |retention|
|
55
|
+
collection_name = retention['name']
|
56
|
+
unless db.collection_names.include?(collection_name)
|
57
|
+
db.create_collection(collection_name, :capped => retention['capped'], :size => retention['cap_bytes'])
|
58
|
+
end
|
59
|
+
db.collection(collection_name).ensure_index([['ts', ::Mongo::ASCENDING]])
|
60
|
+
end
|
61
|
+
Statsd::Mongo.hostname = config['mongo_host']
|
62
|
+
Statsd::Mongo.database = config['mongo_database']
|
63
|
+
Statsd::Mongo.retentions = config['retentions']
|
64
|
+
Statsd::Mongo.flush_interval = config['flush_interval']
|
65
|
+
end
|
66
|
+
|
67
|
+
if options[:graphite]
|
68
|
+
require 'statsd/graphite'
|
69
|
+
end
|
70
|
+
|
71
|
+
# Start the server
|
72
|
+
EventMachine::run do
|
73
|
+
EventMachine::open_datagram_socket(config['bind'], config['port'], Statsd::Server)
|
74
|
+
|
75
|
+
# Periodically Flush
|
76
|
+
EventMachine::add_periodic_timer(config['flush_interval']) do
|
77
|
+
counters,timers = Statsd::Server.get_and_clear_stats!
|
78
|
+
|
79
|
+
# Flush Adapters
|
80
|
+
if options[:mongo]
|
81
|
+
EM.defer { Statsd::Mongo.flush_stats(counters,timers) }
|
82
|
+
end
|
83
|
+
|
84
|
+
if options[:graphite]
|
85
|
+
EventMachine.connect config['graphite_host'], config['graphite_port'], Statsd::Graphite do |conn|
|
86
|
+
conn.counters = counters
|
87
|
+
conn.timers = timers
|
88
|
+
conn.flush_interval = config['flush_interval']
|
89
|
+
conn.flush_stats
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
40
99
|
end
|
41
|
-
end
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
require 'statsd/graphite'
|
105
|
+
|
106
|
+
|
107
|
+
|
data/lib/statsd/test.rb
ADDED
data/{em-server.rb → stats.rb}
RENAMED
File without changes
|
data/statsd.gemspec
CHANGED
@@ -10,12 +10,13 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.email = ['quasor@me.com']
|
11
11
|
s.homepage = "http://github.com/quasor/statsd"
|
12
12
|
s.summary = "Ruby version of statsd."
|
13
|
-
s.description = "
|
13
|
+
s.description = "A network daemon for aggregating statistics (counters and timers), rolling them up, then sending them to graphite or mongo."
|
14
14
|
|
15
15
|
s.required_rubygems_version = ">= 1.3.6"
|
16
16
|
|
17
|
-
s.add_dependency "eventmachine",
|
18
|
-
s.add_dependency "mongo",
|
17
|
+
s.add_dependency "eventmachine", "~> 0.12.10"
|
18
|
+
s.add_dependency "mongo", "~> 1.2.4"
|
19
|
+
s.add_dependency "erubis", "~> 2.6.6"
|
19
20
|
|
20
21
|
s.files = `git ls-files`.split("\n")
|
21
22
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: statsd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0
|
5
|
+
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrew Coldham
|
@@ -33,52 +33,42 @@ dependencies:
|
|
33
33
|
requirements:
|
34
34
|
- - ~>
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: 1.2.
|
36
|
+
version: 1.2.4
|
37
37
|
type: :runtime
|
38
38
|
version_requirements: *id002
|
39
|
-
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: erubis
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.6.6
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id003
|
50
|
+
description: A network daemon for aggregating statistics (counters and timers), rolling them up, then sending them to graphite or mongo.
|
40
51
|
email:
|
41
52
|
- quasor@me.com
|
42
|
-
executables:
|
43
|
-
|
53
|
+
executables:
|
54
|
+
- statsd
|
44
55
|
extensions: []
|
45
56
|
|
46
57
|
extra_rdoc_files: []
|
47
58
|
|
48
59
|
files:
|
49
|
-
- LICENSE
|
50
60
|
- README.md
|
51
|
-
-
|
61
|
+
- bin/statsd
|
52
62
|
- config.yml
|
53
|
-
- em-server.rb
|
54
|
-
- exampleConfig.js
|
55
63
|
- lib/statsd.rb
|
56
64
|
- lib/statsd/echos.rb
|
57
65
|
- lib/statsd/graphite.rb
|
58
66
|
- lib/statsd/mongo.rb
|
59
67
|
- lib/statsd/server.rb
|
68
|
+
- lib/statsd/test.rb
|
60
69
|
- netcat-example.sh
|
61
|
-
-
|
62
|
-
- python_example.py
|
63
|
-
- stats.js
|
70
|
+
- stats.rb
|
64
71
|
- statsd.gemspec
|
65
|
-
- webapp/Gemfile
|
66
|
-
- webapp/Gemfile.lock
|
67
|
-
- webapp/README.md
|
68
|
-
- webapp/app.rb
|
69
|
-
- webapp/bin/rackup
|
70
|
-
- webapp/bin/statsd-web
|
71
|
-
- webapp/config.yml
|
72
|
-
- webapp/public/jquery-1.4.4.js
|
73
|
-
- webapp/public/jquery.flot.js
|
74
|
-
- webapp/public/jquery.flot.selection.js
|
75
|
-
- webapp/vendor/cache/SystemTimer-1.2.2.gem
|
76
|
-
- webapp/vendor/cache/rack-1.2.1.gem
|
77
|
-
- webapp/vendor/cache/redis-2.1.1.gem
|
78
|
-
- webapp/vendor/cache/sinatra-1.1.3.gem
|
79
|
-
- webapp/vendor/cache/tilt-1.2.2.gem
|
80
|
-
- webapp/vendor/cache/vegas-0.1.8.gem
|
81
|
-
- webapp/views/chart.erb
|
82
72
|
has_rdoc: true
|
83
73
|
homepage: http://github.com/quasor/statsd
|
84
74
|
licenses: []
|
data/LICENSE
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2010 Etsy
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person
|
4
|
-
obtaining a copy of this software and associated documentation
|
5
|
-
files (the "Software"), to deal in the Software without
|
6
|
-
restriction, including without limitation the rights to use,
|
7
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
copies of the Software, and to permit persons to whom the
|
9
|
-
Software is furnished to do so, subject to the following
|
10
|
-
conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be
|
13
|
-
included in all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
data/config.js
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
var fs = require('fs')
|
2
|
-
, sys = require('sys')
|
3
|
-
|
4
|
-
var Configurator = function (file) {
|
5
|
-
|
6
|
-
var self = this;
|
7
|
-
var config = {};
|
8
|
-
var oldConfig = {};
|
9
|
-
|
10
|
-
this.updateConfig = function () {
|
11
|
-
sys.log('reading config file: ' + file);
|
12
|
-
|
13
|
-
fs.readFile(file, function (err, data) {
|
14
|
-
if (err) { throw err; }
|
15
|
-
old_config = self.config;
|
16
|
-
|
17
|
-
self.config = process.compile('config = ' + data, file);
|
18
|
-
self.emit('configChanged', self.config);
|
19
|
-
});
|
20
|
-
};
|
21
|
-
|
22
|
-
this.updateConfig();
|
23
|
-
|
24
|
-
fs.watchFile(file, function (curr, prev) {
|
25
|
-
if (curr.ino != prev.ino) { self.updateConfig(); }
|
26
|
-
});
|
27
|
-
};
|
28
|
-
|
29
|
-
sys.inherits(Configurator, process.EventEmitter);
|
30
|
-
|
31
|
-
exports.Configurator = Configurator;
|
32
|
-
|
33
|
-
exports.configFile = function(file, callbackFunc) {
|
34
|
-
var config = new Configurator(file);
|
35
|
-
config.on('configChanged', function() {
|
36
|
-
callbackFunc(config.config, config.oldConfig);
|
37
|
-
});
|
38
|
-
};
|
39
|
-
|
data/exampleConfig.js
DELETED
data/php-example.php
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
<?php
|
2
|
-
|
3
|
-
/**
|
4
|
-
* Sends statistics to the stats daemon over UDP
|
5
|
-
*
|
6
|
-
**/
|
7
|
-
|
8
|
-
class StatsD {
|
9
|
-
|
10
|
-
/**
|
11
|
-
* Log timing information
|
12
|
-
*
|
13
|
-
* @param string $stats The metric to in log timing info for.
|
14
|
-
* @param float $time The ellapsed time (ms) to log
|
15
|
-
* @param float|1 $sampleRate the rate (0-1) for sampling.
|
16
|
-
**/
|
17
|
-
public static function timing($stat, $time, $sampleRate=1) {
|
18
|
-
StatsD::send(array($stat => "$time|ms"), $sampleRate);
|
19
|
-
}
|
20
|
-
|
21
|
-
/**
|
22
|
-
* Increments one or more stats counters
|
23
|
-
*
|
24
|
-
* @param string|array $stats The metric(s) to increment.
|
25
|
-
* @param float|1 $sampleRate the rate (0-1) for sampling.
|
26
|
-
* @return boolean
|
27
|
-
**/
|
28
|
-
public static function increment($stats, $sampleRate=1) {
|
29
|
-
StatsD::updateStats($stats, 1, $sampleRate);
|
30
|
-
}
|
31
|
-
|
32
|
-
/**
|
33
|
-
* Decrements one or more stats counters.
|
34
|
-
*
|
35
|
-
* @param string|array $stats The metric(s) to decrement.
|
36
|
-
* @param float|1 $sampleRate the rate (0-1) for sampling.
|
37
|
-
* @return boolean
|
38
|
-
**/
|
39
|
-
public static function decrement($stats, $sampleRate=1) {
|
40
|
-
StatsD::updateStats($stats, -1, $sampleRate);
|
41
|
-
}
|
42
|
-
|
43
|
-
/**
|
44
|
-
* Updates one or more stats counters by arbitrary amounts.
|
45
|
-
*
|
46
|
-
* @param string|array $stats The metric(s) to update. Should be either a string or array of metrics.
|
47
|
-
* @param int|1 $delta The amount to increment/decrement each metric by.
|
48
|
-
* @param float|1 $sampleRate the rate (0-1) for sampling.
|
49
|
-
* @return boolean
|
50
|
-
**/
|
51
|
-
public static function updateStats($stats, $delta=1, $sampleRate=1) {
|
52
|
-
if (!is_array($stats)) { $stats = array($stats); }
|
53
|
-
$data = array();
|
54
|
-
foreach($stats as $stat) {
|
55
|
-
$data[$stat] = "$delta|c";
|
56
|
-
}
|
57
|
-
|
58
|
-
StatsD::send($data, $sampleRate);
|
59
|
-
}
|
60
|
-
|
61
|
-
/*
|
62
|
-
* Squirt the metrics over UDP
|
63
|
-
**/
|
64
|
-
public static function send($data, $sampleRate=1) {
|
65
|
-
$config = Config::getInstance();
|
66
|
-
if (! $config->isEnabled("statsd")) { return; }
|
67
|
-
|
68
|
-
// sampling
|
69
|
-
$sampledData = array();
|
70
|
-
|
71
|
-
if ($sampleRate < 1) {
|
72
|
-
foreach ($data as $stat => $value) {
|
73
|
-
if ((mt_rand() / mt_getrandmax()) <= $sampleRate) {
|
74
|
-
$sampledData[$stat] = "$value|@$sampleRate";
|
75
|
-
}
|
76
|
-
}
|
77
|
-
} else {
|
78
|
-
$sampledData = $data;
|
79
|
-
}
|
80
|
-
|
81
|
-
if (empty($sampledData)) { return; }
|
82
|
-
|
83
|
-
// Wrap this in a try/catch - failures in any of this should be silently ignored
|
84
|
-
try {
|
85
|
-
$host = $config->getConfig("statsd.host");
|
86
|
-
$port = $config->getConfig("statsd.port");
|
87
|
-
$fp = fsockopen("udp://$host", $port, $errno, $errstr);
|
88
|
-
if (! $fp) { return; }
|
89
|
-
foreach ($sampledData as $stat => $value) {
|
90
|
-
fwrite($fp, "$stat:$value");
|
91
|
-
}
|
92
|
-
fclose($fp);
|
93
|
-
} catch (Exception $e) {
|
94
|
-
}
|
95
|
-
}
|
96
|
-
}
|