File: registry.rb

package info (click to toggle)
ruby-metriks 0.9.9.8-3.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 288 kB
  • sloc: ruby: 1,877; makefile: 2
file content (207 lines) | stat: -rw-r--r-- 5,442 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
require 'metriks/counter'
require 'metriks/timer'
require 'metriks/utilization_timer'
require 'metriks/meter'
require 'metriks/gauge'

module Metriks
  # Public: A collection of metrics
  class Registry
    # Public: The default registry for the process.
    #
    # Returns the default Registry for the process.
    def self.default
      @default ||= new
    end

    # Public: Initializes a new Registry.
    def initialize
      @mutex = Mutex.new
      @metrics = {}
    end

    # Public: Clear all of the metrics in the Registry. This ensures all
    # metrics that have been added are stopped.
    #
    # Returns nothing.
    def clear
      @mutex.synchronize do
        @metrics.each do |key, metric|
          metric.stop if metric.respond_to?(:stop)
        end

        @metrics = {}
      end
    end

    # Public: Clear all of the metrics in the Registry. This has the same
    # effect as calling #clear.
    #
    # Returns nothing.
    def stop
      clear
    end

    # Public: Iterate over all of the counters.
    #
    # Examples
    #
    #   registry.each do |name, metric|
    #     puts name
    #   end
    #
    # Returns nothing.
    def each(&block)
      metrics = @mutex.synchronize do
        @metrics.dup
      end

      metrics.each(&block)
    end

    # Public: Fetch or create a new counter metric. Counters are one of the
    # simplest metrics whose only operations are increment and decrement.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.counter('method.calls')
    #
    # Returns the Metriks::Counter identified by the name.
    def counter(name)
      add_or_get(name, Metriks::Counter)
    end

    # Public: Fetch or create a new gauge metric.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.gauge('disk_space.used') { 1 }
    #
    # Returns the Metriks::Gauge identified by the name.
    def gauge(name, callable = nil, &block)
      add_or_get(name, Metriks::Gauge) do
        Metriks::Gauge.new(callable, &block)
      end
    end

    # Public: Fetch or create a new meter metric. Meters are a counter that
    # tracks throughput along with the count.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.meter('resque.calls')
    #
    # Returns the Metriks::Meter identified by the name.
    def meter(name)
      add_or_get(name, Metriks::Meter)
    end

    # Public: Fetch or create a new timer metric. Timers provide the means to
    # time the execution of a method including statistics on the number of
    # invocations, average length of time, throughput.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.timer('resque.worker')
    #
    # Returns the Metriks::Timer identified by the name.
    def timer(name)
      add_or_get(name, Metriks::Timer)
    end

    # Public: Fetch or create a new utilization timer metric.
    #
    # Utilization timers are a specialized version of a timer that calculate
    # the percentage of wall-clock time (between 0 and 1) that was spent in
    # the method. This metric is most valuable in a single-threaded
    # environment where a processes is waiting on an external resource like a
    # message queue or HTTP server.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.utilization_timer('rack.utilization')
    #
    # Returns the Metriks::UtilizationTimer identified by the name.
    def utilization_timer(name)
      add_or_get(name, Metriks::UtilizationTimer)
    end

    # Public: Fetch or create a new histogram metric. Histograms record values
    # and expose statistics about the distribution of the data like median and
    # 95th percentile.
    #
    # name - The String name of the metric to define or fetch
    #
    # Examples
    #
    #   registry.histogram('backlog.wait')
    #
    # Returns the Metriks::Histogram identified by the name.
    def histogram(name)
      add_or_get(name, Metriks::Histogram) do
        Metriks::Histogram.new_exponentially_decaying
      end
    end

    # Public: Fetch an existing metric.
    #
    # name - The String name of the metric to fetch
    #
    # Examples
    #
    #   registry.get('rack.utilization')
    #
    # Returns the metric or nil.
    def get(name)
      @mutex.synchronize do
        @metrics[name]
      end
    end

    # Public: Add a new metric.
    #
    # name - The String name of the metric to add
    # metric - The metric instance to add
    #
    # Examples
    #
    #   registry.add('method.calls', Metriks::Counter.new)
    #
    # Returns nothing.
    # Raises RuntimeError if the metric name is already defined
    def add(name, metric)
      @mutex.synchronize do
        if @metrics[name]
          raise "Metric '#{name}' already defined"
        else
          @metrics[name] = metric
        end
      end
    end

    protected
    def add_or_get(name, klass, &create_metric)
      @mutex.synchronize do
        if metric = @metrics[name]
          if !metric.is_a?(klass)
            raise "Metric already defined as '#{metric.class}'"
          else
            return metric
          end
        else
          @metrics[name] = create_metric ? create_metric.call : klass.new
        end
      end
    end
  end
end