fiveruns-dash-ruby 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -8,11 +8,11 @@ You'll need a Dash account before using this library.
8
8
 
9
9
  This library is released as a gem from the official repository at http://github.com/fiveruns/dash-ruby
10
10
 
11
- sudo gem install fiveruns-dash-ruby --source 'http://gems.github.com'
11
+ sudo gem install fiveruns-dash-ruby --source http://gems.github.com
12
12
 
13
13
  == Usage
14
14
 
15
- See the Ruby Language Guide http://dash.fiveruns.com/help/ruby.html for information on how to use this library.
15
+ See the Ruby support pages, http://support.fiveruns.com/faqs/dash/ruby, for information on how to use this library.
16
16
 
17
17
  == Authors
18
18
 
@@ -38,7 +38,7 @@ The best way to contribute is by sending pull requests via GitHub. The official
38
38
 
39
39
  Please join the dash-users Google group, http://groups.google.com/group/dash-users
40
40
 
41
- You can also contact us via Twitter, Campfire, or email; see the main help page, http://dash.fiveruns.com/help, for details.
41
+ You can also contact us via Twitter, Campfire, or email; see the main help page, http://support.fiveruns.com, for details.
42
42
 
43
43
  == License
44
44
 
@@ -4,7 +4,9 @@ module Fiveruns::Dash
4
4
 
5
5
  class ConflictError < ::ArgumentError; end
6
6
 
7
- delegate :each, :to => :metrics
7
+ def each(&block)
8
+ metrics.each(&block)
9
+ end
8
10
 
9
11
  def self.default_options
10
12
  ::Fiveruns::Dash.logger.info "CWD::#{Dir.pwd.inspect}"
@@ -77,9 +77,9 @@ module Fiveruns
77
77
  end
78
78
 
79
79
  def data
80
- returning exceptions.dup do
81
- reset
82
- end
80
+ duped = exceptions.dup
81
+ reset
82
+ duped
83
83
  end
84
84
 
85
85
  def reset
@@ -20,9 +20,9 @@ module Fiveruns::Dash
20
20
  begin
21
21
  obj, meth = case raw_target
22
22
  when /^(.+)#(.+)$/
23
- [$1.constantize, $2]
23
+ [Fiveruns::Dash::Util.constantize($1), $2]
24
24
  when /^(.+)(?:\.|::)(.+)$/
25
- [(class << $1.constantize; self; end), $2]
25
+ [(class << Fiveruns::Dash::Util.constantize($1); self; end), $2]
26
26
  else
27
27
  raise Error, "Bad target format: #{raw_target}"
28
28
  end
@@ -129,7 +129,7 @@ module Fiveruns::Dash
129
129
  #{yield(format % :without)}
130
130
  end
131
131
  end
132
- alias_method_chain :#{meth}, :#{feature}
132
+ Fiveruns::Dash::Util.chain(self, :#{meth}, :#{feature})
133
133
  DYNAMIC
134
134
  end
135
135
 
@@ -10,8 +10,8 @@ module Fiveruns::Dash
10
10
  def initialize(name, *args, &block)
11
11
  @@warned = false
12
12
  @name = name.to_s
13
- @options = args.extract_options!
14
- @description = args.shift || @name.titleize
13
+ @options = args.last.is_a?(Hash) ? args.pop : {}
14
+ @description = args.shift || Util.titleize(@name)
15
15
  @help_text = args.shift
16
16
  @operation = block
17
17
  @virtual = !!options[:sources]
@@ -102,17 +102,20 @@ module Fiveruns::Dash
102
102
  #######
103
103
 
104
104
  def validate!
105
- raise ArgumentError, "#{name} - Virtual metrics should have source metrics" if virtual? && options[:sources].blank?
105
+ raise ArgumentError, "'#{name}' should be between 3 and 32 characters" unless (3..32).include?(name.size)
106
+ raise ArgumentError, "'#{name}' should only contain letters, numbers and underscore" if name !~ /\A\w+\Z/
107
+
108
+ raise ArgumentError, "#{name} - Virtual metrics should have source metrics" if virtual? && Util.blank?(options[:sources])
106
109
  raise ArgumentError, "#{name} - metrics should not have source metrics" if !virtual? && options[:sources]
107
110
  end
108
111
 
109
112
  def optional_info
110
- returning({}) do |optional|
111
- copy = optional.merge(@options[:unit] ? {:unit => @options[:unit].to_s} : {})
112
- copy = copy.merge(@options[:scope] ? {:scope => @options[:scope].to_s} : {})
113
- copy = copy.merge(abstract? ? {:abstract => true} : {})
114
- optional.merge!(copy)
115
- end
113
+ optional = {}
114
+ copy = optional.merge(@options[:unit] ? {:unit => @options[:unit].to_s} : {})
115
+ copy = copy.merge(@options[:scope] ? {:scope => @options[:scope].to_s} : {})
116
+ copy = copy.merge(abstract? ? {:abstract => true} : {})
117
+ optional.merge!(copy)
118
+ optional
116
119
  end
117
120
 
118
121
  def combine(source_values)
@@ -257,9 +260,9 @@ module Fiveruns::Dash
257
260
  end
258
261
 
259
262
  def value_hash
260
- returning(:values => current_value) do
261
- reset
262
- end
263
+ values = {:values => current_value}
264
+ reset
265
+ values
263
266
  end
264
267
 
265
268
  def install_hook
@@ -276,22 +279,26 @@ module Fiveruns::Dash
276
279
  end
277
280
 
278
281
  def instrument_options
279
- returning({}) do |options|
280
- options[:reentrant_token] = self.object_id.abs if @options[:reentrant]
281
- options[:only_within] = @options[:only_within] if @options[:only_within]
282
- options[:mark_as] = @name if @options[:mark]
283
- end
282
+ options = {}
283
+ options[:reentrant_token] = self.object_id.abs if @options[:reentrant]
284
+ options[:only_within] = @options[:only_within] if @options[:only_within]
285
+ options[:mark_as] = @name if @options[:mark]
286
+ options
284
287
  end
285
288
 
286
289
  def methods_to_instrument
287
- @methods_to_instrument ||= Array(@options[:method]) + Array(@options[:methods])
290
+ @methods_to_instrument ||= begin
291
+ Array(@options[:method]) + Array(@options[:methods])
292
+ end
288
293
  end
289
294
 
290
295
  def validate!
291
296
  super
292
- raise ArgumentError, "Can not set :unit for `#{@name}' time metric" if @options[:unit]
293
- if methods_to_instrument.blank?
294
- raise ArgumentError, "Must set :method or :methods option for `#{@name}` time metric"
297
+ raise ArgumentError,
298
+ "Can not set :unit for `#{@name}' time metric" if @options[:unit]
299
+ if Util.blank?(methods_to_instrument)
300
+ raise ArgumentError,
301
+ "Must set :method or :methods option for `#{@name}` time metric"
295
302
  end
296
303
  end
297
304
 
@@ -319,17 +326,18 @@ module Fiveruns::Dash
319
326
 
320
327
  def value_hash
321
328
  if incrementing_methods.any?
322
- returning(:values => current_value) do
323
- reset
324
- end
329
+ values = {:values => current_value}
330
+ reset
331
+ values
325
332
  else
326
333
  super
327
334
  end
328
335
  end
329
336
 
330
337
  def install_hook
331
- if incrementing_methods.blank?
332
- raise RuntimeError, "Bad configuration for `#{@name}` counter metric"
338
+ if Util.blank?(incrementing_methods)
339
+ raise RuntimeError,
340
+ "Bad configuration for `#{@name}` counter metric"
333
341
  end
334
342
  @operation ||= lambda { nil }
335
343
  incrementing_methods.each do |meth|
@@ -8,7 +8,7 @@ module Fiveruns::Dash
8
8
 
9
9
  attr_accessor :interval
10
10
  attr_reader :started_at
11
- def initialize(session, interval = 60.seconds.to_i)
11
+ def initialize(session, interval = 60)
12
12
  @session = session
13
13
  @interval = interval
14
14
  end
@@ -67,6 +67,10 @@ module Fiveruns::Dash
67
67
  @thread && @thread.alive? && @thread.raise(ShutdownSignal.new)
68
68
  end
69
69
 
70
+ def secure!
71
+ @update_locations = %w(https://dash-collector.fiveruns.com https://dash-collector02.fiveruns.com)
72
+ end
73
+
70
74
  #######
71
75
  private
72
76
  #######
@@ -200,7 +204,7 @@ module Fiveruns::Dash
200
204
  end
201
205
 
202
206
  def default_update_locations
203
- %w(https://dash-collector.fiveruns.com https://dash-collector02.fiveruns.com)
207
+ %w(http://dash-collector.fiveruns.com http://dash-collector02.fiveruns.com)
204
208
  end
205
209
 
206
210
  end
@@ -52,7 +52,7 @@ module Fiveruns::Dash
52
52
 
53
53
  def reset
54
54
  exception_recorder.reset
55
- configuration.metrics.each(&:reset)
55
+ configuration.metrics.each { |m| m.reset }
56
56
  end
57
57
 
58
58
  def data
@@ -20,7 +20,7 @@ module Fiveruns::Dash::Store
20
20
  ip = resolved_hostnames[hostname].ip
21
21
  else
22
22
  ip = hostname == 'localhost' ? '127.0.0.1' : IPSocket.getaddress(hostname)
23
- ip_struct = OpenStruct.new(:ip => ip, :next_update => Time.now + 23.hours + rand(60).minutes)
23
+ ip_struct = OpenStruct.new(:ip => ip, :next_update => Time.now + (23 * 60 * 60) + (rand(60) * 60))
24
24
  resolved_hostnames[hostname] = ip_struct
25
25
  end
26
26
  ip
@@ -92,23 +92,23 @@ module Fiveruns::Dash::Store
92
92
  end
93
93
 
94
94
  def add_path_to(uri)
95
- returning uri.dup do |new_uri|
96
- path = case payload
97
- when Fiveruns::Dash::PingPayload
98
- ::File.join('/apps', app_token, "ping")
99
- when Fiveruns::Dash::InfoPayload
100
- ::File.join('/apps', app_token, "processes.json")
101
- when Fiveruns::Dash::DataPayload
102
- ::File.join('/apps', app_token, "metrics.json")
103
- when Fiveruns::Dash::TracePayload
104
- ::File.join('/apps', app_token, "traces.json")
105
- when Fiveruns::Dash::ExceptionsPayload
106
- ::File.join('/apps', app_token, "exceptions.json")
107
- else
108
- raise ArgumentError, 'Unknown payload type: #{payload.class}'
109
- end
110
- new_uri.path = path
95
+ new_uri = uri.dup
96
+ path = case payload
97
+ when Fiveruns::Dash::PingPayload
98
+ ::File.join('/apps', app_token, "ping")
99
+ when Fiveruns::Dash::InfoPayload
100
+ ::File.join('/apps', app_token, "processes.json")
101
+ when Fiveruns::Dash::DataPayload
102
+ ::File.join('/apps', app_token, "metrics.json")
103
+ when Fiveruns::Dash::TracePayload
104
+ ::File.join('/apps', app_token, "traces.json")
105
+ when Fiveruns::Dash::ExceptionsPayload
106
+ ::File.join('/apps', app_token, "exceptions.json")
107
+ else
108
+ raise ArgumentError, 'Unknown payload type: #{payload.class}'
111
109
  end
110
+ new_uri.path = path
111
+ new_uri
112
112
  end
113
113
 
114
114
  def extra_params_for(payload)
@@ -121,7 +121,7 @@ module Fiveruns::Dash::Store
121
121
  end
122
122
 
123
123
  def normalize_key(key)
124
- key.to_a.flatten.map(&:to_s).sort
124
+ key.to_a.flatten.map { |k| k.to_s }.sort
125
125
  end
126
126
 
127
127
  def app_token
@@ -130,7 +130,7 @@ module Fiveruns::Dash::Store
130
130
 
131
131
  class Multipart
132
132
 
133
- BOUNDARY_ROOT = 'B0UND~F0R~UPL0AD'
133
+ BOUNDARY_ROOT = 'B0UND'
134
134
 
135
135
  attr_reader :file, :params
136
136
  def initialize(file, params={})
@@ -3,10 +3,13 @@ module Fiveruns::Dash
3
3
  module Typable
4
4
 
5
5
  def self.included(base)
6
- name = base.name.demodulize.underscore
6
+ name = Fiveruns::Dash::Util.shortname(base.name)
7
7
  base.class_eval %{
8
8
  def self.#{name}_type
9
- @#{name}_type ||= name.demodulize.underscore.sub(/_#{name}$/, '').to_sym
9
+ @#{name}_type ||= begin
10
+ short = Fiveruns::Dash::Util.shortname(name)
11
+ short.sub(/_#{name}$/, '').to_sym
12
+ end
10
13
  end
11
14
  }
12
15
  base.extend ClassMethods
@@ -15,7 +18,7 @@ module Fiveruns::Dash
15
18
  module ClassMethods
16
19
 
17
20
  def inherited(klass)
18
- types[klass.__send__("#{name.demodulize.underscore}_type")] = klass
21
+ types[klass.__send__("#{Fiveruns::Dash::Util.shortname(name)}_type")] = klass
19
22
  end
20
23
 
21
24
  def types
@@ -97,7 +97,12 @@ module Fiveruns::Dash
97
97
  end
98
98
 
99
99
  def uris_by_scheme(urls)
100
- urls.map { |url| safe_parse(url) }.group_by(&:scheme)
100
+ safe = urls.map { |url| safe_parse(url) }
101
+ safe.inject({}) do |mapping, url|
102
+ mapping[url.scheme] ||= []
103
+ mapping[url.scheme] << url
104
+ mapping
105
+ end
101
106
  end
102
107
 
103
108
  def storage_method_for(scheme)
@@ -118,10 +123,10 @@ module Fiveruns::Dash
118
123
  end
119
124
 
120
125
  def io
121
- returning StringIO.new do |io|
122
- io.write compressed
123
- io.rewind
124
- end
126
+ io = StringIO.new
127
+ io.write compressed
128
+ io.rewind
129
+ io
125
130
  end
126
131
 
127
132
  def params
@@ -0,0 +1,70 @@
1
+ module Fiveruns::Dash
2
+
3
+ # Utility methods, largely extracted from ActiveSupport
4
+ module Util
5
+
6
+ def self.demodulize(str)
7
+ str.sub(/.*::/, '')
8
+ end
9
+
10
+ def self.shortname(str)
11
+ underscore(demodulize(str))
12
+ end
13
+
14
+ # Note: Doesn't do any fancy Inflector-style modifications
15
+ def self.titleize(str)
16
+ underscore(str.to_s).split(/[_]+/).map { |s| s.capitalize }.join(' ')
17
+ end
18
+
19
+ def self.underscore(str)
20
+ str.to_s.gsub(/::/, '/').
21
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
22
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
23
+ tr("-", "_").
24
+ downcase
25
+ end
26
+
27
+ def self.blank?(obj)
28
+ obj.respond_to?(:empty?) ? obj.empty? : !self
29
+ end
30
+
31
+ def self.constantize(str)
32
+ names = str.split('::')
33
+ names.shift if names.empty? || names.first.empty?
34
+
35
+ constant = Object
36
+ names.each do |name|
37
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
38
+ end
39
+ constant
40
+ end
41
+
42
+ # ActiveSupport's alias_method_chain (but from outside the module)
43
+ # Note: We'd love to use something other than AMC, but it's the
44
+ # most consistent wrapper we know of that doesn't require
45
+ # cooperation from the target.
46
+ def self.chain(mod, target, feature)
47
+ # Strip out punctuation on predicates or bang methods since
48
+ # e.g. target?_without_feature is not a valid method name.
49
+ aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
50
+ yield(aliased_target, punctuation) if block_given?
51
+
52
+ with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}",
53
+ "#{aliased_target}_without_#{feature}#{punctuation}"
54
+
55
+ mod.send(:alias_method, without_method, target)
56
+ mod.send(:alias_method, target, with_method)
57
+
58
+ case
59
+ when mod.public_method_defined?(without_method)
60
+ mod.instance_eval %(public :#{target})
61
+ when mod.protected_method_defined?(without_method)
62
+ mod.instance_eval %(protected :#{target})
63
+ when mod.private_method_defined?(without_method)
64
+ mod.instance_eval %(private :#{target})
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
data/lib/fiveruns/dash.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'rubygems'
2
- # TODO remove ActiveSupport dependency
3
- require 'activesupport'
4
2
  require 'json'
5
3
 
4
+ require 'pathname'
6
5
  require 'thread'
7
6
  require 'logger'
8
7
 
@@ -14,6 +13,7 @@ $:.unshift(File.dirname(__FILE__))
14
13
  module Fiveruns; end
15
14
 
16
15
  require 'dash/version'
16
+ require 'dash/util'
17
17
  require 'dash/configuration'
18
18
  require 'dash/typable'
19
19
  require 'dash/metric'
@@ -238,7 +238,7 @@ class CollectorCommunicationTest < Test::Unit::TestCase
238
238
  #######
239
239
 
240
240
  def full_urls(service)
241
- full_uris(service).map(&:to_s)
241
+ full_uris(service).map { |u| u.to_s }
242
242
  end
243
243
 
244
244
  def full_uris(service)
@@ -25,7 +25,7 @@ class ConfigurationTest < Test::Unit::TestCase
25
25
  setup do
26
26
  @configuration = Configuration.new do |config|
27
27
  metric_types.each do |type|
28
- config.__send__(type, "Metric: #{type}") do
28
+ config.__send__(type, "#{type}") do
29
29
  # Empty block for metric types that require it
30
30
  end
31
31
  end
@@ -34,7 +34,7 @@ class ConfigurationTest < Test::Unit::TestCase
34
34
  should "assign all metrics" do
35
35
  assert_equal 3, @configuration.metrics.size
36
36
  types = @configuration.metrics.map { |metric| metric.class.metric_type }
37
- assert_equal metric_types.map(&:to_s).sort, types.map(&:to_s).sort
37
+ assert_equal metric_types.map { |i| i.to_s }.sort, types.map { |i| i.to_s }.sort
38
38
  end
39
39
  should "not allow invalid types" do
40
40
  assert_raises NoMethodError do
@@ -76,7 +76,7 @@ class ConfigurationTest < Test::Unit::TestCase
76
76
  end
77
77
  should "execute if correct version" do
78
78
  assert_equal 2, @config.metrics.size
79
- assert_equal %w(bar foo), @config.metrics.map(&:name).map(&:to_s).sort
79
+ assert_equal %w(bar foo), @config.metrics.map { |m| m.name }.map { |i| i.to_s }.sort
80
80
  end
81
81
  end
82
82
 
@@ -42,7 +42,7 @@ class HTTPStoreTest < Test::Unit::TestCase
42
42
  new_uri = @update.resolved_hostname(uris.first.host)
43
43
  assert_equal new_uri, "1.1.1.1"
44
44
  assert_equal @update.resolved_hostnames.keys.size, 1
45
- assert @update.resolved_hostnames[uris.first.host].next_update > (Time.now + 23.hours)
45
+ assert @update.resolved_hostnames[uris.first.host].next_update > (Time.now + (23 * 60 * 60))
46
46
  assert_equal @update.resolved_hostname(uris.first.host), "1.1.1.1"
47
47
  junk = @update.resolved_hostname(uris.first.host)
48
48
 
@@ -54,14 +54,14 @@ class HTTPStoreTest < Test::Unit::TestCase
54
54
  assert_equal @update.resolved_hostnames.keys.size, 0
55
55
  new_uri = @update.resolved_hostname(uris.first.host)
56
56
  assert_equal new_uri, "1.1.1.1"
57
- @update.resolved_hostnames[uris.first.host].next_update = 10.hours.ago
57
+ @update.resolved_hostnames[uris.first.host].next_update = Time.now - (10 * 60 * 60)
58
58
  first_expire = @update.resolved_hostnames[uris.first.host].next_update
59
59
 
60
60
  new_uri = @update.resolved_hostname(uris.first.host)
61
61
  second_expire = @update.resolved_hostnames[uris.first.host].next_update
62
62
  assert_equal new_uri, "2.2.2.2"
63
- assert second_expire < (Time.now + 25.hours)
64
- assert second_expire > (Time.now + 23.hours)
63
+ assert second_expire < (Time.now + (25 * 60 * 60))
64
+ assert second_expire > (Time.now + (23 * 60 * 60))
65
65
  end
66
66
  end
67
67
 
@@ -83,9 +83,8 @@ class HTTPStoreTest < Test::Unit::TestCase
83
83
  end
84
84
  end
85
85
  should "fallback to working URL" do
86
- returning @update.store_http(*uris) do |pass_uri|
87
- assert_equal uris[1], pass_uri
88
- end
86
+ pass_uri = @update.store_http(*uris)
87
+ assert_equal uris[1], pass_uri
89
88
  end
90
89
  end
91
90
  context "on non-201 response" do
@@ -117,9 +116,8 @@ class HTTPStoreTest < Test::Unit::TestCase
117
116
  end
118
117
  end
119
118
  should "fallback to working URL" do
120
- returning @update.store_http(*uris) do |pass_uri|
121
- assert_equal uris[1], pass_uri
122
- end
119
+ pass_uri = @update.store_http(*uris)
120
+ assert_equal uris[1], pass_uri
123
121
  end
124
122
  end
125
123
  context "on non-201 response" do
@@ -166,9 +164,8 @@ class HTTPStoreTest < Test::Unit::TestCase
166
164
  end
167
165
  end
168
166
  should "fallback to working URL" do
169
- returning @update.store_http(*uris) do |pass_uri|
170
- assert_equal uris[1], pass_uri
171
- end
167
+ pass_uri = @update.store_http(*uris)
168
+ assert_equal uris[1], pass_uri
172
169
  end
173
170
  end
174
171
  context "on non-201 response" do
@@ -192,7 +189,7 @@ class HTTPStoreTest < Test::Unit::TestCase
192
189
  #######
193
190
 
194
191
  def full_urls(service)
195
- full_uris(service).map(&:to_s)
192
+ full_uris(service).map { |u| u.to_s }
196
193
  end
197
194
 
198
195
  def full_uris(service)
data/test/recipe_test.rb CHANGED
@@ -136,7 +136,8 @@ class RecipeTest < Test::Unit::TestCase
136
136
  #######
137
137
 
138
138
  def assert_metrics(*names)
139
- assert_equal names.sort, config.metrics.map(&:name).map(&:to_s).sort
139
+ assert_equal names.sort,
140
+ config.metrics.map { |m| m.name }.map { |m| m.to_s }.sort
140
141
  end
141
142
 
142
143
  def recipe(name = :test, options = {:url => 'http://test.com'}, &block)
data/test/test_helper.rb CHANGED
@@ -5,10 +5,15 @@ begin
5
5
  require 'shoulda'
6
6
  require 'flexmock/test_unit'
7
7
  require 'fake_web'
8
- rescue
8
+ rescue LoadError
9
9
  puts "Please install the Shoulda, FakeWeb and flexmock gems to run the Dash plugin tests."
10
10
  end
11
11
 
12
+ begin
13
+ require 'redgreen'
14
+ rescue LoadError
15
+ end
16
+
12
17
  $:.unshift(File.dirname(__FILE__) << '/../lib')
13
18
  # Require library files
14
19
  require 'fiveruns/dash'
data/version.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 7
4
- :patch: 6
3
+ :minor: 8
4
+ :patch: 0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiveruns-dash-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.6
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - FiveRuns Development Team
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-11 00:00:00 -08:00
12
+ date: 2009-02-16 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -51,6 +52,7 @@ files:
51
52
  - lib/fiveruns/dash/trace.rb
52
53
  - lib/fiveruns/dash/typable.rb
53
54
  - lib/fiveruns/dash/update.rb
55
+ - lib/fiveruns/dash/util.rb
54
56
  - lib/fiveruns/dash/version.rb
55
57
  - lib/fiveruns/dash.rb
56
58
  - test/collector_communication_test.rb