lookout-statsd 1.0.0 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +14 -0
- data/README.md +22 -1
- data/lib/statsd.rb +114 -5
- data/spec/statsd_spec.rb +57 -1
- data/statsd.gemspec +1 -1
- metadata +4 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 09edd7854e30fe524a21a82dd325487e96c83a3b
         | 
| 4 | 
            +
              data.tar.gz: f7d047db68333414a84ec0bbdce59f0fcde041b1
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 53190cf6ac482c34bde75b18f727f1b74904a5ef1bb837c3299e487bea532d164114a9625c5185254379c6a97ef8fec794d83e3fab89e0a10d4068e87909f0bd
         | 
| 7 | 
            +
              data.tar.gz: 36d9ce3ed7906da7d80226d9978a03873fe9502744eb234a3a73adbfe81af75ba159694c174566d5b75e3264014161ebbe13d08428dcf9aa1749a7441668bf5a
         | 
    
        data/.travis.yml
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            language: ruby
         | 
| 2 | 
            +
            rvm:
         | 
| 3 | 
            +
            - jruby
         | 
| 4 | 
            +
            - 2.1
         | 
| 5 | 
            +
            - 1.9.3
         | 
| 6 | 
            +
            deploy:
         | 
| 7 | 
            +
              provider: rubygems
         | 
| 8 | 
            +
              api_key: 701b3f137a894afa3dca9390da8b3afe
         | 
| 9 | 
            +
              gem: lookout-statsd
         | 
| 10 | 
            +
              on:
         | 
| 11 | 
            +
                repo: lookout/statsd
         | 
| 12 | 
            +
            install:
         | 
| 13 | 
            +
            - gem install bundler
         | 
| 14 | 
            +
            - bundle install --jobs=3 --retry=3
         | 
    
        data/README.md
    CHANGED
    
    | @@ -11,7 +11,7 @@ In your client code: | |
| 11 11 |  | 
| 12 12 | 
             
                require 'rubygems'
         | 
| 13 13 | 
             
                require 'statsd'
         | 
| 14 | 
            -
                STATSD = Statsd::Client.new('localhost',8125)
         | 
| 14 | 
            +
                STATSD = Statsd::Client.new(:host => 'localhost', :port => 8125)
         | 
| 15 15 |  | 
| 16 16 | 
             
                STATSD.increment('some_counter') # basic incrementing
         | 
| 17 17 | 
             
                STATSD.increment('system.nested_counter', 0.1) # incrementing with sampling (10%)
         | 
| @@ -22,6 +22,27 @@ In your client code: | |
| 22 22 | 
             
                STATSD.timing('some_job_time', 20) # reporting job that took 20ms
         | 
| 23 23 | 
             
                STATSD.timing('some_job_time', 20, 0.05) # reporting job that took 20ms with sampling (5% sampling)
         | 
| 24 24 |  | 
| 25 | 
            +
            There is an option for reduced DNS lookups, you can specify an additional
         | 
| 26 | 
            +
            constructor option `:resolve_always` and set it to `false`. By default, the
         | 
| 27 | 
            +
            client will always resolve the address unless `host` is set to 'localhost' or
         | 
| 28 | 
            +
            '127.0.0.1'.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                require 'rubygems'
         | 
| 31 | 
            +
                require 'statsd'
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                STATSD = Statsd::Client.new(:host => 'specialstats.host.example',
         | 
| 34 | 
            +
                                            :port => '8125',
         | 
| 35 | 
            +
                                            :resolve_always => false)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                STATSD.increment('some_counter') # basic incrementing
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            #### Note about thread-safety
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            Since class variables and instance variables are not thread-safe on
         | 
| 42 | 
            +
            initialization, there is a potential for multiple UDP sockets being opened upon
         | 
| 43 | 
            +
            if you are using a truly multithreaded ruby, i.e. JRuby. Make sure to take that
         | 
| 44 | 
            +
            in to account when initializing this library.
         | 
| 45 | 
            +
             | 
| 25 46 | 
             
            Guts
         | 
| 26 47 | 
             
            ----
         | 
| 27 48 |  | 
    
        data/lib/statsd.rb
    CHANGED
    
    | @@ -15,12 +15,17 @@ module Statsd | |
| 15 15 | 
             
              end
         | 
| 16 16 |  | 
| 17 17 | 
             
              class Client
         | 
| 18 | 
            -
                attr_accessor :host, :port, :prefix
         | 
| 18 | 
            +
                attr_accessor :host, :port, :prefix, :resolve_always, :batch_size
         | 
| 19 19 |  | 
| 20 20 | 
             
                def initialize(opts={})
         | 
| 21 21 | 
             
                  @host = opts[:host] || 'localhost'
         | 
| 22 22 | 
             
                  @port = opts[:port] || 8125
         | 
| 23 | 
            +
                  @batch_size = opts[:batch_size] || 10
         | 
| 23 24 | 
             
                  @prefix = opts[:prefix]
         | 
| 25 | 
            +
                  # set resolve_always to true unless localhost or specified
         | 
| 26 | 
            +
                  @resolve_always = opts.fetch(:resolve_always, !is_localhost?)
         | 
| 27 | 
            +
                  @socket = UDPSocket.new
         | 
| 28 | 
            +
                  @send_data = send_method
         | 
| 24 29 | 
             
                end
         | 
| 25 30 |  | 
| 26 31 | 
             
                def host_ip_addr
         | 
| @@ -77,6 +82,22 @@ module Statsd | |
| 77 82 | 
             
                             })
         | 
| 78 83 | 
             
                end
         | 
| 79 84 |  | 
| 85 | 
            +
                # Creates and yields a Batch that can be used to batch instrument reports into
         | 
| 86 | 
            +
                # larger packets. Batches are sent either when the packet is "full" (defined
         | 
| 87 | 
            +
                # by batch_size), or when the block completes, whichever is the sooner.
         | 
| 88 | 
            +
                #
         | 
| 89 | 
            +
                # Good artists copy https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
         | 
| 90 | 
            +
                #
         | 
| 91 | 
            +
                # @yield [Batch] a statsd subclass that collects and batches instruments
         | 
| 92 | 
            +
                # @example Batch two instument operations:
         | 
| 93 | 
            +
                #   $statsd.batch do |batch|
         | 
| 94 | 
            +
                #     batch.increment 'sys.requests'
         | 
| 95 | 
            +
                #     batch.gauge('user.count', User.count)
         | 
| 96 | 
            +
                #   end
         | 
| 97 | 
            +
                def batch(&block)
         | 
| 98 | 
            +
                  Batch.new(self).easy(&block)
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 80 101 | 
             
                private
         | 
| 81 102 |  | 
| 82 103 | 
             
                def send_stats(data, sample_rate = 1)
         | 
| @@ -98,17 +119,105 @@ module Statsd | |
| 98 119 | 
             
                  raise "host and port must be set" unless host && port
         | 
| 99 120 |  | 
| 100 121 | 
             
                  begin
         | 
| 101 | 
            -
                    sock = UDPSocket.new
         | 
| 102 122 | 
             
                    data.each do |d|
         | 
| 103 | 
            -
                       | 
| 123 | 
            +
                      @send_data[d]
         | 
| 104 124 | 
             
                    end
         | 
| 105 125 | 
             
                  rescue # silent but deadly
         | 
| 106 | 
            -
                  ensure
         | 
| 107 | 
            -
                    sock.close
         | 
| 108 126 | 
             
                  end
         | 
| 109 127 | 
             
                  true
         | 
| 110 128 | 
             
                end
         | 
| 111 129 |  | 
| 130 | 
            +
                def socket_connect!
         | 
| 131 | 
            +
                  @socket.connect(@host, @port)
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                # Curries the send based on if we need to lookup dns every time we send
         | 
| 135 | 
            +
                def send_method
         | 
| 136 | 
            +
                  if resolve_always
         | 
| 137 | 
            +
                    lambda {|data| @socket.send(data, 0, @host, @port)}
         | 
| 138 | 
            +
                  else
         | 
| 139 | 
            +
                    socket_connect!
         | 
| 140 | 
            +
                    lambda {|data| @socket.send(data, 0)}
         | 
| 141 | 
            +
                  end
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                def is_localhost?
         | 
| 145 | 
            +
                  @host == 'localhost' || @host == '127.0.0.1'
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
              end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
              # Some more unabashed borrowing: https://github.com/reinh/statsd/blob/master/lib/statsd.rb#L410
         | 
| 150 | 
            +
              # The big difference between this implementation and reinh's is that we don't support namespaces,
         | 
| 151 | 
            +
              # and we have a bunch of hacks for introducing prefixes to the namespaces we're acting against.
         | 
| 152 | 
            +
              # = Batch: A batching statsd proxy
         | 
| 153 | 
            +
              #
         | 
| 154 | 
            +
              # @example Batch a set of instruments using Batch and manual flush:
         | 
| 155 | 
            +
              #   $statsd = Statsd.new 'localhost', 8125
         | 
| 156 | 
            +
              #   batch = Statsd::Batch.new($statsd)
         | 
| 157 | 
            +
              #   batch.increment 'garets'
         | 
| 158 | 
            +
              #   batch.timing 'glork', 320
         | 
| 159 | 
            +
              #   batch.gauge 'bork', 100
         | 
| 160 | 
            +
              #   batch.flush
         | 
| 161 | 
            +
              #
         | 
| 162 | 
            +
              # Batch is a subclass of Statsd, but with a constructor that proxies to a
         | 
| 163 | 
            +
              # normal Statsd instance. It has it's own batch_size parameters
         | 
| 164 | 
            +
              # (that inherit defaults from the supplied Statsd instance). It is recommended
         | 
| 165 | 
            +
              # that some care is taken if setting very large batch sizes. If the batch size
         | 
| 166 | 
            +
              # exceeds the allowed packet size for UDP on your network, communication
         | 
| 167 | 
            +
              # troubles may occur and data will be lost.
         | 
| 168 | 
            +
              class Batch < Statsd::Client
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                extend Forwardable
         | 
| 171 | 
            +
                def_delegators :@statsd,
         | 
| 172 | 
            +
                               :host, :host=,
         | 
| 173 | 
            +
                               :port, :port=,
         | 
| 174 | 
            +
                               :prefix,
         | 
| 175 | 
            +
                               :postfix,
         | 
| 176 | 
            +
                               :delimiter, :delimiter=
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                attr_accessor :batch_size
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                # @param [Statsd] requires a configured Statsd instance
         | 
| 181 | 
            +
                def initialize(statsd)
         | 
| 182 | 
            +
                  @statsd = statsd
         | 
| 183 | 
            +
                  @batch_size = statsd.batch_size
         | 
| 184 | 
            +
                  @backlog = []
         | 
| 185 | 
            +
                  @send_data = send_method
         | 
| 186 | 
            +
                end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                # @yields [Batch] yields itself
         | 
| 189 | 
            +
                #
         | 
| 190 | 
            +
                # A convenience method to ensure that data is not lost in the event of an
         | 
| 191 | 
            +
                # exception being thrown. Batches will be transmitted on the parent socket
         | 
| 192 | 
            +
                # as soon as the batch is full, and when the block finishes.
         | 
| 193 | 
            +
                def easy
         | 
| 194 | 
            +
                  yield self
         | 
| 195 | 
            +
                ensure
         | 
| 196 | 
            +
                  flush
         | 
| 197 | 
            +
                end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                def flush
         | 
| 200 | 
            +
                  unless @backlog.empty?
         | 
| 201 | 
            +
                    @statsd.send_data @backlog.join("\n")
         | 
| 202 | 
            +
                    @backlog.clear
         | 
| 203 | 
            +
                  end
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                def send_batch_data(message)
         | 
| 207 | 
            +
                  @backlog << message
         | 
| 208 | 
            +
                  if @backlog.size >= @batch_size
         | 
| 209 | 
            +
                    flush
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
                end
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                def send_method
         | 
| 214 | 
            +
                  lambda { |data|
         | 
| 215 | 
            +
                    @backlog << data
         | 
| 216 | 
            +
                    if @backlog.size >= @batch_size
         | 
| 217 | 
            +
                      flush
         | 
| 218 | 
            +
                    end
         | 
| 219 | 
            +
                  }
         | 
| 220 | 
            +
                end
         | 
| 112 221 | 
             
              end
         | 
| 113 222 |  | 
| 114 223 | 
             
              module Rails
         | 
    
        data/spec/statsd_spec.rb
    CHANGED
    
    | @@ -55,6 +55,48 @@ describe Statsd::Client do | |
| 55 55 | 
             
                  c = Statsd::Client.new(:prefix => prefix)
         | 
| 56 56 | 
             
                  c.prefix.should match(prefix)
         | 
| 57 57 | 
             
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                it 'should accept a :resolve_always keyword argument' do
         | 
| 60 | 
            +
                  lookup = false
         | 
| 61 | 
            +
                  c = Statsd::Client.new(:resolve_always => lookup)
         | 
| 62 | 
            +
                  c.resolve_always.should be(lookup)
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                context 'when :resolve_always is not specified' do
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  context 'when host is localhost or 127.0.0.1' do
         | 
| 68 | 
            +
                    it ':resolve_always should default to false' do
         | 
| 69 | 
            +
                      c = Statsd::Client.new(:host => 'localhost')
         | 
| 70 | 
            +
                      c.resolve_always.should be(false)
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  context 'when host is not local' do
         | 
| 75 | 
            +
                    it ':resolve_always should default to true' do
         | 
| 76 | 
            +
                      c = Statsd::Client.new(:host => 'statsd.example.example')
         | 
| 77 | 
            +
                      c.resolve_always.should be(true)
         | 
| 78 | 
            +
                    end
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              describe '#send_stats' do
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                it 'should use cached resolve address when :resolve_always is false' do
         | 
| 88 | 
            +
                  c = Statsd::Client.new(:resolve_always => false)
         | 
| 89 | 
            +
                  sock = c.instance_variable_get(:@socket)
         | 
| 90 | 
            +
                  expect(sock).to receive(:send).with(anything, 0)
         | 
| 91 | 
            +
                  c.increment('foo')
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                it 'should always resolve address when :resolve_always is true' do
         | 
| 95 | 
            +
                  c = Statsd::Client.new(:resolve_always => true)
         | 
| 96 | 
            +
                  sock = c.instance_variable_get(:@socket)
         | 
| 97 | 
            +
                  expect(sock).to receive(:send).with(anything, 0, c.host, c.port)
         | 
| 98 | 
            +
                  c.increment('foo')
         | 
| 99 | 
            +
                end
         | 
| 58 100 | 
             
              end
         | 
| 59 101 |  | 
| 60 102 | 
             
              describe '#timing' do
         | 
| @@ -148,4 +190,18 @@ describe Statsd::Client do | |
| 148 190 | 
             
                  c.gauge('foo' => 1)
         | 
| 149 191 | 
             
                end
         | 
| 150 192 | 
             
              end
         | 
| 151 | 
            -
             | 
| 193 | 
            +
             | 
| 194 | 
            +
              describe '#batch' do
         | 
| 195 | 
            +
                let(:c) { Statsd::Client.new }
         | 
| 196 | 
            +
                subject { c.batch { |b| b.increment('foo'); b.increment('bar'); } }
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                it 'should take a block and put increments into a buffer' do
         | 
| 199 | 
            +
                  Statsd::Batch.any_instance do |b|
         | 
| 200 | 
            +
                    b.backlog.should_receive(:<<).exactly.twice
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
                  Statsd::Batch.any_instance.should_receive(:flush).and_call_original
         | 
| 203 | 
            +
                  c.should_receive(:send_data).once
         | 
| 204 | 
            +
                  subject
         | 
| 205 | 
            +
                end
         | 
| 206 | 
            +
              end
         | 
| 207 | 
            +
            end
         | 
    
        data/statsd.gemspec
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: lookout-statsd
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 2.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - R. Tyler Croy
         | 
| @@ -10,7 +10,7 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date:  | 
| 13 | 
            +
            date: 2016-05-16 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies: []
         | 
| 15 15 | 
             
            description: A simple ruby statsd client.
         | 
| 16 16 | 
             
            email:
         | 
| @@ -20,6 +20,7 @@ extensions: [] | |
| 20 20 | 
             
            extra_rdoc_files: []
         | 
| 21 21 | 
             
            files:
         | 
| 22 22 | 
             
            - ".gitignore"
         | 
| 23 | 
            +
            - ".travis.yml"
         | 
| 23 24 | 
             
            - Gemfile
         | 
| 24 25 | 
             
            - Guardfile
         | 
| 25 26 | 
             
            - README.md
         | 
| @@ -50,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 50 51 | 
             
                  version: 1.3.6
         | 
| 51 52 | 
             
            requirements: []
         | 
| 52 53 | 
             
            rubyforge_project: 
         | 
| 53 | 
            -
            rubygems_version: 2.4. | 
| 54 | 
            +
            rubygems_version: 2.4.6
         | 
| 54 55 | 
             
            signing_key: 
         | 
| 55 56 | 
             
            specification_version: 4
         | 
| 56 57 | 
             
            summary: Ruby statsd client.
         |