clear_skies 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e7f3e39ee746e315e437e4b03ec2cfd661acfdd
4
- data.tar.gz: 571c9c8882415e687f3c25518225f251503e0117
3
+ metadata.gz: 9b28817b1d9a2d115177165c9b1a2ab8d44aeb43
4
+ data.tar.gz: 2033b9f62ed98513dc3eb01c3a3ab88d682d2860
5
5
  SHA512:
6
- metadata.gz: cabc3a1ffd842b584c9d7d4435e4102492bcc63383c9fb079c96da59a625f0078fa2a300b4a0f1e6fc258a9cd479fd17be3d1c2647cbb097a3c4c60c38deb947
7
- data.tar.gz: 2c135a5330dd5da45997494e0c3f50a41222c45250d1e81ef3c9fbb62a47c3d8c1cfe051d41fda6af28ffa35245eb7212c400e947fa5fc034a2369ea3567155f
6
+ metadata.gz: 86fbbf4d79173b447bd66d5539263ede10256bf23c129397b032ebed7e035560ee899f3b067165327ac149f44636f234cf0aa5519479bf7d6132c44774685fe4
7
+ data.tar.gz: 4333fa6071ffeb618af49418fa01e644cf4729b4bf7ec996c45c5b1bdaf8cd99d81739ecc0f51ff7166b98b1792156b3ef7d6e257e3dac0a7214943ff21b143e
data/README.md CHANGED
@@ -32,7 +32,7 @@ The SDK searches the following locations for a region:
32
32
  To run the exporter simple do:
33
33
  $ clear_skies metrics_file
34
34
 
35
- The metrics_file is a ruby script that registers the metrics you wish to export.
35
+ The `metrics_file` is a ruby script that registers the metrics you wish to export.
36
36
 
37
37
  ``` ruby
38
38
  # To grab a generic cloudwatch metric use the following method:
@@ -40,12 +40,12 @@ ClearSkies::Gauge.register(namespace, metric_name,dimensions, statistics) do |la
40
40
  labels[:extra] = "label"
41
41
  labels[:instance_id] == "something specific"
42
42
  end
43
-
43
+ ```
44
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
45
 
46
46
 
47
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.
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
49
 
50
50
  ``` ruby
51
51
  # To grab an RDS metric
@@ -53,7 +53,7 @@ ClearSkies::RDSGauge.register("ReadThroughput", ["DBInstanceIdentifier"], ["Aver
53
53
  ```
54
54
 
55
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.
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
57
 
58
58
  ``` ruby
59
59
  # To grab an ELB metric
@@ -61,7 +61,7 @@ ClearSkies::ELBGauge.register("Latency", ["LoadBalancerName"], ["Average", "p90"
61
61
  ```
62
62
 
63
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.
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
65
 
66
66
  ``` ruby
67
67
  # To grab an ELB metric
data/clear_skies.gemspec CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_dependency "puma"
25
25
  spec.add_dependency "aws-sdk"
26
+ spec.add_dependency "redis"
26
27
  spec.add_dependency "greek_fire", ">= 0.3.0"
27
28
  spec.add_dependency "awesome_print"
28
29
 
data/exe/clear_skies CHANGED
@@ -30,7 +30,5 @@ ARGV.each do |config|
30
30
  load config
31
31
  end
32
32
 
33
- Aws::CloudWatch::Client.add_plugin(ClearSkies::RequestCounterPlugin)
34
- GreekFire::Counter.register("cloudwatch_requests_total") { ClearSkies::RequestCounter.count }
35
33
 
36
34
  Rack::Handler::Puma.run ClearSkies::App, options
data/lib/clear_skies.rb CHANGED
@@ -7,8 +7,9 @@ require "greek_fire"
7
7
  require "aws-sdk"
8
8
 
9
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"
10
+ require "clear_skies/cloud_watch/gauge"
11
+ require "clear_skies/cloud_watch/rds_gauge"
12
+ require "clear_skies/cloud_watch/elb_gauge"
13
+ require "clear_skies/cloud_watch/elastic_beanstalk_gauge"
14
+ require "clear_skies/cloud_watch/request_counter"
15
+ require "clear_skies/redis/report"
@@ -0,0 +1,45 @@
1
+ module ClearSkies
2
+ module CloudWatch
3
+ class ElasticBeanstalkGauge < ClearSkies::CloudWatch::Gauge
4
+ def self.client
5
+ @client ||= Aws::ElasticBeanstalk::Client.new
6
+ end
7
+ def initialize(metric_name, dimension, statistics, description: nil, &block)
8
+ super("AWS/ElasticBeanstalk", metric_name, dimension, statistics, description: description, &block)
9
+ end
10
+
11
+ def application_name(environment_name)
12
+ ElasticBeanstalkGauge.client.describe_environments({environment_names: [environment_name] }).environments.first&.application_name
13
+ end
14
+
15
+ def vpc_id(application_name, environment_name)
16
+ config = ElasticBeanstalkGauge.client.describe_configuration_settings({ application_name: application_name, environment_name: environment_name }).
17
+ configuration_settings.find { |config| config.application_name == application_name && config.environment_name == environment_name}
18
+ option = config.option_settings.find { |option| option.namespace == "aws:ec2:vpc" && option.option_name == "VPCId"}
19
+ option.value if option
20
+ end
21
+
22
+
23
+ def labels_from_metric(metric)
24
+ labels = super(metric)
25
+
26
+ if labels.has_key?( "environment_name") && !(Rails.cache.fetch("#{labels["environment_name"]}_skip"))
27
+ application_name = Rails.cache.fetch("#{labels["environment_name"]}_application_name", expires_in: 1.hour) do
28
+ application_name(labels["environment_name"])
29
+ end
30
+ if application_name
31
+ labels["application_name"] = application_name
32
+
33
+ labels["vpc_id"] = Rails.cache.fetch("#{labels["environment_name"]}_vpc_id_") do
34
+ vpc_id(labels["application_name"], labels["environment_name"])
35
+ end
36
+ end
37
+ else
38
+ Rails.cache.write("#{labels["environment_name"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
39
+ end
40
+
41
+ return labels
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,44 @@
1
+ module ClearSkies
2
+ module CloudWatch
3
+ class ELBGauge < ClearSkies::CloudWatch::Gauge
4
+ def self.client
5
+ @client ||= Aws::ElasticLoadBalancing::Client.new
6
+ end
7
+ def initialize(metric_name, dimension, statistics, description: nil, &block)
8
+ super("AWS/ELB", metric_name, dimension, statistics, description: description, &block)
9
+ end
10
+
11
+ def tags(load_balancer_name)
12
+ labels = {}
13
+ ELBGauge.client.
14
+ describe_tags({load_balancer_names: [load_balancer_name]}).
15
+ tag_descriptions.
16
+ select {|doc| doc.load_balancer_name == load_balancer_name}.each do |tag_description|
17
+ tag_description.tags.each do |tag|
18
+ labels[tag.key.downcase] = tag.value
19
+ end
20
+ end
21
+ labels
22
+ end
23
+
24
+ def labels_from_metric(metric)
25
+ labels = super(metric)
26
+
27
+ if labels.has_key?( "load_balancer_name") && !(Rails.cache.fetch("#{labels["load_balancer_name"]}_skip"))
28
+
29
+ labels["vpc_id"] = Rails.cache.fetch("#{labels["load_balancer_name"]}_vpc_id_") do
30
+ ELBGauge.client.describe_load_balancers(load_balancer_names: [labels["load_balancer_name"]]).load_balancer_descriptions.first.vpc_id
31
+ end
32
+
33
+ labels.merge!(Rails.cache.fetch("#{labels["load_balancer_name"]}_tags_", expires_in: 1.hour, race_condition_ttl: 60.seconds) do
34
+ tags(labels["load_balancer_name"])
35
+ end)
36
+ end
37
+ labels
38
+ rescue Aws::ElasticLoadBalancing::Errors::LoadBalancerNotFound
39
+ Rails.cache.write("#{labels["load_balancer_name"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
40
+ return labels
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,70 @@
1
+
2
+ module ClearSkies
3
+ module CloudWatch
4
+ class Gauge < GreekFire::Gauge
5
+ include ActiveModel::Conversion
6
+
7
+ def self.register(*args, &block)
8
+ GreekFire::Metric.register(self.new(*args, &block))
9
+ end
10
+
11
+ def initialize(namespace, metric_name, dimensions, statistics, description:nil, &block)
12
+ super("#{namespace.underscore.gsub("/", "_")}_#{metric_name.underscore}", description: description)
13
+ @namespace = namespace
14
+ @metric_name = metric_name
15
+ @dimensions = dimensions
16
+ @statistics = statistics.select { |stat| ["SampleCount", "Average", "Sum", "Minimum", "Maximum"].include?(stat.to_s) }
17
+ @extended_statistics = statistics - @statistics
18
+
19
+ @block = block
20
+ end
21
+
22
+ def self.cloudwatch_client
23
+ @client ||= Aws::CloudWatch::Client.new
24
+ end
25
+
26
+ def aws_metrics
27
+ Aws::CloudWatch::Resource.new(client: Gauge.cloudwatch_client).metrics(
28
+ namespace: @namespace,
29
+ metric_name: @metric_name,
30
+ dimensions: @dimensions.map {|dimension| {name: dimension} }
31
+ ).select { |metrics| metrics.dimensions.count == @dimensions.count }
32
+ end
33
+
34
+ def labels_from_metric(metric)
35
+ metric.dimensions.inject(ActiveSupport::HashWithIndifferentAccess.new) do |labels, dimension|
36
+ labels[dimension.name.underscore] = dimension.value
37
+ labels
38
+ end
39
+ end
40
+
41
+ def metrics
42
+ aws_metrics.map do |metric|
43
+ labels = labels_from_metric(metric)
44
+
45
+ next unless @block.call(labels) if @block
46
+
47
+ stats = metric.get_statistics(
48
+ start_time: Time.now.advance(minutes: -6),
49
+ end_time: Time.now.advance(minutes: -5),
50
+ period: 1,
51
+ statistics: @statistics,
52
+ extended_statistics: @extended_statistics,
53
+ dimensions: metric.dimensions
54
+ )
55
+
56
+ stats.datapoints.map do |datapoint|
57
+ datapoint.to_h.select {|k, v| ![:unit, :timestamp].include?(k) }.map do |key, value|
58
+ if (key == :extended_statistics)
59
+ value.map {|e_key, e_value| GreekFire::Metric.new(name, labels.merge({statistic: e_key}), e_value)}
60
+ else
61
+ GreekFire::Metric.new(name, labels.merge({statistic: key}), value)
62
+ end
63
+ end
64
+ end
65
+
66
+ end.flatten.compact
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,37 @@
1
+ module ClearSkies
2
+ module CloudWatch
3
+ class RDSGauge < ClearSkies::CloudWatch::Gauge
4
+ def initialize(metric_name, dimension, statistics, description: nil, &block)
5
+ super("AWS/RDS", metric_name, dimension, statistics, description: description, &block)
6
+ end
7
+
8
+ def tags(db)
9
+ labels = {}
10
+ db.client.list_tags_for_resource(resource_name: db.db_instance_arn).tag_list.each do |tag|
11
+ labels[tag.key.downcase] = tag.value
12
+ end
13
+ labels
14
+ end
15
+
16
+ def labels_from_metric(metric)
17
+ labels = super(metric)
18
+
19
+ if labels.has_key?( "db_instance_identifier") && !(Rails.cache.fetch("#{labels["db_instance_identifier"]}_skip"))
20
+ db = Aws::RDS::DBInstance.new(labels["db_instance_identifier"])
21
+
22
+ labels["vpc_id"] = Rails.cache.fetch("#{labels["db_instance_identifier"]}_vpc_id_") do
23
+ db.db_subnet_group.vpc_id
24
+ end
25
+
26
+ labels.merge!(Rails.cache.fetch("#{labels["db_instance_identifier"]}_tags_", expires_in: 1.hour, race_condition_ttl: 60.seconds) do
27
+ tags(db)
28
+ end)
29
+ end
30
+ labels
31
+ rescue Aws::RDS::Errors::DBInstanceNotFound
32
+ Rails.cache.write("#{labels["db_instance_identifier"]}_skip", true, expires_in: 1.hour, race_condition_ttl: 60.seconds)
33
+ return labels
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module ClearSkies
2
+ module CloudWatch
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
35
+ end
36
+
37
+ Aws::CloudWatch::Client.add_plugin(ClearSkies::CloudWatch::RequestCounterPlugin)
@@ -0,0 +1,52 @@
1
+ require 'redis'
2
+ module ClearSkies
3
+ module Redis
4
+ class Report
5
+ def self.register(host, port, extra_labels=nil)
6
+ extra_labels = Hash.new unless extra_labels
7
+
8
+ r = ClearSkies::Redis::Report.new(host, port)
9
+ databases = Proc.new { ::Redis.new(:host => host, :port => port).info.keys.map {|k| k =~ /^db/ && k.sub("db", "")}.compact }
10
+
11
+ GreekFire::Gauge.register("redis_keys", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).keys }
12
+ GreekFire::Gauge.register("redis_last_save", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).last_save }
13
+ GreekFire::Gauge.register("redis_uptime", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).uptime }
14
+ GreekFire::Gauge.register("redis_connected_clients", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).connected_clients }
15
+ GreekFire::Gauge.register("redis_blocked_clients", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).blocked_clients }
16
+ GreekFire::Gauge.register("redis_used_memory", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).used_memory }
17
+ GreekFire::Gauge.register("redis_mem_fragmentation_ratio", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).mem_fragmentation_ratio }
18
+ GreekFire::Gauge.register("redis_rdb_changes_since_last_save", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).rdb_changes_since_last_save }
19
+ GreekFire::Gauge.register("redis_rdb_last_bgsave_time_sec", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).rdb_last_bgsave_time_sec }
20
+ GreekFire::Counter.register("redis_total_commands_processed", labels: {"database" => databases} ) { | labels| labels.merge!(extra_labels);r.redis_metrics(labels).total_commands_processed }
21
+ end
22
+
23
+
24
+ def redis_metrics(labels)
25
+ cache_key = "redis_stats_#{@host}_#{@port}_#{labels["database"]}"
26
+ Rails.cache.fetch(cache_key, expires_in: 1.second) do
27
+ redis = ::Redis.new(host: @host, port: @port, db: labels["database"])
28
+ redis_info = redis.info
29
+ metrics = OpenStruct.new
30
+
31
+ metrics.keys = redis.dbsize
32
+ metrics.last_save = Time.now.to_i - redis.lastsave
33
+ metrics.uptime = redis_info["uptime_in_seconds"].to_f
34
+ metrics.connected_clients = redis_info["connected_clients"].to_i
35
+ metrics.blocked_clients = redis_info["blocked_clients"].to_i
36
+ metrics.used_memory = redis_info["used_memory"].to_f
37
+ metrics.mem_fragmentation_ratio = redis_info["mem_fragmentation_ratio"].to_f
38
+ metrics.rdb_changes_since_last_save = redis_info["rdb_changes_since_last_save"].to_f
39
+ metrics.rdb_last_bgsave_time_sec = redis_info["rdb_last_bgsave_time_sec"].to_f
40
+ metrics.total_commands_processed = redis_info["total_commands_processed"].to_f
41
+ metrics
42
+ end
43
+ end
44
+
45
+ private
46
+ def initialize(host, port)
47
+ @host = host
48
+ @port = port
49
+ end
50
+ end
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module ClearSkies
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clear_skies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Constantine
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-17 00:00:00.000000000 Z
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puma
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redis
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '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'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: greek_fire
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -116,11 +130,12 @@ files:
116
130
  - exe/clear_skies
117
131
  - lib/clear_skies.rb
118
132
  - 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
133
+ - lib/clear_skies/cloud_watch/elastic_beanstalk_gauge.rb
134
+ - lib/clear_skies/cloud_watch/elb_gauge.rb
135
+ - lib/clear_skies/cloud_watch/gauge.rb
136
+ - lib/clear_skies/cloud_watch/rds_gauge.rb
137
+ - lib/clear_skies/cloud_watch/request_counter.rb
138
+ - lib/clear_skies/redis/report.rb
124
139
  - lib/clear_skies/version.rb
125
140
  homepage: https://github.com/omadahealth/clear_skies
126
141
  licenses:
@@ -1,41 +0,0 @@
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
@@ -1,42 +0,0 @@
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
@@ -1,72 +0,0 @@
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
@@ -1,35 +0,0 @@
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
@@ -1,34 +0,0 @@
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