aws-reporting 0.9.1
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.
- data/bin/aws-reporting +54 -0
- data/lib/aws-reporting.rb +30 -0
- data/lib/aws-reporting/alarm.rb +36 -0
- data/lib/aws-reporting/command/config.rb +75 -0
- data/lib/aws-reporting/command/run.rb +35 -0
- data/lib/aws-reporting/command/serve.rb +31 -0
- data/lib/aws-reporting/command/version.rb +11 -0
- data/lib/aws-reporting/config.rb +24 -0
- data/lib/aws-reporting/error.rb +9 -0
- data/lib/aws-reporting/generator.rb +186 -0
- data/lib/aws-reporting/helper.rb +3 -0
- data/lib/aws-reporting/plan.rb +57 -0
- data/lib/aws-reporting/resolver/ebs.rb +32 -0
- data/lib/aws-reporting/resolver/ec2.rb +32 -0
- data/lib/aws-reporting/resolvers.rb +29 -0
- data/lib/aws-reporting/server.rb +18 -0
- data/lib/aws-reporting/statistics.rb +43 -0
- data/lib/aws-reporting/store.rb +35 -0
- data/lib/aws-reporting/version.rb +9 -0
- data/metrics/metrics.csv +220 -0
- data/metrics/metrics.yaml +1127 -0
- data/template/css/nightmare.css +209 -0
- data/template/img/logo.png +0 -0
- data/template/index.html +41 -0
- data/template/js/graph.js +159 -0
- data/template/js/gui.js +294 -0
- data/template/js/legend.js +51 -0
- data/template/js/lib/d3.min.js +5 -0
- data/template/js/lib/jquery-1.11.1.min.js +4 -0
- data/template/js/lib/jquery.hashchange.min.js +5 -0
- metadata +140 -0
    
        data/bin/aws-reporting
    ADDED
    
    | @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path('../../lib/aws-reporting', __FILE__)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            slop = Slop.new(:strict => true) do
         | 
| 6 | 
            +
              command 'config' do
         | 
| 7 | 
            +
                banner "Usage: aws-reporting config [-h] [-f] [--access-key-id ACCESS_KEY_ID --secret-access-key SECRET_ACCESS_KEY]"
         | 
| 8 | 
            +
                on 'h', 'help', "Show this messages"
         | 
| 9 | 
            +
                on 'f', 'force', "Force output config file"
         | 
| 10 | 
            +
                on 'access-key-id=', "AWS Access Key ID"
         | 
| 11 | 
            +
                on 'secret-access-key=', "AWS Secret Access Key"
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                run do |opts, args|
         | 
| 14 | 
            +
                  AwsReporting::Command::Config.run(opts, args) 
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              command 'run' do
         | 
| 19 | 
            +
                banner "Usage: aws-reporting run [-f] REPORT_PATH"
         | 
| 20 | 
            +
                on 'h', 'help', "Show this messages"
         | 
| 21 | 
            +
                on 'f', 'force', "Force output report"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                run do |opts, args|
         | 
| 24 | 
            +
                  AwsReporting::Command::Run.run(opts, args) 
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              command 'serve' do
         | 
| 29 | 
            +
                banner "Usage: aws-reporting serve [-p PORT] REPORT_PATH"
         | 
| 30 | 
            +
                on 'h', 'help', "Show this messages"
         | 
| 31 | 
            +
                on 'p=', 'port=', 'Port to listen on'
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                run do |opts, args|
         | 
| 34 | 
            +
                  AwsReporting::Command::Serve.run(opts, args) 
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              command 'version' do
         | 
| 39 | 
            +
                run do |opts, args|
         | 
| 40 | 
            +
                  AwsReporting::Command::Version.run(opts, args) 
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              run do |opts, args|
         | 
| 45 | 
            +
                puts opts.help
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
            end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            begin
         | 
| 50 | 
            +
              slop.parse
         | 
| 51 | 
            +
            rescue Slop::Error => e
         | 
| 52 | 
            +
              puts e.message
         | 
| 53 | 
            +
              puts slop
         | 
| 54 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            $LOAD_PATH.push File.expand_path('../aws-reporting', __FILE__)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # standard libraries
         | 
| 4 | 
            +
            require 'yaml'
         | 
| 5 | 
            +
            require 'fileutils'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            # 3rd party libraries
         | 
| 8 | 
            +
            require 'slop'
         | 
| 9 | 
            +
            require 'aws-sdk'
         | 
| 10 | 
            +
            require 'formatador'
         | 
| 11 | 
            +
            require 'parallel'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            # aws-reporting files
         | 
| 14 | 
            +
            require 'error'
         | 
| 15 | 
            +
            require 'version'
         | 
| 16 | 
            +
            require 'server'
         | 
| 17 | 
            +
            require 'generator'
         | 
| 18 | 
            +
            require 'plan'
         | 
| 19 | 
            +
            require 'config'
         | 
| 20 | 
            +
            require 'command/config'
         | 
| 21 | 
            +
            require 'command/run'
         | 
| 22 | 
            +
            require 'command/serve'
         | 
| 23 | 
            +
            require 'command/version'
         | 
| 24 | 
            +
            require 'resolvers'
         | 
| 25 | 
            +
            require 'resolver/ec2'
         | 
| 26 | 
            +
            require 'resolver/ebs'
         | 
| 27 | 
            +
            require 'helper'
         | 
| 28 | 
            +
            require 'alarm'
         | 
| 29 | 
            +
            require 'statistics'
         | 
| 30 | 
            +
            require 'store'
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              module Alarm
         | 
| 3 | 
            +
                def serialize(dimensions)
         | 
| 4 | 
            +
                  dimensions.sort_by{|dimension| dimension[:name]}.map{|dimension| dimension[:name] + "=>" + dimension[:value]}.join(',')
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def get_alarm_info(region, alarm)
         | 
| 8 | 
            +
                  info = {:name => alarm.name,
         | 
| 9 | 
            +
                          :region => region,
         | 
| 10 | 
            +
                          :namespace => alarm.namespace,
         | 
| 11 | 
            +
                          :dimensions => alarm.dimensions,
         | 
| 12 | 
            +
                          :metric_name => alarm.metric_name,
         | 
| 13 | 
            +
                          :status => get_status(alarm)}
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def get_status(alarm)
         | 
| 17 | 
            +
                  return :ALARM if alarm.state_value == 'ALARM'
         | 
| 18 | 
            +
                  return :ALARM if alarm.history_items.to_a.select{|history| history.history_item_type == 'StateUpdate'}.length > 0
         | 
| 19 | 
            +
                  return :OK
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def get_alarms()
         | 
| 23 | 
            +
                  alarms = []
         | 
| 24 | 
            +
                  AWS.regions.each{|r|
         | 
| 25 | 
            +
                    Config.update_region(r.name)
         | 
| 26 | 
            +
                    cw = AWS::CloudWatch.new
         | 
| 27 | 
            +
                    cw.alarms.each do |alarm|
         | 
| 28 | 
            +
                      alarms << get_alarm_info(r.name, alarm)
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  }
         | 
| 31 | 
            +
                  alarms.sort_by{|alarm| [alarm[:namespace], serialize(alarm[:dimensions]), alarm[:metric_name], alarm[:name]].join(' ')}
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                module_function :get_alarms
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,75 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              module Command
         | 
| 3 | 
            +
                module Config
         | 
| 4 | 
            +
                  DEFAULT_PATH = '~/.aws-reporting/config.yaml'
         | 
| 5 | 
            +
                  MESSAGE_ALREADY_EXIST = " already exists. If you want to overwrite this, use '-f' option."
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def run(opts, args)
         | 
| 8 | 
            +
                    Signal.trap(:INT){
         | 
| 9 | 
            +
                      puts
         | 
| 10 | 
            +
                      puts "interrupted."
         | 
| 11 | 
            +
                      exit
         | 
| 12 | 
            +
                    }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    help = opts['h']
         | 
| 15 | 
            +
                    if help
         | 
| 16 | 
            +
                      puts opts.help
         | 
| 17 | 
            +
                      return
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    begin
         | 
| 21 | 
            +
                      access = opts['access-key-id']
         | 
| 22 | 
            +
                      secret = opts['secret-access-key']
         | 
| 23 | 
            +
                      force = opts['f']
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      if access and secret
         | 
| 26 | 
            +
                        run_batch(access, secret, force)
         | 
| 27 | 
            +
                      elsif !!!access and !!!secret
         | 
| 28 | 
            +
                        run_interactive(force)
         | 
| 29 | 
            +
                      else
         | 
| 30 | 
            +
                        raise CommandArgumentError.new
         | 
| 31 | 
            +
                      end
         | 
| 32 | 
            +
                    rescue AwsReporting::Error::CommandArgumentError
         | 
| 33 | 
            +
                      puts opts.help
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def run_batch(access, secret, force)
         | 
| 38 | 
            +
                    path = File.expand_path(DEFAULT_PATH)
         | 
| 39 | 
            +
                    if force or !File.exist?(path)
         | 
| 40 | 
            +
                      update_config(access, secret, path)
         | 
| 41 | 
            +
                      puts 'done.'
         | 
| 42 | 
            +
                    else
         | 
| 43 | 
            +
                      puts path + MESSAGE_ALREADY_EXIST
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def run_interactive(force)
         | 
| 48 | 
            +
                    path = File.expand_path(DEFAULT_PATH)
         | 
| 49 | 
            +
                    if force or !File.exist?(path)
         | 
| 50 | 
            +
                      print 'Access Key ID    :'
         | 
| 51 | 
            +
                      access = $stdin.gets.chomp
         | 
| 52 | 
            +
                      print 'Secret Access Key:'
         | 
| 53 | 
            +
                      secret = $stdin.gets.chomp
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      update_config(access, secret, path)
         | 
| 56 | 
            +
                      puts 'done.'
         | 
| 57 | 
            +
                    else
         | 
| 58 | 
            +
                      puts path + MESSAGE_ALREADY_EXIST
         | 
| 59 | 
            +
                    end
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def update_config(access, secret, path)
         | 
| 63 | 
            +
                    yaml = YAML.dump(:access_key_id => access, :secret_access_key => secret)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    FileUtils.mkdir_p(File.dirname(path))
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    open(path, 'w'){|f|
         | 
| 68 | 
            +
                      f.print yaml
         | 
| 69 | 
            +
                    }
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  module_function :run, :run_batch, :run_interactive, :update_config
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              module Command
         | 
| 3 | 
            +
                module Run
         | 
| 4 | 
            +
                  MESSAGE_ALREADY_EXIST = " already exists. If you want to overwrite this, use '-f' option."
         | 
| 5 | 
            +
                  MESSAGE_NOT_CONFIGURED = "Can not access config file. Run `aws-reporting config` command first."
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def run(opts, args)
         | 
| 8 | 
            +
                    begin
         | 
| 9 | 
            +
                      help = opts['h']
         | 
| 10 | 
            +
                      if help
         | 
| 11 | 
            +
                        puts opts.help
         | 
| 12 | 
            +
                        return
         | 
| 13 | 
            +
                      end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                      force = opts['f']
         | 
| 16 | 
            +
                      raise AwsReporting::Error::CommandArgumentError.new unless args.length == 1
         | 
| 17 | 
            +
                      path = args[0]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      generator = AwsReporting::Generator.new
         | 
| 20 | 
            +
                      generator.path = path
         | 
| 21 | 
            +
                      generator.force = force
         | 
| 22 | 
            +
                      generator.generate
         | 
| 23 | 
            +
                    rescue AwsReporting::Error::CommandArgumentError
         | 
| 24 | 
            +
                      puts opts.help
         | 
| 25 | 
            +
                    rescue AwsReporting::Error::OverwriteError => e
         | 
| 26 | 
            +
                      puts e.path + MESSAGE_ALREADY_EXIST
         | 
| 27 | 
            +
                    rescue AwsReporting::Error::ConfigFileLoadError
         | 
| 28 | 
            +
                      puts MESSAGE_NOT_CONFIGURED
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  module_function :run
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              module Command
         | 
| 3 | 
            +
                module Serve
         | 
| 4 | 
            +
                  def run(opts, args)
         | 
| 5 | 
            +
                    begin
         | 
| 6 | 
            +
                      help = opts['h']
         | 
| 7 | 
            +
                      if help
         | 
| 8 | 
            +
                        puts opts.help
         | 
| 9 | 
            +
                        return
         | 
| 10 | 
            +
                      end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      port = opts['port'] || 23456
         | 
| 13 | 
            +
                      raise AwsReporting::Error::CommandArgumentError.new unless args.length == 1
         | 
| 14 | 
            +
                      path = args[0]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      server = AwsReporting::Server.new(path, port)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      Signal.trap(:INT){
         | 
| 19 | 
            +
                        server.stop
         | 
| 20 | 
            +
                      }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      server.start
         | 
| 23 | 
            +
                    rescue AwsReporting::Error::CommandArgumentError
         | 
| 24 | 
            +
                      puts opts.help
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  module_function :run
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              class Config
         | 
| 3 | 
            +
                def self.config_file_path()
         | 
| 4 | 
            +
                  File.expand_path('~/.aws-reporting/config.yaml')
         | 
| 5 | 
            +
                end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def self.load()
         | 
| 8 | 
            +
                  @@config = YAML.load(open(config_file_path()){|f| f.read})
         | 
| 9 | 
            +
                rescue
         | 
| 10 | 
            +
                  raise AwsReporting::Error::ConfigFileLoadError.new
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def self.update_region(region)
         | 
| 14 | 
            +
                  AWS.config(:access_key_id => @@config[:access_key_id],
         | 
| 15 | 
            +
                             :secret_access_key => @@config[:secret_access_key],
         | 
| 16 | 
            +
                             :region => region)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def self.get()
         | 
| 20 | 
            +
                  AWS.config(:access_key_id => @@config[:access_key_id],
         | 
| 21 | 
            +
                             :secret_access_key => @@config[:secret_access_key])
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| @@ -0,0 +1,186 @@ | |
| 1 | 
            +
            module AwsReporting
         | 
| 2 | 
            +
              class Generator
         | 
| 3 | 
            +
                attr_accessor :path, :force
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                def format_path(path)
         | 
| 6 | 
            +
                  path.split('/')[-2..-1]
         | 
| 7 | 
            +
                      .join('/')
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def transform(metrics, name_resolvers)
         | 
| 11 | 
            +
                  temp = Hash.new{|h, k| h[k] = Hash.new{|h, k| h[k] = [] }}
         | 
| 12 | 
            +
                  metrics.each{|namespace, value|
         | 
| 13 | 
            +
                    value.each{|identification, files|
         | 
| 14 | 
            +
                      element =  {:region => identification[:region],
         | 
| 15 | 
            +
                                  :namespace => namespace,
         | 
| 16 | 
            +
                                  :dimensions => identification[:dimensions],
         | 
| 17 | 
            +
                                  :files => files.sort_by{|entry| entry[:info][:metric_name]}.map{|entry| format_path(entry[:path])}}
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      element[:name] = name_resolvers.get_name(element)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                      dimension_type = identification[:dimensions].map{|item| item[:name]}.sort
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      temp[namespace][dimension_type] << element
         | 
| 24 | 
            +
                    }
         | 
| 25 | 
            +
                  }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  temp2 = Hash.new{|h, k| h[k] = [] }
         | 
| 28 | 
            +
                  temp.each{|namespace, dimension_table|
         | 
| 29 | 
            +
                    dimension_table.each{|dimension_type, elements| 
         | 
| 30 | 
            +
                      temp2[namespace] << {:dimension_type => dimension_type,
         | 
| 31 | 
            +
                                           :elements => elements}
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  result = []
         | 
| 36 | 
            +
                  temp2.each{|namespace, dimension_table|
         | 
| 37 | 
            +
                    result << {:namespace => namespace, :dimension_table => dimension_table}
         | 
| 38 | 
            +
                  }
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  sort_result!(result)
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  result
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def sort_result!(result)
         | 
| 46 | 
            +
                  result.sort_by!{|namespace_table| namespace_table[:namespace]}
         | 
| 47 | 
            +
                  result.each{|namespace_table|
         | 
| 48 | 
            +
                    namespace_table[:dimension_table].sort_by!{|dimension_table| dimension_table[:dimension_type].join(' ')}
         | 
| 49 | 
            +
                  }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  result.each{|namespace_table|
         | 
| 52 | 
            +
                    namespace_table[:dimension_table].each{|dimension_table|
         | 
| 53 | 
            +
                      dimension_type = dimension_table[:dimension_type]
         | 
| 54 | 
            +
                      dimension_table[:elements].sort_by!{|element| expand(dimension_type, element[:dimensions]) }
         | 
| 55 | 
            +
                    }
         | 
| 56 | 
            +
                  }
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def expand(dimension_type, dimensions)
         | 
| 60 | 
            +
                  dimension_hash = {}
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  dimensions.each{|dimension|
         | 
| 63 | 
            +
                    dimension_hash[dimension[:name]] = dimension[:value]
         | 
| 64 | 
            +
                  }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  values = []
         | 
| 67 | 
            +
                  dimension_type.each{|dimension_name|
         | 
| 68 | 
            +
                    values << dimension_hash[dimension_name] 
         | 
| 69 | 
            +
                  }
         | 
| 70 | 
            +
                  values.join(' ')
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def merge_status(s0, s1)
         | 
| 74 | 
            +
                  if s0 == nil or s1 == nil
         | 
| 75 | 
            +
                    s0 || s1
         | 
| 76 | 
            +
                  else
         | 
| 77 | 
            +
                    if s0 == :ALARM or s1 == :ALARM
         | 
| 78 | 
            +
                      'ALARM'
         | 
| 79 | 
            +
                    else
         | 
| 80 | 
            +
                      'OK'
         | 
| 81 | 
            +
                    end
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                def build_alarm_tree(alarms)
         | 
| 86 | 
            +
                  alarm_tree = {}
         | 
| 87 | 
            +
                  alarms.each{|alarm|
         | 
| 88 | 
            +
                    key = {:region => alarm[:region],
         | 
| 89 | 
            +
                           :namespace => alarm[:namespace],
         | 
| 90 | 
            +
                           :dimensions => alarm[:dimensions],
         | 
| 91 | 
            +
                           :metric_name => alarm[:metric_name]}
         | 
| 92 | 
            +
                    alarm_tree[key] = merge_status(alarm_tree[key], alarm[:status])
         | 
| 93 | 
            +
                  }
         | 
| 94 | 
            +
                  alarm_tree
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def set_status(data, alarm_tree)
         | 
| 98 | 
            +
                  key = {:region => data[:info][:region],
         | 
| 99 | 
            +
                         :namespace => data[:info][:namespace],
         | 
| 100 | 
            +
                         :dimensions => data[:info][:dimensions],
         | 
| 101 | 
            +
                         :metric_name => data[:info][:metric_name]}
         | 
| 102 | 
            +
                  data[:info][:status] = alarm_tree[key] if alarm_tree[key]
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                def download(base_path, plan, start_time, end_time, period, name_resolvers, timestamp)
         | 
| 106 | 
            +
                  metrics = Hash.new{|h, k| h[k] = Hash.new{|h, k| h[k] = []}}
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  alarms = AwsReporting::Alarm.get_alarms()
         | 
| 109 | 
            +
                  alarm_tree = build_alarm_tree(alarms)
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  mutex = Mutex.new
         | 
| 112 | 
            +
                  started_at = Time.now
         | 
| 113 | 
            +
                  num_of_metrics = plan.length
         | 
| 114 | 
            +
                  num_of_downloaded = 0
         | 
| 115 | 
            +
                  Parallel.each_with_index(plan, :in_threads => 8){|entry, i|
         | 
| 116 | 
            +
                    namespace = entry[:namespace]
         | 
| 117 | 
            +
                    metric_name = entry[:metric_name]
         | 
| 118 | 
            +
                    dimensions = entry[:dimensions]
         | 
| 119 | 
            +
                    statistics = entry[:statistics]
         | 
| 120 | 
            +
                    region = entry[:region]
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    mutex.synchronize do
         | 
| 123 | 
            +
                      num_of_downloaded += 1
         | 
| 124 | 
            +
                      Formatador.redisplay_progressbar(num_of_downloaded, num_of_metrics, {:started_at => started_at})
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                    data = AwsReporting::Statistics.get(region, namespace, metric_name, start_time, end_time, period, dimensions, statistics)
         | 
| 128 | 
            +
                    set_status(data, alarm_tree)
         | 
| 129 | 
            +
                    file = AwsReporting::Store.save(base_path, data)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    identification = {:dimensions => dimensions, :region => region}
         | 
| 132 | 
            +
                    metrics[namespace][identification] << file
         | 
| 133 | 
            +
                  }
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                  report_info = {:start_time => start_time.to_s,
         | 
| 136 | 
            +
                                 :end_time => end_time.to_s,
         | 
| 137 | 
            +
                                 :period => period.to_s,
         | 
| 138 | 
            +
                                 :timestamp => timestamp.to_s,
         | 
| 139 | 
            +
                                 :num_of_metrics => plan.length.to_s,
         | 
| 140 | 
            +
                                 :version => Version.get}
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  open(base_path + '/metrics.json', 'w'){|f|
         | 
| 143 | 
            +
                    f.print JSON.dump({:report_info => report_info, :metrics => transform(metrics, name_resolvers), :alarms => alarms})
         | 
| 144 | 
            +
                  }
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                def copy_template(path, force)
         | 
| 148 | 
            +
                  report_path = File.expand_path(path)
         | 
| 149 | 
            +
                  if force != true and File.exist?(path)
         | 
| 150 | 
            +
                    error = AwsReporting::Error::OverwriteError.new
         | 
| 151 | 
            +
                    error.path = report_path
         | 
| 152 | 
            +
                    raise error
         | 
| 153 | 
            +
                  end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
                  template_path = File.expand_path('../../../template', __FILE__)
         | 
| 156 | 
            +
                  template_files = Dir.glob(template_path + '/*')
         | 
| 157 | 
            +
                  FileUtils.mkdir_p(report_path)
         | 
| 158 | 
            +
                  FileUtils.cp_r(template_files, report_path)
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                def generate
         | 
| 162 | 
            +
                  timestamp = Time.now
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  AwsReporting::Config.load()
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                  puts 'Report generating started.'
         | 
| 167 | 
            +
                  copy_template(@path, @force)
         | 
| 168 | 
            +
                  data_dir = @path + '/data'
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                  puts '(1/3) Planning...'
         | 
| 171 | 
            +
                  plan = Plan.generate
         | 
| 172 | 
            +
                  puts "Planning complete."
         | 
| 173 | 
            +
                  start_time = Time.now - 24 * 60 * 60 * 14
         | 
| 174 | 
            +
                  end_time = Time.now
         | 
| 175 | 
            +
                  period = 60 * 60
         | 
| 176 | 
            +
                  puts '(2/3) Building name tables...'
         | 
| 177 | 
            +
                  name_resolvers = AwsReporting::Resolvers.new
         | 
| 178 | 
            +
                  name_resolvers.init
         | 
| 179 | 
            +
                  puts 'Name tables were builded.'
         | 
| 180 | 
            +
                  puts '(3/3) Downloading metrics...'
         | 
| 181 | 
            +
                  download(data_dir, plan, start_time, end_time, period, name_resolvers, timestamp)
         | 
| 182 | 
            +
                  puts 'Downloading metrics done.'
         | 
| 183 | 
            +
                  puts 'Report generating complete!'
         | 
| 184 | 
            +
                end
         | 
| 185 | 
            +
              end
         | 
| 186 | 
            +
            end
         |