custom-prometheus-client 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 59513bdd6f293705f4f34c864ba6406d0fa9522d
4
+ data.tar.gz: a5f20ee8c59ff151cec16de150afff6924669fc9
5
+ SHA512:
6
+ metadata.gz: c2f628acc7b16dbfe82db00b854705a8a20d53660d6e03e295afe5373284656b404852234ab209b40e895bcecfcc2534bf6f29609767026d77d32a8f7c8f97d7
7
+ data.tar.gz: da87469693d2646d160927edb6a928530a1f57cfb7bb4f5aafb79bdf4058dc162f450b7f15738a3558dfbd982e8ae12d81b83deba3400d8cdaafc0a55e2396b4
data/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # Custom Prometheus Ruby Client
2
+
3
+ This repo is essentially a fork of https://github.com/prometheus/client_ruby and adds the following behaviour to the captured metrics.
4
+
5
+ - It takes the service_name as an options to the rake middleware (see usage)
6
+ - It adds the following labels to the metrics
7
+ * User Agent
8
+ * Accept
9
+ * Content Type
10
+
11
+ ## Usage
12
+ Add the following to your Gemfile
13
+ ```
14
+ gem 'custom-prometheus-client'
15
+ ```
16
+
17
+ Then in your config.ru add the following (Change 'my_app' to the name of your app being monitored)
18
+ ```
19
+ require 'prometheus/client/rack/collector'
20
+ require 'prometheus/client/rack/exporter'
21
+
22
+ options = { service_name: 'my_app'}
23
+ use Prometheus::Client::Rack::Collector, options
24
+ use Prometheus::Client::Rack::Exporter
25
+ ```
26
+
27
+ Configure your prometheus.yml to scrape /metrics from rails service
data/lib/prometheus.rb ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+
3
+ # Prometheus is a generic time-series collection and computation server.
4
+ module Prometheus
5
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'prometheus/client/registry'
4
+
5
+ module Prometheus
6
+ # Client is a ruby implementation for a Prometheus compatible client.
7
+ module Client
8
+ # Returns a default registry object
9
+ def self.registry
10
+ @registry ||= Registry.new
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'prometheus/client/metric'
4
+
5
+ module Prometheus
6
+ module Client
7
+ # Counter is a metric that exposes merely a sum or tally of things.
8
+ class Counter < Metric
9
+ def type
10
+ :counter
11
+ end
12
+
13
+ def increment(labels = {}, by = 1)
14
+ fail ArgumentError, 'increment must be a non-negative number' if by < 0
15
+
16
+ label_set = label_set_for(labels)
17
+ synchronize { @values[label_set] += by }
18
+ end
19
+
20
+ private
21
+
22
+ def default
23
+ 0
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'json'
4
+
5
+ module Prometheus
6
+ module Client
7
+ module Formats
8
+ # JSON format is a deprecated, human-readable format to expose the state
9
+ # of a given registry.
10
+ module JSON
11
+ MEDIA_TYPE = 'application/json'
12
+ SCHEMA = 'prometheus/telemetry'
13
+ VERSION = '0.0.2'
14
+ CONTENT_TYPE = %(#{MEDIA_TYPE}; schema="#{SCHEMA}"; version=#{VERSION})
15
+
16
+ MAPPING = { summary: :histogram }
17
+
18
+ def self.marshal(registry)
19
+ registry.metrics.map do |metric|
20
+ {
21
+ baseLabels: metric.base_labels.merge(__name__: metric.name),
22
+ docstring: metric.docstring,
23
+ metric: {
24
+ type: MAPPING[metric.type] || metric.type,
25
+ value: metric.values.map { |l, v| { labels: l, value: v } },
26
+ },
27
+ }
28
+ end.to_json
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: UTF-8
2
+
3
+ module Prometheus
4
+ module Client
5
+ module Formats
6
+ # Text format is human readable mainly used for manual inspection.
7
+ module Text
8
+ MEDIA_TYPE = 'text/plain'
9
+ VERSION = '0.0.4'
10
+ CONTENT_TYPE = "#{MEDIA_TYPE}; version=#{VERSION}"
11
+
12
+ METRIC_LINE = '%s%s %s'
13
+ TYPE_LINE = '# TYPE %s %s'
14
+ HELP_LINE = '# HELP %s %s'
15
+
16
+ LABEL = '%s="%s"'
17
+ SEPARATOR = ','
18
+ DELIMITER = "\n"
19
+
20
+ REGEX = { doc: /[\n\\]/, label: /[\n\\"]/ }
21
+ REPLACE = { "\n" => '\n', '\\' => '\\\\', '"' => '\"' }
22
+
23
+ def self.marshal(registry)
24
+ lines = []
25
+
26
+ registry.metrics.each do |metric|
27
+ lines << format(TYPE_LINE, metric.name, metric.type)
28
+ lines << format(HELP_LINE, metric.name, escape(metric.docstring))
29
+
30
+ metric.values.each do |label_set, value|
31
+ representation(metric, label_set, value) { |l| lines << l }
32
+ end
33
+ end
34
+
35
+ # there must be a trailing delimiter
36
+ (lines << nil).join(DELIMITER)
37
+ end
38
+
39
+ private
40
+
41
+ def self.representation(metric, label_set, value, &block)
42
+ set = metric.base_labels.merge(label_set)
43
+
44
+ if metric.type == :summary
45
+ summary(metric.name, set, value, &block)
46
+ else
47
+ yield metric(metric.name, labels(set), value)
48
+ end
49
+ end
50
+
51
+ def self.summary(name, set, value)
52
+ value.each do |q, v|
53
+ yield metric(name, labels(set.merge(quantile: q)), v)
54
+ end
55
+
56
+ l = labels(set)
57
+ yield metric("#{name}_sum", l, value.sum)
58
+ yield metric("#{name}_count", l, value.total)
59
+ end
60
+
61
+ def self.metric(name, labels, value)
62
+ format(METRIC_LINE, name, labels, value)
63
+ end
64
+
65
+ def self.labels(set)
66
+ return if set.empty?
67
+
68
+ strings = set.each_with_object([]) do |(key, value), memo|
69
+ memo << format(LABEL, key, escape(value, :label))
70
+ end
71
+
72
+ "{#{strings.join(SEPARATOR)}}"
73
+ end
74
+
75
+ def self.escape(string, format = :doc)
76
+ string.to_s.gsub(REGEX[format], REPLACE)
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'prometheus/client/metric'
4
+
5
+ module Prometheus
6
+ module Client
7
+ # A Gauge is a metric that exposes merely an instantaneous value or some
8
+ # snapshot thereof.
9
+ class Gauge < Metric
10
+ def type
11
+ :gauge
12
+ end
13
+
14
+ # Sets the value for the given label set
15
+ def set(labels, value)
16
+ @values[label_set_for(labels)] = value
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+
3
+ module Prometheus
4
+ module Client
5
+ # LabelSetValidator ensures that all used label sets comply with the
6
+ # Prometheus specification.
7
+ class LabelSetValidator
8
+ # TODO: we might allow setting :instance in the future
9
+ RESERVED_LABELS = [:job, :instance]
10
+
11
+ class LabelSetError < StandardError; end
12
+ class InvalidLabelSetError < LabelSetError; end
13
+ class InvalidLabelError < LabelSetError; end
14
+ class ReservedLabelError < LabelSetError; end
15
+
16
+ def initialize
17
+ @validated = {}
18
+ end
19
+
20
+ def valid?(labels)
21
+ unless labels.respond_to?(:all?)
22
+ fail InvalidLabelSetError, "#{labels} is not a valid label set"
23
+ end
24
+
25
+ labels.all? do |key, _|
26
+ validate_symbol(key)
27
+ validate_name(key)
28
+ validate_reserved_key(key)
29
+ end
30
+ end
31
+
32
+ def validate(labels)
33
+ return labels if @validated.key?(labels.hash)
34
+
35
+ valid?(labels)
36
+
37
+ unless @validated.empty? || match?(labels, @validated.first.last)
38
+ fail InvalidLabelSetError, 'labels must have the same signature'
39
+ end
40
+
41
+ @validated[labels.hash] = labels
42
+ end
43
+
44
+ private
45
+
46
+ def match?(a, b)
47
+ a.keys.sort == b.keys.sort
48
+ end
49
+
50
+ def validate_symbol(key)
51
+ return true if key.is_a?(Symbol)
52
+
53
+ fail InvalidLabelError, "label #{key} is not a symbol"
54
+ end
55
+
56
+ def validate_name(key)
57
+ return true unless key.to_s.start_with?('__')
58
+
59
+ fail ReservedLabelError, "label #{key} must not start with __"
60
+ end
61
+
62
+ def validate_reserved_key(key)
63
+ return true unless RESERVED_LABELS.include?(key)
64
+
65
+ fail ReservedLabelError, "#{key} is reserved"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'thread'
4
+ require 'prometheus/client/label_set_validator'
5
+
6
+ module Prometheus
7
+ module Client
8
+ # Metric
9
+ class Metric
10
+ attr_reader :name, :docstring, :base_labels
11
+
12
+ def initialize(name, docstring, base_labels = {})
13
+ @mutex = Mutex.new
14
+ @validator = LabelSetValidator.new
15
+ @values = Hash.new { |hash, key| hash[key] = default }
16
+
17
+ validate_name(name)
18
+ validate_docstring(docstring)
19
+ @validator.valid?(base_labels)
20
+
21
+ @name = name
22
+ @docstring = docstring
23
+ @base_labels = base_labels
24
+ end
25
+
26
+ # Returns the metric type
27
+ def type
28
+ fail NotImplementedError
29
+ end
30
+
31
+ # Returns the value for the given label set
32
+ def get(labels = {})
33
+ @validator.valid?(labels)
34
+
35
+ @values[labels]
36
+ end
37
+
38
+ # Returns all label sets with their values
39
+ def values
40
+ synchronize do
41
+ @values.each_with_object({}) do |(labels, value), memo|
42
+ memo[labels] = value
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def default
50
+ nil
51
+ end
52
+
53
+ def validate_name(name)
54
+ return true if name.is_a?(Symbol)
55
+
56
+ fail ArgumentError, 'given name must be a symbol'
57
+ end
58
+
59
+ def validate_docstring(docstring)
60
+ return true if docstring.respond_to?(:empty?) && !docstring.empty?
61
+
62
+ fail ArgumentError, 'docstring must be given'
63
+ end
64
+
65
+ def label_set_for(labels)
66
+ @validator.validate(labels)
67
+ end
68
+
69
+ def synchronize(&block)
70
+ @mutex.synchronize(&block)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,68 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+
6
+ require 'prometheus/client'
7
+ require 'prometheus/client/formats/text'
8
+
9
+ module Prometheus
10
+ # Client is a ruby implementation for a Prometheus compatible client.
11
+ module Client
12
+ # Push implements a simple way to transmit a given registry to a given
13
+ # Pushgateway.
14
+ class Push
15
+ DEFAULT_GATEWAY = 'http://localhost:9091'
16
+ PATH = '/metrics/jobs/%s'
17
+ INSTANCE_PATH = '/metrics/jobs/%s/instances/%s'
18
+ HEADER = { 'Content-Type' => Formats::Text::CONTENT_TYPE }
19
+
20
+ attr_reader :job, :instance, :gateway, :path
21
+
22
+ def initialize(job, instance = nil, gateway = nil)
23
+ @job = job
24
+ @instance = instance
25
+ @gateway = gateway || DEFAULT_GATEWAY
26
+ @uri = parse(@gateway)
27
+ @path = build_path(job, instance)
28
+ @http = Net::HTTP.new(@uri.host, @uri.port)
29
+ end
30
+
31
+ def add(registry)
32
+ request('POST', registry)
33
+ end
34
+
35
+ def replace(registry)
36
+ request('PUT', registry)
37
+ end
38
+
39
+ private
40
+
41
+ def parse(url)
42
+ uri = URI.parse(url)
43
+
44
+ if uri.scheme == 'http'
45
+ uri
46
+ else
47
+ fail ArgumentError, 'only HTTP gateway URLs are supported currently.'
48
+ end
49
+ rescue URI::InvalidURIError => e
50
+ raise ArgumentError, "#{url} is not a valid URL: #{e}"
51
+ end
52
+
53
+ def build_path(job, instance)
54
+ if instance
55
+ format(INSTANCE_PATH, URI.escape(job), URI.escape(instance))
56
+ else
57
+ format(PATH, URI.escape(job))
58
+ end
59
+ end
60
+
61
+ def request(method, registry)
62
+ data = Formats::Text.marshal(registry)
63
+
64
+ @http.send_request(method, path, data, HEADER)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'prometheus/client'
4
+
5
+ module Prometheus
6
+ module Client
7
+ module Rack
8
+ # Collector is a Rack middleware that provides a sample implementation of
9
+ # a HTTP tracer. The default label builder can be modified to export a
10
+ # different set of labels per recorded metric.
11
+ class Collector
12
+ attr_reader :app, :registry
13
+
14
+ def initialize(app, options = {}, &label_builder)
15
+ @app = app
16
+ @registry = options[:registry] || Client.registry
17
+ @label_builder = label_builder || DEFAULT_LABEL_BUILDER
18
+ # The service name should be read from config or could be git repo name
19
+ @service_name = options[:service_name]
20
+ init_request_metrics
21
+ init_exception_metrics
22
+ end
23
+
24
+ def call(env) # :nodoc:
25
+ trace(env) { @app.call(env) }
26
+ end
27
+
28
+ protected
29
+
30
+ DEFAULT_LABEL_BUILDER = proc do |env|
31
+ {
32
+ method: env['REQUEST_METHOD'].downcase,
33
+ ua: env['HTTP_USER_AGENT'].to_s,
34
+ accept: env['HTTP_ACCEPT'],
35
+ host: env['HTTP_HOST'].to_s,
36
+ path: env['PATH_INFO'].to_s,
37
+ content_type: env['CONTENT_TYPE'].to_s
38
+ }
39
+ end
40
+
41
+ def init_request_metrics
42
+ @request_metrics = @service_name + "__counter_requests_total"
43
+ @response_metrics = @service_name + "__counter_responses_total"
44
+ @response_time_metrics = @service_name + "__summary_responses_duration_microseconds"
45
+
46
+ @requests = @registry.counter(
47
+ @request_metrics.to_sym,
48
+ 'Total number of HTTP requests.')
49
+ @requests_duration = @registry.counter(
50
+ @response_metrics.to_sym,
51
+ 'Total time spent answering HTTP requests ' \
52
+ '(microseconds).')
53
+ @durations = @registry.summary(
54
+ @response_time_metrics.to_sym,
55
+ 'A histogram of the response latency (microseconds).')
56
+ end
57
+
58
+ def init_exception_metrics
59
+ @exceptions = @registry.counter(
60
+ :http_exceptions_total,
61
+ 'A counter of the total number of exceptions raised.')
62
+ end
63
+
64
+ def trace(env)
65
+ start = Time.now
66
+ yield.tap do |response|
67
+ duration = ((Time.now - start) * 1_000_000).to_i
68
+ record(labels(env, response), duration)
69
+ end
70
+ rescue => exception
71
+ @exceptions.increment(exception: exception.class.name)
72
+ raise
73
+ end
74
+
75
+ def labels(env, response)
76
+ @label_builder.call(env).tap do |labels|
77
+ labels[:code] = response.first.to_s
78
+ end
79
+ end
80
+
81
+ def record(labels, duration)
82
+ @requests.increment(labels)
83
+ @requests_duration.increment(labels, duration)
84
+ @durations.add(labels, duration)
85
+ rescue
86
+ # TODO: log unexpected exception during request recording
87
+ nil
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'prometheus/client'
4
+ require 'prometheus/client/formats/json'
5
+ require 'prometheus/client/formats/text'
6
+
7
+ module Prometheus
8
+ module Client
9
+ module Rack
10
+ # Exporter is a Rack middleware that provides a sample implementation of
11
+ # a Prometheus HTTP client API.
12
+ class Exporter
13
+ attr_reader :app, :registry, :path
14
+
15
+ FORMATS = [Formats::Text, Formats::JSON]
16
+ FALLBACK = Formats::JSON
17
+
18
+ def initialize(app, options = {})
19
+ @app = app
20
+ @registry = options[:registry] || Client.registry
21
+ @path = options[:path] || '/metrics'
22
+ @acceptable = build_dictionary(FORMATS, FALLBACK)
23
+ end
24
+
25
+ def call(env)
26
+ if env['PATH_INFO'] == @path
27
+ format = negotiate(env['HTTP_ACCEPT'], @acceptable)
28
+ format ? respond_with(format) : not_acceptable(FORMATS)
29
+ else
30
+ @app.call(env)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def negotiate(accept, formats)
37
+ accept = '*/*' if accept.to_s.empty?
38
+
39
+ parse(accept).each do |content_type, _|
40
+ return formats[content_type] if formats.key?(content_type)
41
+ end
42
+
43
+ nil
44
+ end
45
+
46
+ def parse(header)
47
+ header.to_s.split(/\s*,\s*/).map do |type|
48
+ attributes = type.split(/\s*;\s*/)
49
+ quality = extract_quality(attributes)
50
+
51
+ [attributes.join('; '), quality]
52
+ end.sort_by(&:last).reverse
53
+ end
54
+
55
+ def extract_quality(attributes, default = 1.0)
56
+ quality = default
57
+
58
+ attributes.delete_if do |attr|
59
+ quality = attr.split('q=').last.to_f if attr.start_with?('q=')
60
+ end
61
+
62
+ quality
63
+ end
64
+
65
+ def respond_with(format)
66
+ [
67
+ 200,
68
+ { 'Content-Type' => format::CONTENT_TYPE },
69
+ [format.marshal(@registry)],
70
+ ]
71
+ end
72
+
73
+ def not_acceptable(formats)
74
+ types = formats.map { |format| format::MEDIA_TYPE }
75
+
76
+ [
77
+ 406,
78
+ { 'Content-Type' => 'text/plain' },
79
+ ["Supported media types: #{types.join(', ')}"],
80
+ ]
81
+ end
82
+
83
+ def build_dictionary(formats, fallback)
84
+ formats.each_with_object('*/*' => fallback) do |format, memo|
85
+ memo[format::CONTENT_TYPE] = format
86
+ memo[format::MEDIA_TYPE] = format
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'thread'
4
+
5
+ require 'prometheus/client/counter'
6
+ require 'prometheus/client/summary'
7
+ require 'prometheus/client/gauge'
8
+
9
+ module Prometheus
10
+ module Client
11
+ # Registry
12
+ class Registry
13
+ class AlreadyRegisteredError < StandardError; end
14
+
15
+ def initialize
16
+ @metrics = {}
17
+ @mutex = Mutex.new
18
+ end
19
+
20
+ def register(metric)
21
+ name = metric.name
22
+
23
+ @mutex.synchronize do
24
+ if exist?(name.to_sym)
25
+ fail AlreadyRegisteredError, "#{name} has already been registered"
26
+ else
27
+ @metrics[name.to_sym] = metric
28
+ end
29
+ end
30
+
31
+ metric
32
+ end
33
+
34
+ def counter(name, docstring, base_labels = {})
35
+ register(Counter.new(name, docstring, base_labels))
36
+ end
37
+
38
+ def summary(name, docstring, base_labels = {})
39
+ register(Summary.new(name, docstring, base_labels))
40
+ end
41
+
42
+ def gauge(name, docstring, base_labels = {})
43
+ register(Gauge.new(name, docstring, base_labels))
44
+ end
45
+
46
+ def exist?(name)
47
+ @metrics.key?(name)
48
+ end
49
+
50
+ def get(name)
51
+ @metrics[name.to_sym]
52
+ end
53
+
54
+ def metrics
55
+ @metrics.values
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'quantile'
4
+ require 'prometheus/client/metric'
5
+
6
+ module Prometheus
7
+ module Client
8
+ # Summary is an accumulator for samples. It captures Numeric data and
9
+ # provides an efficient quantile calculation mechanism.
10
+ class Summary < Metric
11
+ # Value represents the state of a Summary at a given point.
12
+ class Value < Hash
13
+ attr_accessor :sum, :total
14
+
15
+ def initialize(estimator)
16
+ @sum = estimator.sum
17
+ @total = estimator.observations
18
+
19
+ estimator.invariants.each do |invariant|
20
+ self[invariant.quantile] = estimator.query(invariant.quantile)
21
+ end
22
+ end
23
+ end
24
+
25
+ def type
26
+ :summary
27
+ end
28
+
29
+ # Records a given value.
30
+ def add(labels, value)
31
+ label_set = label_set_for(labels)
32
+ synchronize { @values[label_set].observe(value) }
33
+ end
34
+
35
+ # Returns the value for the given label set
36
+ def get(labels = {})
37
+ @validator.valid?(labels)
38
+
39
+ synchronize do
40
+ Value.new(@values[labels])
41
+ end
42
+ end
43
+
44
+ # Returns all label sets with their values
45
+ def values
46
+ synchronize do
47
+ @values.each_with_object({}) do |(labels, value), memo|
48
+ memo[labels] = Value.new(value)
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def default
56
+ Quantile::Estimator.new
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ module Prometheus
4
+ module Client
5
+ VERSION = '0.4.3'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: custom-prometheus-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.3
5
+ platform: ruby
6
+ authors:
7
+ - Shah Bagdadi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-10-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: quantile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.0
27
+ description:
28
+ email:
29
+ - email.shanu@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - lib/prometheus.rb
36
+ - lib/prometheus/client.rb
37
+ - lib/prometheus/client/counter.rb
38
+ - lib/prometheus/client/formats/json.rb
39
+ - lib/prometheus/client/formats/text.rb
40
+ - lib/prometheus/client/gauge.rb
41
+ - lib/prometheus/client/label_set_validator.rb
42
+ - lib/prometheus/client/metric.rb
43
+ - lib/prometheus/client/push.rb
44
+ - lib/prometheus/client/rack/collector.rb
45
+ - lib/prometheus/client/rack/exporter.rb
46
+ - lib/prometheus/client/registry.rb
47
+ - lib/prometheus/client/summary.rb
48
+ - lib/prometheus/client/version.rb
49
+ homepage: https://github.com/prometheus/client_ruby
50
+ licenses:
51
+ - Apache 2.0
52
+ metadata: {}
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 2.4.8
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: A suite of instrumentation metric primitivesthat can be exposed through a
73
+ web services interface.
74
+ test_files: []