inst_statsd 2.0.4

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.
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe InstStatsd::BlockStat do
4
+ it "track exclusives correctly" do
5
+ stat = InstStatsd::BlockStat.new("key")
6
+ stat.stats['total'] = 5.0
7
+ stat.subtract_exclusives("total" => 1.5)
8
+ stat.subtract_exclusives("total" => 2.1)
9
+ expect(stat.exclusive_stats).to eql("total" => 1.4)
10
+ end
11
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe InstStatsd::BlockTracking do
4
+ before(:all) do
5
+ InstStatsd::DefaultTracking.track_sql
6
+ end
7
+
8
+ it "works" do
9
+ statsd = double()
10
+ allow(statsd).to receive(:timing).with('mykey.total', anything)
11
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 1)
12
+
13
+ InstStatsd::BlockTracking.track("mykey", statsd: statsd, only: 'sql.read') do
14
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
15
+ end
16
+ end
17
+
18
+ it "keeps track of exclusive stats too" do
19
+ statsd = double()
20
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 2).ordered
21
+ expect(statsd).to receive(:timing).with('mykey.total', anything).ordered
22
+ expect(statsd).to receive(:timing).with("mykey.exclusive.sql.read", 2).ordered
23
+ expect(statsd).to receive(:timing).with('mykey.exclusive.total', anything).ordered
24
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 2).ordered
25
+ expect(statsd).to receive(:timing).with('mykey.total', anything).ordered
26
+ expect(statsd).to receive(:timing).with("mykey.exclusive.sql.read", 2).ordered
27
+ expect(statsd).to receive(:timing).with('mykey.exclusive.total', anything).ordered
28
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 5).ordered
29
+ expect(statsd).to receive(:timing).with('mykey.total', anything).ordered
30
+ expect(statsd).to receive(:timing).with("mykey.exclusive.sql.read", 1).ordered
31
+ expect(statsd).to receive(:timing).with('mykey.exclusive.total', anything).ordered
32
+
33
+ InstStatsd::BlockTracking.track("mykey", category: :nested, statsd: statsd, only: 'sql.read') do
34
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
35
+ InstStatsd::BlockTracking.track("mykey", category: :nested, statsd: statsd, only: 'sql.read') do
36
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
37
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
38
+ end
39
+ InstStatsd::BlockTracking.track("mykey", category: :nested, statsd: statsd, only: 'sql.read') do
40
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
41
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
42
+ end
43
+ end
44
+ end
45
+
46
+ context "mask" do
47
+ after do
48
+ InstStatsd::BlockTracking.mask = nil
49
+ InstStatsd::BlockTracking.negative_mask = nil
50
+ end
51
+
52
+ it "only tracks keys that match the mask" do
53
+ InstStatsd::BlockTracking.mask = /mykey/
54
+ statsd = double()
55
+ allow(statsd).to receive(:timing).with('mykey.total', anything)
56
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 1)
57
+
58
+ InstStatsd::BlockTracking.track("mykey", statsd: statsd, only: 'sql.read') do
59
+ InstStatsd::BlockTracking.track("ignoreme", statsd: statsd, only: 'sql.read') do
60
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
61
+ end
62
+ end
63
+ end
64
+
65
+ it "doesn't track keys that match the negative mask" do
66
+ InstStatsd::BlockTracking.negative_mask = /ignoreme/
67
+ statsd = double()
68
+ allow(statsd).to receive(:timing).with('mykey.total', anything)
69
+ expect(statsd).to receive(:timing).with("mykey.sql.read", 1)
70
+
71
+ InstStatsd::BlockTracking.track("mykey", statsd: statsd, only: 'sql.read') do
72
+ InstStatsd::BlockTracking.track("ignoreme", statsd: statsd, only: 'sql.read') do
73
+ ActiveSupport::Notifications.instrument('sql.active_record', name: "LOAD", sql: "SELECT * FROM users") {}
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe InstStatsd::Counter do
4
+
5
+ let(:subject) { InstStatsd::Counter.new('test', ['foo']) }
6
+
7
+ describe "#accepted_name?" do
8
+ it 'should return true for names not in blocked_names' do
9
+ expect(subject.accepted_name?('bar')).to eq true
10
+ end
11
+
12
+ it 'should return false for names in blocked_names' do
13
+ expect(subject.accepted_name?('foo')).to eq false
14
+ end
15
+
16
+ it 'should return true for empty string names' do
17
+ expect(subject.accepted_name?('')).to eq true
18
+ end
19
+
20
+ it 'should return true for empty nil names' do
21
+ expect(subject.accepted_name?(nil)).to eq true
22
+ end
23
+ end
24
+
25
+ describe "#track" do
26
+ it 'should increment when given allowed names' do
27
+ cookie = subject.start
28
+ subject.track('bar')
29
+ subject.track('baz')
30
+ expect(subject.finalize_count(cookie)).to eq 2
31
+ end
32
+
33
+ it 'should not increment when given a blocked name' do
34
+ cookie = subject.start
35
+ subject.track('foo') #shouldn't count as foo is a blocked name
36
+ subject.track('name')
37
+ expect(subject.finalize_count(cookie)).to eq 1
38
+ end
39
+ end
40
+
41
+ describe "#finalize_count" do
42
+ it 'should return the current count' do
43
+ cookie = subject.start
44
+ subject.track('bar')
45
+ expect(subject.finalize_count(cookie)).to eq 1
46
+ end
47
+
48
+ it 'should not interfere with multiple people using the object' do
49
+ cookie1 = subject.start
50
+ subject.track('bar')
51
+ cookie2 = subject.start
52
+ subject.track('bar')
53
+ expect(subject.finalize_count(cookie1)).to eq 2
54
+ expect(subject.finalize_count(cookie2)).to eq 1
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,187 @@
1
+ require 'spec_helper'
2
+
3
+ describe InstStatsd do
4
+ before(:each) do
5
+ InstStatsd.settings = nil
6
+ end
7
+
8
+ after(:each) do
9
+ [
10
+ 'INST_STATSD_HOST',
11
+ 'INST_STATSD_NAMESPACE',
12
+ 'INST_STATSD_PORT',
13
+ 'INST_STATSD_APPEND_HOST_NAME',
14
+ ].each {|k| ENV.delete k}
15
+ end
16
+
17
+ describe ".settings" do
18
+ it "have default settings" do
19
+ expect(InstStatsd.settings).to eq({})
20
+ end
21
+
22
+ it "can be assigned a new value" do
23
+ settings = { host: 'bar', port: 1234 }
24
+ InstStatsd.settings = settings
25
+
26
+ expect(InstStatsd.settings).to eq settings
27
+ end
28
+
29
+ it 'pulls from ENV if not already set' do
30
+ ENV['INST_STATSD_HOST'] = 'statsd.example.org'
31
+ ENV['INST_STATSD_NAMESPACE'] = 'canvas'
32
+
33
+ expected = {
34
+ host: 'statsd.example.org',
35
+ namespace: 'canvas',
36
+ }
37
+ expect(InstStatsd.settings).to eq(expected)
38
+ end
39
+
40
+ it 'configured settings are merged into and take precedence over any existing ENV settings' do
41
+ ENV['INST_STATSD_HOST'] = 'statsd.example.org'
42
+ ENV['INST_STATSD_NAMESPACE'] = 'canvas'
43
+
44
+ settings = { host: 'statsd.example-override.org' }
45
+ InstStatsd.settings = settings
46
+
47
+ expect(InstStatsd.settings).to eq(InstStatsd.env_settings.merge(settings))
48
+ expect(InstStatsd.settings[:host]).to eq(settings[:host])
49
+ end
50
+
51
+ it 'validates settings' do
52
+ settings = { foo: 'blah' }
53
+ expect { InstStatsd.settings = settings }.to raise_error(InstStatsd::ConfigurationError)
54
+ end
55
+
56
+ it 'converts string keys to symbols' do
57
+ settings = { 'host' => 'bar', 'port' => 1234 }
58
+ InstStatsd.settings = settings
59
+ expect(InstStatsd.settings).to eq({ host: 'bar', port: 1234 })
60
+ end
61
+ end
62
+
63
+ describe ".convert_bool" do
64
+ it 'sets string true values to boolean true' do
65
+ config = {potential_string_bool: 'true'}
66
+ InstStatsd.convert_bool(config, :potential_string_bool)
67
+ expect(config[:potential_string_bool]).to be(true)
68
+ end
69
+ it 'sets string True values to boolean true' do
70
+ config = {potential_string_bool: 'True'}
71
+ InstStatsd.convert_bool(config, :potential_string_bool)
72
+ expect(config[:potential_string_bool]).to be(true)
73
+ end
74
+ it 'sets boolean true values to boolean true' do
75
+ config = {potential_string_bool: true}
76
+ InstStatsd.convert_bool(config, :potential_string_bool)
77
+ expect(config[:potential_string_bool]).to be(true)
78
+ end
79
+ it 'sets false strings to boolean false' do
80
+ config = {potential_string_bool: 'false'}
81
+ InstStatsd.convert_bool(config, :potential_string_bool)
82
+ expect(config[:potential_string_bool]).to be(false)
83
+ end
84
+ it 'sets False strings to boolean false' do
85
+ config = {potential_string_bool: 'False'}
86
+ InstStatsd.convert_bool(config, :potential_string_bool)
87
+ expect(config[:potential_string_bool]).to be(false)
88
+ end
89
+ it 'sets false booleans to boolean false' do
90
+ config = {potential_string_bool: false}
91
+ InstStatsd.convert_bool(config, :potential_string_bool)
92
+ expect(config[:potential_string_bool]).to be(false)
93
+ end
94
+ it 'makes no change for nil values' do
95
+ config = {foo: 'bar'}
96
+ InstStatsd.convert_bool(config, :potential_string_bool)
97
+ expect(config).to eq({foo: 'bar'})
98
+ end
99
+ it 'raises error for non true or false strings or booleans' do
100
+ config = {potential_string_bool: 'trrruuue'}
101
+ expect{InstStatsd.convert_bool(config, :potential_string_bool)}.to raise_error(InstStatsd::ConfigurationError)
102
+ end
103
+
104
+ end
105
+
106
+ describe ".env_settings" do
107
+ it 'returns empty hash when no INST_STATSD_HOST found' do
108
+ env = {
109
+ 'INST_STATSD_NAMESPACE' => 'canvas'
110
+ }
111
+ expect(InstStatsd.env_settings(env)).to eq({})
112
+ end
113
+
114
+ it 'builds settings hash from environment vars' do
115
+ env = {
116
+ 'INST_STATSD_HOST' => 'statsd.example.org',
117
+ 'INST_STATSD_NAMESPACE' => 'canvas',
118
+ }
119
+ expected = {
120
+ host: 'statsd.example.org',
121
+ namespace: 'canvas',
122
+ }
123
+ expect(InstStatsd.env_settings(env)).to eq(expected)
124
+ end
125
+
126
+ it 'uses ENV if env argument hash not passed' do
127
+ ENV['INST_STATSD_HOST'] = 'statsd.example.org'
128
+ ENV['INST_STATSD_NAMESPACE'] = 'canvas'
129
+
130
+ expected = {
131
+ host: 'statsd.example.org',
132
+ namespace: 'canvas',
133
+ }
134
+ expect(InstStatsd.env_settings).to eq(expected)
135
+ end
136
+
137
+ it 'converts env append_hostname "false" to boolean' do
138
+ env = {
139
+ 'INST_STATSD_HOST' => 'statsd.example.org',
140
+ 'INST_STATSD_APPEND_HOSTNAME' => 'false',
141
+ }
142
+ expected = {
143
+ host: 'statsd.example.org',
144
+ append_hostname: false,
145
+ }
146
+ expect(InstStatsd.env_settings(env)).to eq(expected)
147
+ end
148
+
149
+ it 'converts env append_hostname "true" to boolean' do
150
+ env = {
151
+ 'INST_STATSD_HOST' => 'statsd.example.org',
152
+ 'INST_STATSD_APPEND_HOSTNAME' => 'true',
153
+ }
154
+ expected = {
155
+ host: 'statsd.example.org',
156
+ append_hostname: true,
157
+ }
158
+ expect(InstStatsd.env_settings(env)).to eq(expected)
159
+ end
160
+
161
+ it 'keeps boolean false values for append_hostname' do
162
+ env = {
163
+ 'INST_STATSD_HOST' => 'statsd.example.org',
164
+ 'INST_STATSD_APPEND_HOSTNAME' => false,
165
+ }
166
+ expected = {
167
+ host: 'statsd.example.org',
168
+ append_hostname: false,
169
+ }
170
+ expect(InstStatsd.env_settings(env)).to eq(expected)
171
+ end
172
+
173
+ it 'keeps boolean true values for append_hostname' do
174
+ env = {
175
+ 'INST_STATSD_HOST' => 'statsd.example.org',
176
+ 'INST_STATSD_APPEND_HOSTNAME' => true,
177
+ }
178
+ expected = {
179
+ host: 'statsd.example.org',
180
+ append_hostname: true,
181
+ }
182
+ expect(InstStatsd.env_settings(env)).to eq(expected)
183
+ end
184
+
185
+ end
186
+
187
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe InstStatsd::NullLogger do
4
+
5
+ describe 'initialize' do
6
+ it 'takes any arguments' do
7
+ expect{InstStatsd::NullLogger.new}.to_not raise_error
8
+ expect{InstStatsd::NullLogger.new(1, 2, 3)}.to_not raise_error
9
+ end
10
+ end
11
+
12
+ describe 'debug, info, warn, fatal, and unknown' do
13
+ it 'should all no-op instead of logging' do
14
+ log_path = 'spec/support/test.log'
15
+ File.open(log_path, 'w') { |f| f.write('') } # empty log file
16
+ logger = InstStatsd::NullLogger.new(log_path)
17
+ %w[debug info warn error fatal unknown].each { |m| logger.send(m, 'foo') }
18
+ log_contents = File.read(log_path)
19
+ expect(log_contents).to eq ''
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+ require 'logger'
3
+
4
+ describe InstStatsd::RequestLogger do
5
+
6
+ describe '#build_log_message' do
7
+ before :all do
8
+ @logger = InstStatsd::RequestLogger.new(Logger.new(STDOUT))
9
+ end
10
+ it 'includes the supplied header' do
11
+ request_stat = double('request_stat')
12
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
13
+ allow(request_stat).to receive(:stats).and_return({})
14
+ results = @logger.build_log_message(request_stat, 'FOO_STATS')
15
+ expect(results).to eq("[FOO_STATS]")
16
+ end
17
+ it 'falls back to the default header' do
18
+ request_stat = double('request_stat')
19
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
20
+ allow(request_stat).to receive(:stats).and_return({})
21
+ results = @logger.build_log_message(request_stat)
22
+ expect(results).to eq("[STATSD]")
23
+ end
24
+ it 'includes stats that are available' do
25
+ request_stat = double('request_stat')
26
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
27
+ allow(request_stat).to receive(:stats).and_return(
28
+ "total" => 100.21,
29
+ "active.record" => 24)
30
+ results = @logger.build_log_message(request_stat)
31
+ expect(results).to eq("[STATSD] (total: 100.21) (active_record: 24.00)")
32
+ end
33
+
34
+ it 'includes exclusive_stats if there are any' do
35
+ request_stat = double('request_stat')
36
+ allow(request_stat).to receive(:stats).and_return(
37
+ "total" => 100.21,
38
+ "active.record" => 24)
39
+ allow(request_stat).to receive(:exclusive_stats).and_return(
40
+ "total" => 54.32,
41
+ "active.record" => 1)
42
+ results = @logger.build_log_message(request_stat)
43
+ expect(results).to eq("[STATSD] (total: 100.21) (active_record: 24.00) (exclusive_total: 54.32) (exclusive_active_record: 1.00)")
44
+ end
45
+
46
+ describe 'decimal precision' do
47
+ it 'forces 2 decimal precision' do
48
+ request_stat = double('request_stat')
49
+ allow(request_stat).to receive(:stats).and_return(total: 72.1)
50
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
51
+ results = @logger.build_log_message(request_stat)
52
+ expect(results).to eq("[STATSD] (total: 72.10)")
53
+ end
54
+ it 'rounds values to 2 decimals' do
55
+ request_stat = double('request_stat')
56
+ allow(request_stat).to receive(:stats).and_return(total: 72.1382928)
57
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
58
+ results = @logger.build_log_message(request_stat)
59
+ expect(results).to eq("[STATSD] (total: 72.14)")
60
+ allow(request_stat).to receive(:stats).and_return(total: 72.1348209)
61
+ results = @logger.build_log_message(request_stat)
62
+ expect(results).to eq("[STATSD] (total: 72.13)")
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ describe '#log' do
69
+ it 'sends info method to logger if logger exists' do
70
+ std_out_logger = Logger.new(STDOUT)
71
+ logger = InstStatsd::RequestLogger.new(std_out_logger)
72
+ expect(std_out_logger).to receive(:info)
73
+ request_stat = double('request_stat')
74
+ allow(request_stat).to receive(:stats).and_return({})
75
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
76
+ logger.log(request_stat)
77
+ end
78
+ it 'sends info method with build_log_message output if logger exists' do
79
+ std_out_logger = Logger.new(STDOUT)
80
+ logger = InstStatsd::RequestLogger.new(std_out_logger)
81
+ expect(std_out_logger).to receive(:info).with("[DEFAULT_METRICS] (total: 100.20)")
82
+ request_stat = double('request_stat')
83
+ allow(request_stat).to receive(:stats).and_return(total: 100.2)
84
+ allow(request_stat).to receive(:exclusive_stats).and_return(nil)
85
+ logger.log(request_stat, "DEFAULT_METRICS")
86
+ end
87
+ end
88
+
89
+ end