inst_statsd 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/inst_statsd.rb +65 -0
- data/lib/inst_statsd/block_stat.rb +37 -0
- data/lib/inst_statsd/block_tracking.rb +62 -0
- data/lib/inst_statsd/counter.rb +44 -0
- data/lib/inst_statsd/default_tracking.rb +42 -0
- data/lib/inst_statsd/null_logger.rb +11 -0
- data/lib/inst_statsd/request_logger.rb +25 -0
- data/lib/inst_statsd/request_stat.rb +49 -0
- data/lib/inst_statsd/request_tracking.rb +27 -0
- data/lib/inst_statsd/sql_tracker.rb +50 -0
- data/lib/inst_statsd/statsd.rb +102 -0
- data/spec/inst_statsd/block_stat_spec.rb +11 -0
- data/spec/inst_statsd/block_tracking_spec.rb +78 -0
- data/spec/inst_statsd/counter_spec.rb +58 -0
- data/spec/inst_statsd/inst_statsd_spec.rb +187 -0
- data/spec/inst_statsd/null_logger_spec.rb +23 -0
- data/spec/inst_statsd/request_logger_spec.rb +89 -0
- data/spec/inst_statsd/request_stat_spec.rb +167 -0
- data/spec/inst_statsd/request_tracking_spec.rb +14 -0
- data/spec/inst_statsd/sql_tracker_spec.rb +96 -0
- data/spec/inst_statsd/statsd_spec.rb +98 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/test.log +0 -0
- data/test.sh +16 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f5fcae338209105c5074036e543c03f719f4b3ae
|
4
|
+
data.tar.gz: dbb3c4e3de0a2138737637b86b27ae9764fa7c27
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 00c31868c01435faa215bccbfaca3675fa86c0f7b7e4a356b57c7c04cdfcf83b20f4a33d31c58c0a46d94731f9c3bf01d1ea0d05f0c6204bfe15cd7daf26bdc6
|
7
|
+
data.tar.gz: 91bec914d1e70b5b497b35e675c9d947f0d8924fce7a20d4b8e9c7d4366becd43fa138f61df7ddc7820ef16e77afdb4764b6d9adaa5f9191cb0f4409d2b982f2
|
data/lib/inst_statsd.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'statsd'
|
2
|
+
|
3
|
+
module InstStatsd
|
4
|
+
VALID_SETTINGS = %i[host port namespace append_hostname mask negative_mask batch_size batch_byte_size].freeze
|
5
|
+
|
6
|
+
class ConfigurationError < StandardError; end
|
7
|
+
|
8
|
+
require 'inst_statsd/statsd'
|
9
|
+
require 'inst_statsd/block_stat'
|
10
|
+
require 'inst_statsd/block_tracking'
|
11
|
+
require 'inst_statsd/request_stat'
|
12
|
+
require 'inst_statsd/counter'
|
13
|
+
require 'inst_statsd/sql_tracker'
|
14
|
+
require 'inst_statsd/default_tracking'
|
15
|
+
require 'inst_statsd/request_logger'
|
16
|
+
require 'inst_statsd/request_tracking'
|
17
|
+
require 'inst_statsd/null_logger'
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def settings
|
21
|
+
@settings ||= env_settings
|
22
|
+
end
|
23
|
+
|
24
|
+
def settings=(value)
|
25
|
+
@settings = validate_settings(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def validate_settings(value)
|
29
|
+
return nil if value.nil?
|
30
|
+
|
31
|
+
validated = {}
|
32
|
+
value.each do |k, v|
|
33
|
+
unless VALID_SETTINGS.include?(k.to_sym)
|
34
|
+
raise InstStatsd::ConfigurationError, "Invalid key: #{k}"
|
35
|
+
end
|
36
|
+
v = Regexp.new(v) if %i[mask negative_mask].include?(k.to_sym) && v.is_a?(String)
|
37
|
+
validated[k.to_sym] = v
|
38
|
+
end
|
39
|
+
|
40
|
+
env_settings.merge(validated)
|
41
|
+
end
|
42
|
+
|
43
|
+
def env_settings(env = ENV)
|
44
|
+
config = {
|
45
|
+
host: env.fetch('INST_STATSD_HOST', nil),
|
46
|
+
port: env.fetch('INST_STATSD_PORT', nil),
|
47
|
+
namespace: env.fetch('INST_STATSD_NAMESPACE', nil),
|
48
|
+
append_hostname: env.fetch('INST_STATSD_APPEND_HOSTNAME', nil)
|
49
|
+
}
|
50
|
+
config.delete_if { |_k, v| v.nil? }
|
51
|
+
convert_bool(config, :append_hostname)
|
52
|
+
config[:host] ? config : {}
|
53
|
+
end
|
54
|
+
|
55
|
+
def convert_bool(hash, key)
|
56
|
+
value = hash[key]
|
57
|
+
return if value.nil?
|
58
|
+
unless ['true', 'True', 'false', 'False', true, false].include?(value)
|
59
|
+
message = "#{key} must be a boolean, or the string representation of a boolean, got: #{value}"
|
60
|
+
raise InstStatsd::ConfigurationError, message
|
61
|
+
end
|
62
|
+
hash[key] = ['true', 'True', true].include?(value)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class BlockStat
|
3
|
+
|
4
|
+
attr_accessor :stats
|
5
|
+
attr_accessor :common_key
|
6
|
+
|
7
|
+
def initialize(common_key, statsd=InstStatsd::Statsd)
|
8
|
+
self.common_key = common_key
|
9
|
+
@statsd = statsd
|
10
|
+
@stats = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def subtract_exclusives(stats)
|
14
|
+
@exclusives ||= {}
|
15
|
+
stats.each do |(key, value)|
|
16
|
+
@exclusives[key] ||= 0.0
|
17
|
+
@exclusives[key] += value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def exclusive_stats
|
22
|
+
return nil unless @exclusives
|
23
|
+
stats.map { |key, value| [key, value - (@exclusives[key] || 0.0)] }.to_h
|
24
|
+
end
|
25
|
+
|
26
|
+
def report
|
27
|
+
if common_key
|
28
|
+
stats.each do |(key, value)|
|
29
|
+
@statsd.timing("#{common_key}.#{key}", value)
|
30
|
+
end
|
31
|
+
exclusive_stats&.each do |(key, value)|
|
32
|
+
@statsd.timing("#{common_key}.exclusive.#{key}", value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
module InstStatsd
|
4
|
+
class BlockTracking
|
5
|
+
class << self
|
6
|
+
attr_accessor :logger
|
7
|
+
|
8
|
+
[:mask, :negative_mask].each do |method|
|
9
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
10
|
+
def #{method}
|
11
|
+
InstStatsd.settings[:#{method}]
|
12
|
+
end
|
13
|
+
|
14
|
+
def #{method}=(value)
|
15
|
+
InstStatsd.settings[:#{method}] = value
|
16
|
+
end
|
17
|
+
RUBY
|
18
|
+
end
|
19
|
+
|
20
|
+
def track(key, category: nil, statsd: InstStatsd::Statsd, only: nil)
|
21
|
+
return yield if mask && mask !~ key
|
22
|
+
return yield if negative_mask && negative_mask =~ key
|
23
|
+
|
24
|
+
cookies = if only
|
25
|
+
Array(only).map { |name| [name, Counter.counters[name].start] }
|
26
|
+
else
|
27
|
+
Counter.counters.map { |(name, counter)| [name, counter.start] }
|
28
|
+
end
|
29
|
+
block_stat = InstStatsd::BlockStat.new(key, statsd)
|
30
|
+
stack(category).push(block_stat) if category
|
31
|
+
|
32
|
+
result = nil
|
33
|
+
elapsed = Benchmark.realtime do
|
34
|
+
result = yield
|
35
|
+
end
|
36
|
+
# to be consistent with ActionPack, measure in milliseconds
|
37
|
+
elapsed *= 1000
|
38
|
+
|
39
|
+
block_stat.stats = cookies.map { |(name, cookie)| [name, Counter.counters[name].finalize_count(cookie)] }.to_h
|
40
|
+
block_stat.stats['total'] = elapsed
|
41
|
+
# we need to make sure to report exclusive timings, even if nobody called us re-entrantly
|
42
|
+
block_stat.subtract_exclusives({}) if category
|
43
|
+
block_stat.report
|
44
|
+
logger.log(block_stat, "STATSD #{key}") if logger
|
45
|
+
# -1 is ourselves; we want to subtract from the block above us
|
46
|
+
stack(category)[-2].subtract_exclusives(block_stat.stats) if category && stack(category)[-2]
|
47
|
+
|
48
|
+
result
|
49
|
+
ensure
|
50
|
+
stack(category).pop if category && stack(category).last == block_stat
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def stack(category)
|
56
|
+
Thread.current[:stats_block_stack] ||= {}
|
57
|
+
Thread.current[:stats_block_stack][category] ||= []
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class Counter
|
3
|
+
class << self
|
4
|
+
def counters
|
5
|
+
@counters ||= {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def register(counter)
|
9
|
+
counters[counter.key] = counter
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :key
|
14
|
+
attr_reader :blocked_names
|
15
|
+
|
16
|
+
def initialize(key, blocked_names=[])
|
17
|
+
@blocked_names = blocked_names
|
18
|
+
@key = key
|
19
|
+
@tls_key = "statsd.#{key}"
|
20
|
+
self.class.register(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
Thread.current[@tls_key] ||= 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def track(name)
|
28
|
+
Thread.current[@tls_key] += 1 if Thread.current[@tls_key] && accepted_name?(name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def finalize_count(cookie)
|
32
|
+
Thread.current[@tls_key] - cookie
|
33
|
+
end
|
34
|
+
|
35
|
+
def count
|
36
|
+
Thread.current[@tls_key]
|
37
|
+
end
|
38
|
+
|
39
|
+
def accepted_name?(name)
|
40
|
+
!blocked_names.include?(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "active_support"
|
2
|
+
|
3
|
+
module InstStatsd
|
4
|
+
class DefaultTracking
|
5
|
+
def self.track_sql
|
6
|
+
return if @sql_tracker
|
7
|
+
@sql_tracker = InstStatsd::SqlTracker.new(blocked_names: ['SCHEMA'])
|
8
|
+
ActiveSupport::Notifications.subscribe(/sql\.active_record/) {|*args| update_sql_count(*args)}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.track_active_record
|
12
|
+
return if @ar_counter
|
13
|
+
require 'aroi'
|
14
|
+
|
15
|
+
::Aroi::Instrumentation.instrument_creation!
|
16
|
+
@ar_counter = InstStatsd::Counter.new('active_record')
|
17
|
+
ActiveSupport::Notifications.subscribe(/instance\.active_record/) {|*args| update_active_record_count(*args)}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.track_cache
|
21
|
+
return if @cache_read_counter
|
22
|
+
|
23
|
+
@cache_read_counter = InstStatsd::Counter.new('cache.read')
|
24
|
+
ActiveSupport::Notifications.subscribe(/cache_read\.active_support/) {|*args| update_cache_read_count(*args)}
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.update_sql_count(_name, _start, _finish, _id, payload)
|
30
|
+
@sql_tracker.track payload.fetch(:name), payload.fetch(:sql)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.update_active_record_count(_name, _start, _finish, _id, payload)
|
34
|
+
@ar_counter.track payload.fetch(:name, '')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.update_cache_read_count(_name, _start, _finish, _id, _payload)
|
38
|
+
@cache_read_counter.track "read"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class RequestLogger
|
3
|
+
|
4
|
+
def initialize(logger)
|
5
|
+
@logger = logger || InstStatsd::NullLogger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def log(request_stat, header=nil)
|
9
|
+
@logger.info(build_log_message(request_stat, header))
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_log_message(request_stat, header=nil)
|
13
|
+
header ||= "STATSD"
|
14
|
+
message = "[#{header}]"
|
15
|
+
request_stat.stats.each do |(name, value)|
|
16
|
+
message += " (#{name.to_s.gsub('.', '_')}: #{"%.2f" % value})"
|
17
|
+
end
|
18
|
+
request_stat.exclusive_stats&.each do |(name, value)|
|
19
|
+
message += " (exclusive_#{name.to_s.gsub('.', '_')}: #{"%.2f" % value})"
|
20
|
+
end
|
21
|
+
message
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class RequestStat < BlockStat
|
3
|
+
def initialize(name, start, finish, id, payload, statsd=InstStatsd::Statsd)
|
4
|
+
super(nil, statsd)
|
5
|
+
@name = name
|
6
|
+
@start = start
|
7
|
+
@finish = finish
|
8
|
+
@id = id
|
9
|
+
@payload = payload
|
10
|
+
end
|
11
|
+
|
12
|
+
def common_key
|
13
|
+
common_key = super
|
14
|
+
return common_key if common_key
|
15
|
+
self.common_key = "request.#{controller}.#{action}" if controller && action
|
16
|
+
end
|
17
|
+
|
18
|
+
def report
|
19
|
+
stats['total'] = total
|
20
|
+
stats['view'] = view_runtime if view_runtime
|
21
|
+
stats['db'] = db_runtime if db_runtime
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def db_runtime
|
26
|
+
@payload.fetch(:db_runtime, nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def view_runtime
|
30
|
+
@payload.fetch(:view_runtime, nil)
|
31
|
+
end
|
32
|
+
|
33
|
+
def controller
|
34
|
+
@payload.fetch(:params, {})['controller']
|
35
|
+
end
|
36
|
+
|
37
|
+
def action
|
38
|
+
@payload.fetch(:params, {})['action']
|
39
|
+
end
|
40
|
+
|
41
|
+
def total
|
42
|
+
if (!@finish || !@start)
|
43
|
+
return 0
|
44
|
+
end
|
45
|
+
(@finish - @start) * 1000
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class RequestTracking
|
3
|
+
|
4
|
+
def self.enable(logger: nil)
|
5
|
+
@logger = RequestLogger.new(logger)
|
6
|
+
track_timing
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def self.track_timing
|
12
|
+
ActiveSupport::Notifications.subscribe(/start_processing\.action_controller/, &method(:start_processing))
|
13
|
+
ActiveSupport::Notifications.subscribe(/process_action\.action_controller/, &method(:finalize_processing))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.start_processing(*_args)
|
17
|
+
@cookies = Counter.counters.map { |(name, counter)| [name, counter.start] }
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.finalize_processing *args
|
21
|
+
request_stat = InstStatsd::RequestStat.new(*args)
|
22
|
+
request_stat.stats = @cookies.map { |(name, cookie)| [name, Counter.counters[name].finalize_count(cookie)] }.to_h
|
23
|
+
request_stat.report
|
24
|
+
@logger.log(request_stat)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module InstStatsd
|
2
|
+
class SqlTracker
|
3
|
+
|
4
|
+
attr_reader :blocked_names, :read_counts, :write_counts, :cache_counts
|
5
|
+
|
6
|
+
def initialize(opts=nil)
|
7
|
+
opts ||= {}
|
8
|
+
@blocked_names = opts.fetch(:blocked_names, [])
|
9
|
+
@read_counts = opts.fetch(:read_counter, InstStatsd::Counter.new('sql.read'))
|
10
|
+
@write_counts = opts.fetch(:write_counter, InstStatsd::Counter.new('sql.write'))
|
11
|
+
@cache_counts = opts.fetch(:cache_counter, InstStatsd::Counter.new('sql.cache'))
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
[read_counts, write_counts, cache_counts].map(&:start)
|
16
|
+
end
|
17
|
+
|
18
|
+
def track name, sql
|
19
|
+
return unless sql && accepted_name?(name)
|
20
|
+
|
21
|
+
if name.match(/CACHE/)
|
22
|
+
cache_counts.track name
|
23
|
+
elsif truncate(sql).match(/SELECT/) || name.match(/LOAD/)
|
24
|
+
read_counts.track(sql)
|
25
|
+
else
|
26
|
+
write_counts.track(sql)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def finalize_counts(cookies)
|
31
|
+
[
|
32
|
+
read_counts.finalize_count(cookies[0]),
|
33
|
+
write_counts.finalize_count(cookies[1]),
|
34
|
+
cache_counts.finalize_count(cookies[2])
|
35
|
+
]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def accepted_name?(name)
|
41
|
+
!!(name && !blocked_names.include?(name))
|
42
|
+
end
|
43
|
+
|
44
|
+
def truncate(sql, length=15)
|
45
|
+
sql ||= ''
|
46
|
+
sql.strip[0..length]
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# Proxy class to communicate messages to statsd
|
2
|
+
# Available statsd messages are described in:
|
3
|
+
# https://github.com/etsy/statsd/blob/master/README.md
|
4
|
+
# https://github.com/reinh/statsd/blob/master/lib/statsd.rb
|
5
|
+
#
|
6
|
+
# So for instance:
|
7
|
+
# ms = Benchmark.ms { ..code.. }
|
8
|
+
# InstStatsd::Statsd.timing("my_stat", ms)
|
9
|
+
#
|
10
|
+
# Configured in config/statsd.yml, see config/statsd.yml.example
|
11
|
+
# At least a host needs to be defined for the environment, all other config is optional
|
12
|
+
#
|
13
|
+
# If a namespace is defined in statsd.yml, it'll be prepended to the stat name.
|
14
|
+
# The hostname of the server will be appended to the stat name, unless `append_hostname: false` is specified in the config.
|
15
|
+
# So if the namespace is "canvas" and the hostname is "app01", the final stat name of "my_stat" would be "stats.canvas.my_stat.app01"
|
16
|
+
# (assuming the default statsd/graphite configuration)
|
17
|
+
#
|
18
|
+
# If statsd isn't configured and enabled, then calls to InstStatsd::Statsd.* will do nothing and return nil
|
19
|
+
|
20
|
+
module InstStatsd
|
21
|
+
module Statsd
|
22
|
+
# replace "." in key names with another character to avoid creating spurious sub-folders in graphite
|
23
|
+
def self.escape(str, replacement = '_')
|
24
|
+
str.respond_to?(:gsub) ? str.gsub('.', replacement) : str
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.hostname
|
28
|
+
@hostname ||= Socket.gethostname.split('.').first
|
29
|
+
end
|
30
|
+
|
31
|
+
%w[increment decrement count gauge timing].each do |method|
|
32
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
33
|
+
def self.#{method}(stat, *args)
|
34
|
+
if self.instance
|
35
|
+
if Array === stat
|
36
|
+
stat.each do |st|
|
37
|
+
self.#{method}(st, *args)
|
38
|
+
end
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
if self.append_hostname?
|
43
|
+
stat_name = "\#{stat}.\#{hostname}"
|
44
|
+
else
|
45
|
+
stat_name = stat.to_s
|
46
|
+
end
|
47
|
+
self.instance.#{method}(stat_name, *args)
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
RUBY
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.time(stat, sample_rate = 1)
|
56
|
+
start = Time.now
|
57
|
+
result = yield
|
58
|
+
timing(stat, ((Time.now - start) * 1000).round, sample_rate)
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.batch
|
63
|
+
return yield unless (old_instance = instance)
|
64
|
+
old_instance.batch do |batch|
|
65
|
+
Thread.current[:inst_statsd] = batch
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
ensure
|
69
|
+
Thread.current[:inst_statsd] = old_instance
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.instance
|
73
|
+
thread_statsd = Thread.current[:inst_statsd]
|
74
|
+
return thread_statsd if thread_statsd
|
75
|
+
|
76
|
+
unless defined?(@statsd)
|
77
|
+
statsd_settings = InstStatsd.settings
|
78
|
+
|
79
|
+
if statsd_settings && statsd_settings[:host]
|
80
|
+
@statsd = ::Statsd.new(statsd_settings[:host])
|
81
|
+
@statsd.port = statsd_settings[:port] if statsd_settings[:port]
|
82
|
+
@statsd.namespace = statsd_settings[:namespace] if statsd_settings[:namespace]
|
83
|
+
@statsd.batch_size = statsd_settings[:batch_size] if statsd_settings.key?(:batch_size)
|
84
|
+
@statsd.batch_byte_size = statsd_settings[:batch_byte_size] if statsd_settings.key?(:batch_byte_size)
|
85
|
+
@append_hostname = !statsd_settings.key?(:append_hostname) || !!statsd_settings[:append_hostname]
|
86
|
+
else
|
87
|
+
@statsd = nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
@statsd
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.append_hostname?
|
94
|
+
@append_hostname
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.reset_instance
|
98
|
+
remove_instance_variable(:@statsd) if defined?(@statsd)
|
99
|
+
Thread.current[:inst_statsd] = nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|