clear_skies 0.1.0 → 0.2.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 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