clear_skies 0.1.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 +7 -0
- data/.gitignore +10 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Dockerfile +11 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +78 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/clear_skies.gemspec +31 -0
- data/exe/clear_skies +36 -0
- data/lib/clear_skies/app.rb +36 -0
- data/lib/clear_skies/metrics/elastic_beanstalk_gauge.rb +41 -0
- data/lib/clear_skies/metrics/elb_gauge.rb +42 -0
- data/lib/clear_skies/metrics/gauge.rb +72 -0
- data/lib/clear_skies/metrics/rds_gauge.rb +35 -0
- data/lib/clear_skies/request_counter.rb +34 -0
- data/lib/clear_skies/version.rb +3 -0
- data/lib/clear_skies.rb +14 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9e7f3e39ee746e315e437e4b03ec2cfd661acfdd
|
4
|
+
data.tar.gz: 571c9c8882415e687f3c25518225f251503e0117
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cabc3a1ffd842b584c9d7d4435e4102492bcc63383c9fb079c96da59a625f0078fa2a300b4a0f1e6fc258a9cd479fd17be3d1c2647cbb097a3c4c60c38deb947
|
7
|
+
data.tar.gz: 2c135a5330dd5da45997494e0c3f50a41222c45250d1e81ef3c9fbb62a47c3d8c1cfe051d41fda6af28ffa35245eb7212c400e947fa5fc034a2369ea3567155f
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
clear_skies
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.4.1
|
data/Dockerfile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
FROM ruby:2.4.1
|
2
|
+
# throw errors if Gemfile has been modified since Gemfile.lock
|
3
|
+
RUN bundle config --global frozen 1
|
4
|
+
|
5
|
+
RUN mkdir -p /usr/src/app
|
6
|
+
WORKDIR /usr/src/app
|
7
|
+
|
8
|
+
COPY . /usr/src/app
|
9
|
+
RUN bundle install
|
10
|
+
|
11
|
+
ENTRYPOINT ["clear_skies", "-e", "production"]
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 cconstantine
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# ClearSkies
|
2
|
+
|
3
|
+
Programable cloudwatch metrics exporter for Prometheus
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install it yourself as:
|
8
|
+
|
9
|
+
$ gem install clear_skies
|
10
|
+
|
11
|
+
## Configuration
|
12
|
+
(from https://github.com/aws/aws-sdk-ruby)
|
13
|
+
You need to configure `:credentials` and a `:region` to make API calls. It is recommended that you provide these via your environment. This makes it easier to rotate credentials and it keeps your secrets out of source control.
|
14
|
+
|
15
|
+
The SDK searches the following locations for credentials:
|
16
|
+
|
17
|
+
* `ENV['AWS_ACCESS_KEY_ID']` and `ENV['AWS_SECRET_ACCESS_KEY']`
|
18
|
+
* Unless `ENV['AWS_SDK_CONFIG_OPT_OUT']` is set, the shared configuration files (`~/.aws/credentials` and `~/.aws/config`) will be checked for a `role_arn` and `source_profile`, which if present will be used to attempt to assume a role.
|
19
|
+
* The shared credentials ini file at `~/.aws/credentials` ([more information](http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs))
|
20
|
+
* Unless `ENV['AWS_SDK_CONFIG_OPT_OUT']` is set, the shared configuration ini file at `~/.aws/config` will also be parsed for credentials.
|
21
|
+
* From an instance profile when running on EC2, or from the ECS credential provider when running in an ECS container with that feature enabled.
|
22
|
+
|
23
|
+
The SDK searches the following locations for a region:
|
24
|
+
|
25
|
+
* `ENV['AWS_REGION']`
|
26
|
+
* Unless `ENV['AWS_SDK_CONFIG_OPT_OUT']` is set, the shared configuration files (`~/.aws/credentials` and `~/.aws/config`) will also be checked for a region selection.
|
27
|
+
|
28
|
+
**The region is used to construct an SSL endpoint**. If you need to connect to a non-standard endpoint, you may specify the `:endpoint` option.
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
To run the exporter simple do:
|
33
|
+
$ clear_skies metrics_file
|
34
|
+
|
35
|
+
The metrics_file is a ruby script that registers the metrics you wish to export.
|
36
|
+
|
37
|
+
``` ruby
|
38
|
+
# To grab a generic cloudwatch metric use the following method:
|
39
|
+
ClearSkies::Gauge.register(namespace, metric_name,dimensions, statistics) do |labels|
|
40
|
+
labels[:extra] = "label"
|
41
|
+
labels[:instance_id] == "something specific"
|
42
|
+
end
|
43
|
+
|
44
|
+
If you pass a block, it will be called for each dimension retrieved. The block will be passed a hash of all computed labels, and you may add more if you wish. If the blocks value is false, that dimension will be skipped.
|
45
|
+
|
46
|
+
|
47
|
+
### RDS Metrics
|
48
|
+
There is a helper class for grabbing RDS metrics. It behaves the same as ClearSkies::Gauge, except that it automatically adds the vpc_id and tags as labels.
|
49
|
+
|
50
|
+
``` ruby
|
51
|
+
# To grab an RDS metric
|
52
|
+
ClearSkies::RDSGauge.register("ReadThroughput", ["DBInstanceIdentifier"], ["Average", "Minimum", "Maximum"])end
|
53
|
+
```
|
54
|
+
|
55
|
+
### ELB Metrics
|
56
|
+
There is a helper class for grabbing ELB metrics. It behaves the same as ClearSkies::Gauge, except that it automatically adds the vpc_id and tags as labels.
|
57
|
+
|
58
|
+
``` ruby
|
59
|
+
# To grab an ELB metric
|
60
|
+
ClearSkies::ELBGauge.register("Latency", ["LoadBalancerName"], ["Average", "p90"])
|
61
|
+
```
|
62
|
+
|
63
|
+
### ElasticBeanstalk Metrics
|
64
|
+
There is a helper class for grabbing ElasticBeanstalk metrics. It behaves the same as ClearSkies::Gauge, except that it automatically adds vpc_id and application_name as labels.
|
65
|
+
|
66
|
+
``` ruby
|
67
|
+
# To grab an ELB metric
|
68
|
+
ClearSkies::ElasticBeanstalkGauge.register("InstancesOk", ["EnvironmentName"], ["Average", "Minimum", "Maximum"])
|
69
|
+
```
|
70
|
+
|
71
|
+
## Contributing.
|
72
|
+
|
73
|
+
If there is a namespace of metrics you wish to add, please submit a PR.
|
74
|
+
|
75
|
+
## License
|
76
|
+
|
77
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
78
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "clear_skies"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/clear_skies.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'clear_skies/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "clear_skies"
|
8
|
+
spec.version = ClearSkies::VERSION
|
9
|
+
spec.authors = ["Chris Constantine"]
|
10
|
+
spec.email = ["chris@omadahealth.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Cloudwatch metrics for prometheus.}
|
13
|
+
spec.description = %q{A tool for exposing cloudwatch metrics for prometheus.}
|
14
|
+
spec.homepage = "https://github.com/omadahealth/clear_skies"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "puma"
|
25
|
+
spec.add_dependency "aws-sdk"
|
26
|
+
spec.add_dependency "greek_fire", ">= 0.3.0"
|
27
|
+
spec.add_dependency "awesome_print"
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
end
|
data/exe/clear_skies
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require "clear_skies"
|
4
|
+
require "rack/handler/puma"
|
5
|
+
require "optparse"
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
OptionParser.new do |parser|
|
9
|
+
parser.banner = "Usage: clear_skies [options] [--] metrics_file [metrics_file ...]"
|
10
|
+
parser.on("-p", "--port PORT",
|
11
|
+
"Port to listen on") do |port|
|
12
|
+
options[:Port] = port
|
13
|
+
end
|
14
|
+
parser.on("-b", "--bind host",
|
15
|
+
"Host/ip to listen on") do |host|
|
16
|
+
options[:Host] = host
|
17
|
+
end
|
18
|
+
parser.on("-t", "--threads MIN:MAX",
|
19
|
+
"min:max threads to use (default 0:16)") do |threads|
|
20
|
+
options[:Threads] = threads
|
21
|
+
end
|
22
|
+
parser.on("-e", "--environment env",
|
23
|
+
"The environment to run the Rack app on (default development)") do |env|
|
24
|
+
options[:environment] = env
|
25
|
+
end
|
26
|
+
end.parse!
|
27
|
+
|
28
|
+
ARGV.each do |config|
|
29
|
+
puts "Loading: '#{config}'"
|
30
|
+
load config
|
31
|
+
end
|
32
|
+
|
33
|
+
Aws::CloudWatch::Client.add_plugin(ClearSkies::RequestCounterPlugin)
|
34
|
+
GreekFire::Counter.register("cloudwatch_requests_total") { ClearSkies::RequestCounter.count }
|
35
|
+
|
36
|
+
Rack::Handler::Puma.run ClearSkies::App, options
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ClearSkies
|
2
|
+
|
3
|
+
class App < Rails::Application
|
4
|
+
routes.append do
|
5
|
+
mount GreekFire::Engine => "/metrics"
|
6
|
+
end
|
7
|
+
|
8
|
+
# Enable cache classes. Production style.
|
9
|
+
config.cache_classes = Rails.env.production?
|
10
|
+
|
11
|
+
config.logger = Logger.new(STDOUT)
|
12
|
+
config.log_level = :info
|
13
|
+
config.action_view.logger = nil
|
14
|
+
|
15
|
+
|
16
|
+
config.cache_store = :memory_store
|
17
|
+
config.eager_load = Rails.env.production?
|
18
|
+
|
19
|
+
# uncomment below to display errors
|
20
|
+
config.consider_all_requests_local = !Rails.env.production?
|
21
|
+
|
22
|
+
# Here you could remove some middlewares, for example
|
23
|
+
# Rack::Lock, ActionDispatch::Flash and ActionDispatch::BestStandardsSupport below.
|
24
|
+
# The remaining stack is printed on rackup (for fun!).
|
25
|
+
# Rails API has config.middleware.api_only! to get
|
26
|
+
# rid of browser related middleware.
|
27
|
+
config.middleware.delete "Rack::Lock"
|
28
|
+
config.middleware.delete "ActionDispatch::Flash"
|
29
|
+
config.middleware.delete "ActionDispatch::BestStandardsSupport"
|
30
|
+
|
31
|
+
# We need a secret token for session, cookies, etc.
|
32
|
+
config.secret_key_base = ENV['secret_key_base'] || SecureRandom.hex(64)
|
33
|
+
end
|
34
|
+
|
35
|
+
ClearSkies::App.initialize!
|
36
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ClearSkies
|
2
|
+
class ElasticBeanstalkGauge < ClearSkies::Gauge
|
3
|
+
def self.client
|
4
|
+
@client ||= Aws::ElasticBeanstalk::Client.new
|
5
|
+
end
|
6
|
+
def initialize(metric_name, dimension, statistics, description: nil, &block)
|
7
|
+
super("AWS/ElasticBeanstalk", metric_name, dimension, statistics, description: description, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def application_name(environment_name)
|
11
|
+
ElasticBeanstalkGauge.client.describe_environments({environment_names: [environment_name] }).environments.first.application_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def vpc_id(application_name, environment_name)
|
15
|
+
config = ElasticBeanstalkGauge.client.describe_configuration_settings({ application_name: application_name, environment_name: environment_name }).
|
16
|
+
configuration_settings.find { |config| config.application_name == application_name && config.environment_name == environment_name}
|
17
|
+
option = config.option_settings.find { |option| option.namespace == "aws:ec2:vpc" && option.option_name == "VPCId"}
|
18
|
+
option.value if option
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def labels_from_metric(metric)
|
23
|
+
labels = super(metric)
|
24
|
+
|
25
|
+
if labels.has_key?( "environment_name") && !(Rails.cache.fetch("#{labels["environment_name"]}_skip"))
|
26
|
+
|
27
|
+
labels["application_name"] = Rails.cache.fetch("#{labels["environment_name"]}_application_name", expires_in: 1.hour) do
|
28
|
+
application_name(labels["environment_name"])
|
29
|
+
end
|
30
|
+
|
31
|
+
labels["vpc_id"] = Rails.cache.fetch("#{labels["environment_name"]}_vpc_id_") do
|
32
|
+
vpc_id(labels["application_name"], labels["environment_name"])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
labels
|
36
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound
|
37
|
+
Rails.cache.write("#{labels["environment_name"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
|
38
|
+
return labels
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ClearSkies
|
2
|
+
class ELBGauge < ClearSkies::Gauge
|
3
|
+
def self.client
|
4
|
+
@client ||= Aws::ElasticLoadBalancing::Client.new
|
5
|
+
end
|
6
|
+
def initialize(metric_name, dimension, statistics, description: nil, &block)
|
7
|
+
super("AWS/ELB", metric_name, dimension, statistics, description: description, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def tags(load_balancer_name)
|
11
|
+
labels = {}
|
12
|
+
ELBGauge.client.
|
13
|
+
describe_tags({load_balancer_names: [load_balancer_name]}).
|
14
|
+
tag_descriptions.
|
15
|
+
select {|doc| doc.load_balancer_name == load_balancer_name}.each do |tag_description|
|
16
|
+
tag_description.tags.each do |tag|
|
17
|
+
labels[tag.key.downcase] = tag.value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
labels
|
21
|
+
end
|
22
|
+
|
23
|
+
def labels_from_metric(metric)
|
24
|
+
labels = super(metric)
|
25
|
+
|
26
|
+
if labels.has_key?( "load_balancer_name") && !(Rails.cache.fetch("#{labels["load_balancer_name"]}_skip"))
|
27
|
+
|
28
|
+
labels["vpc_id"] = Rails.cache.fetch("#{labels["load_balancer_name"]}_vpc_id_") do
|
29
|
+
ELBGauge.client.describe_load_balancers(load_balancer_names: [labels["load_balancer_name"]]).load_balancer_descriptions.first.vpc_id
|
30
|
+
end
|
31
|
+
|
32
|
+
labels.merge!(Rails.cache.fetch("#{labels["load_balancer_name"]}_tags_", expires_in: 1.hour, race_condition_ttl: 60.seconds) do
|
33
|
+
tags(labels["load_balancer_name"])
|
34
|
+
end)
|
35
|
+
end
|
36
|
+
labels
|
37
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound
|
38
|
+
Rails.cache.write("#{labels["load_balancer_name"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
|
39
|
+
return labels
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
module ClearSkies
|
3
|
+
class Gauge < GreekFire::Gauge
|
4
|
+
include ActiveModel::Conversion
|
5
|
+
|
6
|
+
def self.register(*args, &block)
|
7
|
+
GreekFire::Metric.register(self.new(*args, &block))
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_partial_path
|
11
|
+
GreekFire::Gauge._to_partial_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(namespace, metric_name, dimensions, statistics, description:nil, &block)
|
15
|
+
super("#{namespace.underscore.gsub("/", "_")}_#{metric_name.underscore}", description: description)
|
16
|
+
@namespace = namespace
|
17
|
+
@metric_name = metric_name
|
18
|
+
@dimensions = dimensions
|
19
|
+
@statistics = statistics.select { |stat| ["SampleCount", "Average", "Sum", "Minimum", "Maximum"].include?(stat.to_s) }
|
20
|
+
@extended_statistics = statistics - @statistics
|
21
|
+
|
22
|
+
@block = block
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.cloudwatch_client
|
26
|
+
@client ||= Aws::CloudWatch::Client.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def aws_metrics
|
30
|
+
Aws::CloudWatch::Resource.new(client: Gauge.cloudwatch_client).metrics(
|
31
|
+
namespace: @namespace,
|
32
|
+
metric_name: @metric_name,
|
33
|
+
dimensions: @dimensions.map {|dimension| {name: dimension} }
|
34
|
+
).select { |metrics| metrics.dimensions.count == @dimensions.count }
|
35
|
+
end
|
36
|
+
|
37
|
+
def labels_from_metric(metric)
|
38
|
+
metric.dimensions.inject(ActiveSupport::HashWithIndifferentAccess.new) do |labels, dimension|
|
39
|
+
labels[dimension.name.underscore] = dimension.value
|
40
|
+
labels
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def metrics
|
45
|
+
aws_metrics.map do |metric|
|
46
|
+
labels = labels_from_metric(metric)
|
47
|
+
|
48
|
+
next unless @block.call(labels) if @block
|
49
|
+
|
50
|
+
stats = metric.get_statistics(
|
51
|
+
start_time: Time.now.advance(minutes: -6),
|
52
|
+
end_time: Time.now.advance(minutes: -5),
|
53
|
+
period: 1,
|
54
|
+
statistics: @statistics,
|
55
|
+
extended_statistics: @extended_statistics,
|
56
|
+
dimensions: metric.dimensions
|
57
|
+
)
|
58
|
+
|
59
|
+
stats.datapoints.map do |datapoint|
|
60
|
+
datapoint.to_h.select {|k, v| ![:unit, :timestamp].include?(k) }.map do |key, value|
|
61
|
+
if (key == :extended_statistics)
|
62
|
+
value.map {|e_key, e_value| GreekFire::Metric.new(name, labels.merge({statistic: e_key}), e_value)}
|
63
|
+
else
|
64
|
+
GreekFire::Metric.new(name, labels.merge({statistic: key}), value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end.flatten.compact
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ClearSkies
|
2
|
+
class RDSGauge < ClearSkies::Gauge
|
3
|
+
def initialize(metric_name, dimension, statistics, description: nil, &block)
|
4
|
+
super("AWS/RDS", metric_name, dimension, statistics, description: description, &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def tags(db)
|
8
|
+
labels = {}
|
9
|
+
db.client.list_tags_for_resource(resource_name: db.db_instance_arn).tag_list.each do |tag|
|
10
|
+
labels[tag.key.downcase] = tag.value
|
11
|
+
end
|
12
|
+
labels
|
13
|
+
end
|
14
|
+
|
15
|
+
def labels_from_metric(metric)
|
16
|
+
labels = super(metric)
|
17
|
+
|
18
|
+
if labels.has_key?( "db_instance_identifier") && !(Rails.cache.fetch("#{labels["db_instance_identifier"]}_skip"))
|
19
|
+
db = Aws::RDS::DBInstance.new(labels["db_instance_identifier"])
|
20
|
+
|
21
|
+
labels["vpc_id"] = Rails.cache.fetch("#{labels["db_instance_identifier"]}_vpc_id_") do
|
22
|
+
db.db_subnet_group.vpc_id
|
23
|
+
end
|
24
|
+
|
25
|
+
labels.merge!(Rails.cache.fetch("#{labels["db_instance_identifier"]}_tags_", expires_in: 1.hour, race_condition_ttl: 60.seconds) do
|
26
|
+
tags(db)
|
27
|
+
end)
|
28
|
+
end
|
29
|
+
labels
|
30
|
+
rescue Aws::RDS::Errors::DBInstanceNotFound
|
31
|
+
Rails.cache.write("#{labels["db_instance_identifier"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
|
32
|
+
return labels
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ClearSkies
|
2
|
+
|
3
|
+
class RequestCounter < Seahorse::Client::Handler
|
4
|
+
@mutex = Mutex.new
|
5
|
+
def self.increment
|
6
|
+
@mutex.synchronize do
|
7
|
+
@count ||= 0
|
8
|
+
@count += 1
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.count
|
13
|
+
@count ||= 0
|
14
|
+
@count
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(handler)
|
18
|
+
@handler = handler
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(context)
|
22
|
+
RequestCounter.increment
|
23
|
+
@handler.call(context)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class RequestCounterPlugin < Seahorse::Client::Plugin
|
28
|
+
|
29
|
+
def add_handlers(handlers, config)
|
30
|
+
handlers.add(RequestCounter, step: :validate)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/clear_skies.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "clear_skies/version"
|
2
|
+
require "securerandom"
|
3
|
+
|
4
|
+
require "rails"
|
5
|
+
require "action_controller/railtie"
|
6
|
+
require "greek_fire"
|
7
|
+
require "aws-sdk"
|
8
|
+
|
9
|
+
require "clear_skies/app"
|
10
|
+
require "clear_skies/metrics/gauge"
|
11
|
+
require "clear_skies/metrics/rds_gauge"
|
12
|
+
require "clear_skies/metrics/elb_gauge"
|
13
|
+
require "clear_skies/metrics/elastic_beanstalk_gauge"
|
14
|
+
require "clear_skies/request_counter"
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clear_skies
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Constantine
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: puma
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: greek_fire
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.3.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.3.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: awesome_print
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
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: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.14'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.14'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
description: A tool for exposing cloudwatch metrics for prometheus.
|
98
|
+
email:
|
99
|
+
- chris@omadahealth.com
|
100
|
+
executables:
|
101
|
+
- clear_skies
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- ".ruby-gemset"
|
107
|
+
- ".ruby-version"
|
108
|
+
- Dockerfile
|
109
|
+
- Gemfile
|
110
|
+
- LICENSE.txt
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- clear_skies.gemspec
|
116
|
+
- exe/clear_skies
|
117
|
+
- lib/clear_skies.rb
|
118
|
+
- lib/clear_skies/app.rb
|
119
|
+
- lib/clear_skies/metrics/elastic_beanstalk_gauge.rb
|
120
|
+
- lib/clear_skies/metrics/elb_gauge.rb
|
121
|
+
- lib/clear_skies/metrics/gauge.rb
|
122
|
+
- lib/clear_skies/metrics/rds_gauge.rb
|
123
|
+
- lib/clear_skies/request_counter.rb
|
124
|
+
- lib/clear_skies/version.rb
|
125
|
+
homepage: https://github.com/omadahealth/clear_skies
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.6.11
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: Cloudwatch metrics for prometheus.
|
149
|
+
test_files: []
|