g5_prom_rails 0.1.0

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: 9b989ca4a0078f71ac841968d0856eee42d502b3
4
+ data.tar.gz: f3b202a9f269331b49a22451115929e456ba5dff
5
+ SHA512:
6
+ metadata.gz: 45635669ba0ee1ec30a31c16103e2bd8363ea088405cb8e91e4811c6ee14d717c148324412d76c2bcdb947da9c9f8745966bd277b83eccfe462b890cfe8f91f8
7
+ data.tar.gz: 8f07da93804aa4cb94cde9f4317e041e9a70ef435135c2a753211c44e705c9f4433afc8aec88c58405262810f29a33bf50272998252379516cbe9000388cbcd1
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Don Petersen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,145 @@
1
+ # G5 Prom Rails
2
+
3
+ This gem provides a rails engine that provides very basic help in integrating Prometheus into your Rails app. It brings in Prometheus Exporter middleware, initializes a metrics registry, and can add metrics for common use-cases and Rails gems.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'g5_prom_rails'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ The engine brings in the `prometheus-client` ruby gem. It is well-documented, and `g5_prom_rails` doesn't insulate you from how that gem works. You should [read its documentation](https://github.com/prometheus/client_ruby) to understand what metric types are available to you and how to update them. Registries and metrics endpoints are configured for you.
21
+
22
+ This gem is designed to work when Prometheus scrapes both individual instances of Rails (horizontally scaled processes) and the application as a whole. Application-level metrics are those that are shared between every Rails process, like database model counts or background job queue sizes. Per-process metrics are instrumented events that hit individual processes, like a particular controller action being called. Prometheus deals with aggregating events that happen in multiple disconnected processes, like load balanced Rails web servers.
23
+
24
+ ## Configuration
25
+
26
+ There are a few configuration points for the engine, which you should specify in an initializer. Here's an example of a simple recommended setup:
27
+
28
+ **`config/initializers/metrics.rb`**
29
+ ```ruby
30
+ METRICS = Metrics.new
31
+
32
+ G5PromRails.initialize_per_application = -> (registry) {
33
+ METRICS.initialize_per_application(registry)
34
+ }
35
+
36
+ G5PromRails.initialize_per_application = -> (registry) {
37
+ METRICS.initialize_per_process(registry)
38
+ }
39
+
40
+ G5PromRails.add_refresh_hook do
41
+ METRICS.published_posts.set({}, Post.where(published: true).count)
42
+ end
43
+ ```
44
+
45
+ **`lib/metrics.rb`**
46
+ ```ruby
47
+ class Metrics
48
+ attr_reader :published_posts, :post_shares
49
+
50
+ def initialize_per_application(registry)
51
+ @published_posts = registry.gauge(:my_app_posts, "published blog posts")
52
+ end
53
+
54
+ def initialize_per_application(registry)
55
+ @post_shares = registry.counter(:my_app_post_shares, "blog post shares")
56
+ end
57
+ end
58
+ ```
59
+
60
+ **`app/controllers/posts_controller.rb`**
61
+ ```ruby
62
+ class PostsController < ApplicationController
63
+ def share
64
+ METRICS.post_shares.increment
65
+ # ... a bunch of important business logic
66
+ end
67
+ end
68
+ ```
69
+
70
+ There are a few things going on here. In the initializer, you have hooks to initialize new metric types depending on their scope. Each lambda is passed a Prometheus registry instance, which is where you attach the metric types. They are safe for concurrent access, and the individual metric instances you're instantiating are the objects you'll be interacting with in your code when you want to instrument something.
71
+
72
+ The `Metrics` class is part of your codebase, and this structure is only a recommendation. I'm suggesting that fewer global variables are easier to deal with, but you could reimplement what I've done here with multiple globals and keep it all within your initializer (except the controller instrumentation).
73
+
74
+ We're instrumenting two things in this example: the number of Posts in the database, and the number of times any Post was shared.
75
+
76
+ Post count hits the database, and no matter which process you asked, the answer would be the same. You do *not* want to ask every process individually as it would generate pointless database queries and multiple copies of the same data.
77
+
78
+ Share count is per-process. With a load balancer and scaled web processes, different instances of your application might serve the request to share a blog post. You increment a counter in your controller code, and Prometheus deals with aggregating the differing values for this metric from each process.
79
+
80
+ An additional wrinkle is the `add_refresh_hook` in the initializer. This is a hook to update your metrics when the application-level metrics endpoint is hit. For a metric like database row counts, this is the easiest place to make sure the metrics up-to-date before you provide them to Prometheus. Because this hook is called every time the endpoint is hit, you should avoid any extremely strenuous queries, as it will be called at Prometheus's regular scrape interval.
81
+
82
+ ## Warnings
83
+
84
+ There are a couple of general Prometheus tips things to keep in mind.
85
+
86
+ * Namespace your metrics. If you named a metric `users`, that's the name of the metric for every other user of your Prometheus server. You should name it `your_app_users`. This engine does not force namespaces on you, because it's possible you'll want to aggregate metrics across multiple applications.
87
+ * Read [the official Prometheus guidelines on metric naming](https://prometheus.io/docs/practices/naming/). It's short and extremely helpful.
88
+ * Did you see the big warning at the end of the naming guidelines? Labels in Prometheus are extremely powerful; I encourage you to use them, but don't abuse them. A new time series database is created for every combination of label values. Feel free to use a label that could have dozens of possible values, for instance in your blog post counter to differentiate drafts from published articles. Do *not* use `author_id` as a label to count posts by author. *Especially* do not use multiple labels that could have many possible values, because the effect on the total number of time series databases is multiplicative.
89
+
90
+ ## App Name
91
+
92
+ As you will soon learn, G5PromRails can provide you with some automatic metrics. Most of them are scoped to your application's name. It will attempt to infer the application's name from the Rails Application class's (`config/application.rb`) dasherized parent module name. If that doesn't work for you, it can be manually defined with:
93
+
94
+ ```ruby
95
+ G5PromRails.app_name = "my_app_name"
96
+ ```
97
+
98
+ ## Sidekiq
99
+
100
+ Prometheus's strategy is to scrape metrics. If you take a moment to think about it, we have a problem: how do you scrape in-memory metrics from a Sidekiq worker? That process doesn't start a web server.
101
+
102
+ Well, it does now. If you have Sidekiq and the process is a worker, it will start a thread with a simple Rack server that only serves metric. By default this will run on port 3000, but it can be configured with:
103
+
104
+ ```ruby
105
+ G5PromRails.sidekiq_scrape_server_port = 3001
106
+ ```
107
+
108
+ If your application includes Sidekiq, G5PromRails will detect it and include several metrics using Sidekiq's built-in statistics classes. It also adds a benchmarking middleware to the Sidekiq server middleware chain.
109
+
110
+ Metrics include:
111
+
112
+ * *`sidekiq_processed`* Counter for jobs processed.
113
+ * *`sidekiq_failed`* Counter for jobs failed.
114
+ * *`sidekiq_retry`* Gauge for current retries length.
115
+ * *`sidekiq_queued`* Gauge for current queue length. The label `queue` is applied to allow per-queue analysis.
116
+ * *`sidekiq_job_seconds`*,*`sidekiq_job_seconds_sum`*,*`sidekiq_job_seconds_count`* Histogram for job execution time. The label `job_name` is applied, and will be identical to the Ruby class name of the job (e.g. `MyImportantWorker`). To understand how to use this data, look at [the official documentation](https://prometheus.io/docs/practices/histograms/). See particularly the section about aggregation.
117
+
118
+ Each metric also has the `app` label applied with the name of your application.
119
+
120
+ ## Helpers
121
+
122
+ There are some common instrumentation tasks that this gem can help you with.
123
+
124
+ #### Row Counts
125
+
126
+ When you'd like to instrument the count of certain ActiveRecord models, in an initializer you can:
127
+
128
+ ```ruby
129
+ G5PromRails.count_models(:my_app, Post, Comment)
130
+ ```
131
+
132
+ Will result in a gauge metric named `model_rows` with a `model` label set to the tableized name of your model and an `app` label set to the `my_app`. In PromQL this will look like:
133
+ ```promql
134
+ model_rows{model="posts", app="my_app"}
135
+ ```
136
+
137
+ This metric is left un-namespaced because it gives you the ability to compare these values across applications, while still allowing them to be limited to a single app via PromQL. The values will automatically be refreshed when the application-level metrics endpoint is hit.
138
+
139
+ ## Development
140
+
141
+ To run this engine's tests, you need redis running. Sorry. You need to do some finagling to get Sidekiq using fakeredis, and I didn't feel like spending the time on it. I'm using Sidekiq::Stats, which isn't part of any of sidekiq's normal testing setup.
142
+
143
+ ## License
144
+
145
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'G5PromRails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/g5_prom_rails .js
2
+ //= link_directory ../stylesheets/g5_prom_rails .css
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ module G5PromRails
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module G5PromRails
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module G5PromRails
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module G5PromRails
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module G5PromRails
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>G5 prom rails</title>
5
+ <%= stylesheet_link_tag "g5_prom_rails/application", media: "all" %>
6
+ <%= javascript_include_tag "g5_prom_rails/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ G5PromRails::Engine.routes.draw do
2
+ end
@@ -0,0 +1,26 @@
1
+ require "g5_prom_rails/engine"
2
+
3
+ module G5PromRails
4
+ PER_PROCESS_PATH = "/metrics"
5
+ PER_APPLICATION_PATH = "/probe"
6
+
7
+ cattr_accessor :app_name
8
+ cattr_accessor :initialize_per_application, :initialize_per_process
9
+ cattr_accessor :sidekiq_scrape_server_port
10
+
11
+ def self.add_refresh_hook(&block)
12
+ @@refresh_hooks ||= []
13
+ @@refresh_hooks << block
14
+ end
15
+
16
+ def self.refresh_gauges
17
+ return if @@refresh_hooks.nil?
18
+ @@refresh_hooks.each { |b| b.call }
19
+ end
20
+
21
+ def self.count_models(*models)
22
+ add_refresh_hook do
23
+ Metrics.update_model_count_gauge(*models)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,90 @@
1
+ require 'prometheus/client/rack/exporter'
2
+ require_relative 'metrics'
3
+ require_relative 'refreshing_exporter'
4
+ require_relative 'settable_counter'
5
+ require_relative 'sidekiq_timing_middleware'
6
+
7
+ module G5PromRails
8
+ class Engine < ::Rails::Engine
9
+ isolate_namespace G5PromRails
10
+
11
+ config.generators do |g|
12
+ g.test_framework :rspec
13
+ end
14
+
15
+ initializer "g5_prom_rails.configure_global" do |app|
16
+ app_name = G5PromRails.app_name || app.class.parent_name.underscore.dasherize
17
+ G5PromRails::Metrics = MetricsContainer.new(app_name)
18
+
19
+ if G5PromRails.initialize_per_application.present?
20
+ G5PromRails::Metrics.per_application.instance_eval(
21
+ &G5PromRails.initialize_per_application
22
+ )
23
+ end
24
+
25
+ if G5PromRails.initialize_per_process.present?
26
+ G5PromRails::Metrics.per_process.instance_eval(
27
+ &G5PromRails.initialize_per_process
28
+ )
29
+ end
30
+ end
31
+
32
+ initializer "g5_prom_rails.add_exporter" do |app|
33
+ Prometheus::Client::Rack::Exporter.send(
34
+ :prepend,
35
+ G5PromRails::RefreshingExporter
36
+ )
37
+
38
+ per_application_opts = {
39
+ path: G5PromRails::PER_APPLICATION_PATH,
40
+ registry: G5PromRails::Metrics.per_application
41
+ }
42
+ per_process_opts = {
43
+ path: G5PromRails::PER_PROCESS_PATH,
44
+ registry: G5PromRails::Metrics.per_process
45
+ }
46
+
47
+ # has sidekiq and is a worker
48
+ if defined?(Sidekiq) && Sidekiq.server?.present?
49
+ app = Rack::Builder.new do
50
+ use Rack::ShowExceptions
51
+ use Rack::Lint
52
+ use Prometheus::Client::Rack::Exporter, per_process_opts
53
+ run -> { [ '404', {}, ["Not Found"] ] }
54
+ end
55
+
56
+ Thread.new do
57
+ Rails.logger.info("started g5_prom_rails metrics endpoint...")
58
+ Rack::Server.start(
59
+ app: app,
60
+ Port: (G5PromRails.sidekiq_scrape_server_port || 3000),
61
+ )
62
+ end
63
+ else
64
+ app.middleware.use(Prometheus::Client::Rack::Exporter, per_process_opts)
65
+ app.middleware.use(Prometheus::Client::Rack::Exporter, per_application_opts)
66
+ end
67
+ end
68
+
69
+ initializer "g5_prom_rails.maybe_configure_sidekiq" do |app|
70
+ if defined?(Sidekiq)
71
+ G5PromRails.add_refresh_hook do
72
+ Metrics.update_sidekiq_statistics
73
+ end
74
+
75
+ timing_metric = G5PromRails::SidekiqTimingMiddleware.build_metric(
76
+ G5PromRails::Metrics.per_process
77
+ )
78
+ Sidekiq.configure_server do |config|
79
+ config.server_middleware do |chain|
80
+ chain.add(
81
+ G5PromRails::SidekiqTimingMiddleware,
82
+ app: G5PromRails::Metrics.app,
83
+ metric: timing_metric
84
+ )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'sidekiq_application_metrics'
2
+
3
+ class G5PromRails::MetricsContainer
4
+ if defined?(Sidekiq)
5
+ include G5PromRails::SidekiqApplicationMetrics
6
+ end
7
+
8
+ MODEL_COUNT_NAME = :model_rows
9
+
10
+ attr_reader :app
11
+ attr_reader :per_process, :per_application
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ @per_process = Prometheus::Client::Registry.new
16
+ @per_application = Prometheus::Client::Registry.new
17
+ @model_count_gauge = @per_application.gauge(MODEL_COUNT_NAME, "model row counts")
18
+ try(:initialize_sidekiq_application)
19
+ end
20
+
21
+ def update_model_count_gauge(*models)
22
+ models.each do |model|
23
+ @model_count_gauge.set(
24
+ { app: app, model: model.name.tableize },
25
+ model.count
26
+ )
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def app_hash(h = {})
33
+ { app: app }.merge(h)
34
+ end
35
+ end
@@ -0,0 +1,6 @@
1
+ module G5PromRails::RefreshingExporter
2
+ def respond_with(format)
3
+ G5PromRails.refresh_gauges if @path == G5PromRails::PER_APPLICATION_PATH
4
+ super
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ # prometheus-client provides a counter that can only be incremented. That works
2
+ # great for instrumenting events, but in the case of something like Sidekiq
3
+ # Processed count, prometheus (the server) can handle resets and all kinds of
4
+ # great stuff if I simply pass the count as-is. Rather than having to monkey
5
+ # with saving the previous value and all that nonsense, I just want to set the
6
+ # value and let the server deal with it.
7
+ class G5PromRails::SettableCounter < Prometheus::Client::Metric
8
+ def type
9
+ :counter
10
+ end
11
+
12
+ def set(labels, value)
13
+ @values[label_set_for(labels)] = value
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ require 'sidekiq/api'
2
+
3
+ module G5PromRails::SidekiqApplicationMetrics
4
+ extend ActiveSupport::Concern
5
+
6
+ def initialize_sidekiq_application
7
+ @processed_counter = G5PromRails::SettableCounter.new(
8
+ :sidekiq_processed,
9
+ "jobs processed"
10
+ )
11
+ per_application.register(@processed_counter)
12
+ @failed_counter = G5PromRails::SettableCounter.new(
13
+ :sidekiq_failed,
14
+ "jobs failed"
15
+ )
16
+ per_application.register(@failed_counter)
17
+
18
+ @retry_gauge = per_application.gauge(
19
+ :sidekiq_retry,
20
+ "jobs to be retried"
21
+ )
22
+ @queues_gauge = per_application.gauge(
23
+ :sidekiq_queued,
24
+ "job queue lengths"
25
+ )
26
+ end
27
+
28
+ def update_sidekiq_statistics
29
+ stats = Sidekiq::Stats.new
30
+ @processed_counter.set(app_hash, stats.processed)
31
+ @failed_counter.set(app_hash, stats.failed)
32
+ @retry_gauge.set(app_hash, stats.retry_size)
33
+
34
+ Sidekiq::Stats::Queues.new.lengths.each do |queue, length|
35
+ @queues_gauge.set(app_hash(queue: queue), length)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ class G5PromRails::SidekiqTimingMiddleware
2
+ def self.build_metric(reg)
3
+ reg.histogram(
4
+ :sidekiq_job_seconds,
5
+ "job running time in seconds",
6
+ {},
7
+ [
8
+ 10,
9
+ 30,
10
+ 90,
11
+ 3.minutes.to_i,
12
+ 7.minutes.to_i,
13
+ 12.minutes.to_i,
14
+ 20.minutes.to_i,
15
+ 35.minutes.to_i,
16
+ 60.minutes.to_i,
17
+ 80.minutes.to_i,
18
+ 2.hours.to_i,
19
+ 3.hours.to_i,
20
+ 5.hours.to_i,
21
+ 10.hours.to_i,
22
+ ]
23
+ )
24
+ end
25
+
26
+ def initialize(options = nil)
27
+ @app = options[:app]
28
+ @metric = options[:metric]
29
+ end
30
+
31
+ def call(worker, msg, queue)
32
+ @metric.observe(
33
+ { app: @app, job_class: worker.class.name },
34
+ Benchmark.realtime { yield }
35
+ )
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module G5PromRails
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :g5_prom_rails do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: g5_prom_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Don Petersen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: prometheus-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sidekiq
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Rails-friendly prometheus base
84
+ email:
85
+ - don@donpetersen.net
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - MIT-LICENSE
91
+ - README.md
92
+ - Rakefile
93
+ - app/assets/config/g5_prom_rails_manifest.js
94
+ - app/assets/javascripts/g5_prom_rails/application.js
95
+ - app/assets/stylesheets/g5_prom_rails/application.css
96
+ - app/controllers/g5_prom_rails/application_controller.rb
97
+ - app/helpers/g5_prom_rails/application_helper.rb
98
+ - app/jobs/g5_prom_rails/application_job.rb
99
+ - app/mailers/g5_prom_rails/application_mailer.rb
100
+ - app/models/g5_prom_rails/application_record.rb
101
+ - app/views/layouts/g5_prom_rails/application.html.erb
102
+ - config/routes.rb
103
+ - lib/g5_prom_rails.rb
104
+ - lib/g5_prom_rails/engine.rb
105
+ - lib/g5_prom_rails/metrics.rb
106
+ - lib/g5_prom_rails/refreshing_exporter.rb
107
+ - lib/g5_prom_rails/settable_counter.rb
108
+ - lib/g5_prom_rails/sidekiq_application_metrics.rb
109
+ - lib/g5_prom_rails/sidekiq_timing_middleware.rb
110
+ - lib/g5_prom_rails/version.rb
111
+ - lib/tasks/g5_prom_rails_tasks.rake
112
+ homepage: http://github.com/G5/g5_prom_rails
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.5.1
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Rails-friendly prometheus base
136
+ test_files: []