├── .gitignore ├── .travis.yml ├── Gemfile ├── Gemfile.fluentd.0.12 ├── LICENSE ├── README.md ├── Rakefile ├── fluent-plugin-cloudwatch.gemspec ├── lib └── fluent │ └── plugin │ └── in_cloudwatch.rb └── test ├── helper.rb └── plugin └── test_in_cloudwatch.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | before_install: 4 | - gem update bundler 5 | 6 | rvm: 7 | - 2.1.* 8 | - 2.2.* 9 | - 2.3.8 10 | - 2.4.5 11 | - 2.5.3 12 | gemfile: 13 | - Gemfile 14 | - Gemfile.fluentd.0.12 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in fluent-plugin-cloudwatch.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Gemfile.fluentd.0.12: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | gem 'fluentd', '~> 0.12.0' 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Yusuke Nomura 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fluent-plugin-cloudwatch, a plugin for [Fluentd](http://fluentd.org) [![Build Status](https://travis-ci.org/yunomu/fluent-plugin-cloudwatch.png)](https://travis-ci.org/yunomu/fluent-plugin-cloudwatch/) 2 | 3 | 4 | ## Overview 5 | 6 | ***AWS CloudWatch*** input plugin. 7 | 8 | This plugin is simple. 9 | Get metrics from cloudwatch to fluentd. 10 | 11 | * Get metrics from AWS CloudWatch API. 12 | * Interval is 300(default. config=interval) seconds 13 | * Fetch datapoints in recent (interval * 10) seconds, and emit the latest datapoint to Fluentd data stream. 14 | 15 | ## Configuration 16 | 17 | ```config 18 | 19 | @type cloudwatch 20 | tag cloudwatch 21 | aws_key_id YOUR_AWS_KEY_ID 22 | aws_sec_key YOUR_AWS_SECRET_KEY 23 | cw_endpoint ENDPOINT 24 | 25 | namespace [namespace] 26 | statistics [statistics] (default: Average) 27 | metric_name [metric name] 28 | dimensions_name [dimensions_name] 29 | dimensions_value [dimensions value] 30 | period [period] (default: 300) 31 | interval [interval] (default: 300) 32 | delayed_start [bool] (default: false) 33 | emit_zero [bool] (default: false) 34 | 35 | ``` 36 | 37 | ### GET RDS Metric 38 | 39 | ```config 40 | 41 | @type cloudwatch 42 | tag cloudwatch 43 | aws_key_id YOUR_AWS_KEY_ID 44 | aws_sec_key YOUR_AWS_SECRET_KEY 45 | cw_endpoint monitoring.ap-northeast-1.amazonaws.com 46 | 47 | namespace AWS/RDS 48 | metric_name CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput 49 | dimensions_name DBInstanceIdentifier 50 | dimensions_value rds01 51 | 52 | 53 | 54 | @type copy 55 | 56 | @type file 57 | path /var/log/td-agent/test 58 | 59 | 60 | 61 | ``` 62 | 63 | #### output data format 64 | 65 | ``` 66 | 2013-02-24T13:40:00+09:00 cloudwatch {"CPUUtilization":2.0} 67 | 2013-02-24T13:40:00+09:00 cloudwatch {"FreeStorageSpace":104080723968.0} 68 | 2013-02-24T13:39:00+09:00 cloudwatch {"DiskQueueDepth":0.002000233360558732} 69 | 2013-02-24T13:40:00+09:00 cloudwatch {"FreeableMemory":6047948800.0} 70 | 2013-02-24T13:40:00+09:00 cloudwatch {"SwapUsage":0.0} 71 | 2013-02-24T13:40:00+09:00 cloudwatch {"ReadIOPS":0.4832769510223807} 72 | 2013-02-24T13:40:00+09:00 cloudwatch {"ReadLatency":0.0} 73 | 2013-02-24T13:39:00+09:00 cloudwatch {"ReadThroughput":0.0} 74 | 2013-02-24T13:40:00+09:00 cloudwatch {"WriteIOPS":5.116069791857616} 75 | 2013-02-24T13:40:00+09:00 cloudwatch {"WriteLatency":0.004106280193236715} 76 | 2013-02-24T13:39:00+09:00 cloudwatch {"WriteThroughput":54074.40992132284} 77 | ``` 78 | 79 | 80 | ### GET ELB Metirc 81 | 82 | ```config 83 | 84 | @type cloudwatch 85 | tag cloudwatch 86 | aws_key_id YOUR_AWS_KEY_ID 87 | aws_sec_key YOUR_AWS_SECRET_KEY 88 | cw_endpoint monitoring.ap-northeast-1.amazonaws.com 89 | 90 | namespace AWS/ELB 91 | metric_name HealthyHostCount,HTTPCode_Backend_2XX,HTTPCode_Backend_3XX,HTTPCode_Backend_4XX,HTTPCode_Backend_5XX,HTTPCode_ELB_4XX,Latency,RequestCount,UnHealthyHostCount 92 | dimensions_name LoadBalancerName 93 | dimensions_value YOUR_ELB_NAME 94 | 95 | ``` 96 | 97 | #### output data format 98 | 99 | ``` 100 | 2013-03-21T14:08:00+09:00 cloudwatch {"HealthyHostCount":2.0} 101 | 2013-03-21T14:08:00+09:00 cloudwatch {"HTTPCode_Backend_2XX":1.0} 102 | 2013-03-21T14:08:00+09:00 cloudwatch {"Latency":0.004025} 103 | 2013-03-21T14:08:00+09:00 cloudwatch {"RequestCount":1.0} 104 | 2013-03-21T14:09:00+09:00 cloudwatch {"UnHealthyHostCount":0.0} 105 | ``` 106 | 107 | 108 | ### GET EC2 Metirc 109 | 110 | ```config 111 | 112 | @type cloudwatch 113 | tag cloudwatch 114 | aws_key_id YOUR_AWS_KEY_ID 115 | aws_sec_key YOUR_AWS_SECRET_KEY 116 | cw_endpoint monitoring.ap-northeast-1.amazonaws.com 117 | 118 | namespace AWS/EC2 119 | metric_name CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput 120 | dimensions_name InstanceId 121 | dimensions_value YOUR_INSTANCE_ID 122 | 123 | ``` 124 | 125 | #### output data format 126 | 127 | ``` 128 | 2013-02-25T00:44:00+09:00 cloudwatch {"CPUUtilization":1.58} 129 | 2013-02-25T00:44:00+09:00 cloudwatch {"DiskReadBytes":0.0} 130 | 2013-02-25T00:44:00+09:00 cloudwatch {"DiskReadBytes":0.0} 131 | 2013-02-25T00:44:00+09:00 cloudwatch {"DiskWriteBytes":0.0} 132 | 2013-02-25T00:44:00+09:00 cloudwatch {"DiskWriteOps":0.0} 133 | 2013-02-25T00:44:00+09:00 cloudwatch {"NetworkIn":95183.0} 134 | 2013-02-25T00:44:00+09:00 cloudwatch {"NetworkOut":95645.0} 135 | ``` 136 | 137 | ### GET DynamoDB Metirc 138 | 139 | ```config 140 | @type cloudwatch 141 | tag cloudwatch 142 | aws_key_id YOUR_AWS_KEY_ID 143 | aws_sec_key YOUR_AWS_SECRET_KEY 144 | cw_endpoint monitoring.ap-northeast-1.amazonaws.com 145 | 146 | namespace AWS/DynamoDB 147 | metric_name ConsumedReadCapacityUnits,ConsumedWriteCapacityUnits 148 | dimensions_name TableName 149 | dimensions_value some_dd_tablename 150 | statistics Sum 151 | interval 300 152 | period 300 153 | ``` 154 | 155 | #### output data format 156 | 157 | ``` 158 | 2013-04-11 15:13:00 +0900 cloudwatch {"ConsumedReadCapacityUnits":8271.5} 159 | 2013-04-11 15:13:00 +0900 cloudwatch {"ConsumedWriteCapacityUnits":2765.5} 160 | ``` 161 | 162 | ### GET Billing Metirc 163 | 164 | Note: Billing requires the us-east-1 endpoint 165 | ```config 166 | @type cloudwatch 167 | tag cloudwatch 168 | aws_key_id YOUR_AWS_KEY_ID 169 | aws_sec_key YOUR_AWS_SECRET_KEY 170 | cw_endpoint monitoring.us-east-1.amazonaws.com 171 | 172 | namespace AWS/Billing 173 | metric_name EstimatedCharges 174 | dimensions_name Currency 175 | dimensions_value USD 176 | statistics Average 177 | interval 7200 178 | period 21600 179 | ``` 180 | 181 | #### output data format 182 | 183 | ``` 184 | 2013-06-10 02:03:00 +0900 cloudwatch {"EstimatedCharges_in_USD":"543.175"} 185 | 2013-06-10 04:03:00 +0900 cloudwatch {"EstimatedCharges_in_USD":"550.39"} 186 | ``` 187 | 188 | ### GET StorageGateway Metirc 189 | 190 | ```config 191 | @type cloudwatch 192 | tag cloudwatch 193 | aws_key_id YOUR_AWS_KEY_ID 194 | aws_sec_key YOUR_AWS_SECRET_KEY 195 | cw_endpoint monitoring.us-east-1.amazonaws.com 196 | 197 | namespace AWS/StorageGateway 198 | metric_name CacheHitPercent,CachePercentUsed 199 | dimensions_name GatewayId,GatewayName 200 | dimensions_value sgw-XXXXXXXX,mygateway 201 | statistics Average 202 | ``` 203 | 204 | #### output data format 205 | 206 | ``` 207 | 2014-01-20 20:12:00 +0900 cloudwatch: {"CacheHitPercent":0.0} 208 | 2014-01-20 20:12:00 +0900 cloudwatch: {"CachePercentUsed":95.15519175634687} 209 | ``` 210 | 211 | ## config: Complex metric_name 212 | 213 | `metric_name` format is allowed as below. 214 | - `MetricName` 215 | - `MetricName:Statstics` 216 | 217 | For example, this configuration fetches "Sum of RequestCount" and "Average of Latancy". 218 | 219 | ``` 220 | metric_name RequestCount,Latency:Average 221 | statistics Sum 222 | ``` 223 | 224 | ## config: delayed_start 225 | 226 | When config `delayed_start` is set true, plugin startup will be delayed in random seconds(0 ~ interval). 227 | 228 | ## config: offset 229 | 230 | unit: seconds. 231 | 232 | flunet-plugin-cloudwatch gets metrics between now and `period` × 10 sec ago, and pick a latest value from that. 233 | 234 | But the latest metric is insufficient for `statistics Sum`. 235 | 236 | If `offset` is specified, fluent-plugin-cloudwatch gets metrics between `offset` sec ago and older. 237 | 238 | ## config: emit_zero 239 | 240 | If `emit_zero` is true and cloudwatch datapoint is empty, fluent-plugin-cloudwatch emits 0 instead of warn log "datapoint is empty". 241 | 242 | ## config: record_attr 243 | 244 | `record_attr` is an optional value injected into each records. 245 | 246 | ``` 247 | 248 | @type cloudwatch 249 | tag cloudwatch.rds 250 | aws_key_id YOUR_AWS_KEY_ID 251 | aws_sec_key YOUR_AWS_SECRET_KEY 252 | cw_endpoint monitoring.ap-northeast-1.amazonaws.com 253 | 254 | namespace AWS/RDS 255 | metric_name CPUUtilization,FreeStorageSpace 256 | dimensions_name DBInstanceIdentifier 257 | dimensions_value rds01 258 | record_attr DBInstanceIdentifier:rds01 259 | # JSON format 260 | # record_attr {"DBInstanceIdentifier":"rds01"} 261 | 262 | ``` 263 | 264 | Example output. 265 | 266 | ``` 267 | 2017-11-04T13:40:00+09:00 cloudwatch.rds {"CPUUtilization":2.0,"DBInstanceIdentifier":"rds01"} 268 | 2013-11-04T13:40:00+09:00 cloudwatch.rds {"FreeStorageSpace":104080723968.0,"DBInstanceIdentifier":"rds01"} 269 | ``` 270 | 271 | 272 | ## Contributing 273 | 274 | 1. Fork it 275 | 2. Create your feature branch (`git checkout -b my-new-feature`) 276 | 3. Commit your changes (`git commit -am 'Added some feature'`) 277 | 4. Push to the branch (`git push origin my-new-feature`) 278 | 5. Create new Pull Request 279 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | require "bundler/gem_tasks" 3 | 4 | require "rake/testtask" 5 | Rake::TestTask.new(:test) do |test| 6 | test.libs << 'lib' << 'test' 7 | test.pattern = 'test/**/test_*.rb' 8 | test.verbose = true 9 | end 10 | 11 | task :default => :test 12 | -------------------------------------------------------------------------------- /fluent-plugin-cloudwatch.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | 5 | Gem::Specification.new do |gem| 6 | gem.name = "fluent-plugin-cloudwatch" 7 | gem.version = "2.1.1" 8 | gem.authors = ["Yusuke Nomura", "kenjiskywalker", "FUJIWARA Shunichiro"] 9 | gem.email = ["yunomu@gmail.com", "git@kenjiskywalker.org", "fujiwara.shunichiro@gmail.com"] 10 | gem.description = %q{Input plugin for AWS CloudWatch.} 11 | gem.homepage = "https://github.com/yunomu/fluent-plugin-cloudwatch" 12 | gem.summary = gem.description 13 | gem.files = `git ls-files`.split($\) 14 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 15 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 16 | gem.require_paths = ["lib"] 17 | gem.add_dependency "fluentd", ">= 0.10.30" 18 | gem.add_dependency "aws-sdk-cloudwatch", "~> 1" 19 | gem.add_development_dependency "rake", ">= 0.9.2" 20 | gem.add_development_dependency "test-unit", ">= 3.1.0" 21 | gem.license = 'MIT' 22 | end 23 | -------------------------------------------------------------------------------- /lib/fluent/plugin/in_cloudwatch.rb: -------------------------------------------------------------------------------- 1 | require 'fluent/input' 2 | require 'aws-sdk-cloudwatch' 3 | require 'uri' 4 | 5 | class Fluent::CloudwatchInput < Fluent::Input 6 | Fluent::Plugin.register_input("cloudwatch", self) 7 | 8 | # To support log_level option implemented by Fluentd v0.10.43 9 | unless method_defined?(:log) 10 | define_method("log") { $log } 11 | end 12 | 13 | # Define `router` method of v0.12 to support v0.10 or earlier 14 | unless method_defined?(:router) 15 | define_method("router") { Fluent::Engine } 16 | end 17 | 18 | config_param :tag, :string 19 | config_param :aws_key_id, :string, :default => nil, :secret => true 20 | config_param :aws_sec_key, :string, :default => nil, :secret => true 21 | config_param :cw_endpoint, :string, :default => nil 22 | config_param :region, :string, :default => nil 23 | 24 | config_param :namespace, :string, :default => nil 25 | config_param :metric_name, :string, :default => nil 26 | config_param :statistics, :string, :default => "Average" 27 | config_param :dimensions_name, :string, :default => nil 28 | config_param :dimensions_value, :string, :default => nil 29 | config_param :period, :integer, :default => 300 30 | config_param :interval, :integer, :default => 300 31 | config_param :open_timeout, :integer, :default => 10 32 | config_param :read_timeout, :integer, :default => 30 33 | config_param :delayed_start, :bool, :default => false 34 | config_param :offset, :integer, :default => 0 35 | config_param :emit_zero, :bool, :default => false 36 | config_param :record_attr, :hash, :default => {} 37 | 38 | attr_accessor :dimensions 39 | 40 | def initialize 41 | super 42 | end 43 | 44 | def configure(conf) 45 | super 46 | 47 | @dimensions = [] 48 | if @dimensions_name && @dimensions_value 49 | names = @dimensions_name.split(",").each 50 | values = @dimensions_value.split(",").each 51 | loop do 52 | @dimensions.push({ 53 | :name => names.next, 54 | :value => values.next, 55 | }) 56 | end 57 | elsif @dimensions_name || @dimensions_value 58 | @dimensions.push({ 59 | :name => @dimensions_name, 60 | :value => @dimensions_value, 61 | }) 62 | end 63 | 64 | endpoint = URI(@cw_endpoint) 65 | if endpoint.scheme != "http" && endpoint.scheme != "https" 66 | @cw_endpoint_uri = "https://#{@cw_endpoint}" 67 | else 68 | @cw_endpoint_uri = endpoint.to_s 69 | end 70 | 71 | if !@region 72 | @region = @cw_endpoint.split('.')[1] 73 | end 74 | end 75 | 76 | def start 77 | super 78 | 79 | @running = true 80 | @updated = Time.now 81 | @watcher = Thread.new(&method(:watch)) 82 | @monitor = Thread.new(&method(:monitor)) 83 | @mutex = Mutex.new 84 | end 85 | 86 | def shutdown 87 | super 88 | @running = false 89 | @watcher.terminate 90 | @monitor.terminate 91 | @watcher.join 92 | @monitor.join 93 | end 94 | 95 | private 96 | 97 | # if watcher thread was not update timestamp in recent @interval * 2 sec., restarting it. 98 | def monitor 99 | log.debug "cloudwatch: monitor thread starting" 100 | while @running 101 | sleep @interval / 2 102 | @mutex.synchronize do 103 | log.debug "cloudwatch: last updated at #{@updated}" 104 | now = Time.now 105 | if @updated < now - @interval * 2 106 | log.warn "cloudwatch: watcher thread is not working after #{@updated}. Restarting..." 107 | @watcher.kill 108 | @updated = now 109 | @watcher = Thread.new(&method(:watch)) 110 | end 111 | end 112 | end 113 | end 114 | 115 | def watch 116 | log.debug "cloudwatch: watch thread starting" 117 | if @delayed_start 118 | delay = rand() * @interval 119 | log.debug "cloudwatch: delay at start #{delay} sec" 120 | sleep delay 121 | end 122 | 123 | @cw = Aws::CloudWatch::Client.new( 124 | :region => @region, 125 | :access_key_id => @aws_key_id, 126 | :secret_access_key => @aws_sec_key, 127 | :endpoint => @cw_endpoint_uri, 128 | :http_open_timeout => @open_timeout, 129 | :http_read_timeout => @read_timeout, 130 | ) 131 | output 132 | 133 | started = Time.now 134 | while @running 135 | now = Time.now 136 | sleep 1 137 | if now - started >= @interval 138 | output 139 | started = now 140 | @mutex.synchronize do 141 | @updated = Time.now 142 | end 143 | end 144 | end 145 | end 146 | 147 | def output 148 | @metric_name.split(",").each {|m| 149 | name, s = m.split(":") 150 | s ||= @statistics 151 | now = Time.now - @offset 152 | log.debug("now #{now}") 153 | statistics = @cw.get_metric_statistics({ 154 | :namespace => @namespace, 155 | :metric_name => name, 156 | :statistics => [s], 157 | :dimensions => @dimensions, 158 | :start_time => (now - @period*10).iso8601, 159 | :end_time => now.iso8601, 160 | :period => @period, 161 | }) 162 | if not statistics[:datapoints].empty? 163 | datapoint = statistics[:datapoints].sort_by{|h| h[:timestamp]}.last 164 | data = datapoint[s.downcase.to_sym] 165 | 166 | # unix time 167 | catch_time = datapoint[:timestamp].to_i 168 | router.emit(tag, catch_time, { name => data }.merge(@record_attr)) 169 | elsif @emit_zero 170 | router.emit(tag, now.to_i, { name => 0 }.merge(@record_attr)) 171 | else 172 | log.warn "cloudwatch: #{@namespace} #{@dimensions_name} #{@dimensions_value} #{name} #{s} datapoints is empty" 173 | end 174 | } 175 | end 176 | end 177 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler' 3 | require 'fluent/input' 4 | 5 | begin 6 | Bundler.setup(:default, :development) 7 | rescue Bundler::BundlerError => e 8 | $stderr.puts e.message 9 | $stderr.puts "Run `bundle install` to install missing gems" 10 | exit e.status_code 11 | end 12 | require "test/unit" 13 | 14 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) 15 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 16 | require "fluent/test" 17 | unless ENV.has_key?("VERBOSE") 18 | nulllogger = Object.new 19 | nulllogger.instance_eval {|obj| 20 | def method_missing(method, *args) 21 | #pass 22 | end 23 | } 24 | $log = nulllogger 25 | end 26 | 27 | require "fluent/plugin/in_cloudwatch" 28 | 29 | class Test::Unit::TestCase 30 | end 31 | 32 | -------------------------------------------------------------------------------- /test/plugin/test_in_cloudwatch.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class CloudwatchInputTest < Test::Unit::TestCase 4 | def setup 5 | Fluent::Test.setup 6 | end 7 | 8 | ### for RDS 9 | CONFIG_RDS = %[ 10 | tag cloudwatch 11 | aws_key_id test_key_id 12 | aws_sec_key test_sec_key 13 | cw_endpoint test_cloud_watch_endpoint 14 | namespace AWS/RDS 15 | metric_name CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput 16 | dimensions_name DBInstanceIdentifier 17 | dimensions_value rds01 18 | ] 19 | 20 | def create_driver_rds(conf = CONFIG_RDS) 21 | Fluent::Test::InputTestDriver.new(Fluent::CloudwatchInput).configure(conf) 22 | end 23 | 24 | def test_configure_rds 25 | d = create_driver_rds 26 | assert_equal 'cloudwatch', d.instance.tag 27 | assert_equal 'test_key_id', d.instance.aws_key_id 28 | assert_equal 'test_sec_key', d.instance.aws_sec_key 29 | assert_equal 'test_cloud_watch_endpoint', d.instance.cw_endpoint 30 | assert_equal 'AWS/RDS', d.instance.namespace 31 | assert_equal 'CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput', d.instance.metric_name 32 | assert_equal 'DBInstanceIdentifier', d.instance.dimensions_name 33 | assert_equal 'rds01', d.instance.dimensions_value 34 | assert_equal [{ :name => 'DBInstanceIdentifier', :value => 'rds01' }], d.instance.dimensions 35 | end 36 | 37 | 38 | ### for EC2 39 | CONFIG_ECTWO = %[ 40 | tag cloudwatch 41 | aws_key_id test_key_id 42 | aws_sec_key test_sec_key 43 | cw_endpoint test_cloud_watch_endpoint 44 | namespace AWS/EC2 45 | metric_name CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput 46 | dimensions_name InstanceId 47 | dimensions_value ec2-01 48 | ] 49 | 50 | def create_driver_ectwo(conf = CONFIG_ECTWO) 51 | Fluent::Test::InputTestDriver.new(Fluent::CloudwatchInput).configure(conf) 52 | end 53 | 54 | def test_configure_ectwo 55 | d = create_driver_ectwo 56 | assert_equal 'cloudwatch', d.instance.tag 57 | assert_equal 'test_key_id', d.instance.aws_key_id 58 | assert_equal 'test_sec_key', d.instance.aws_sec_key 59 | assert_equal 'test_cloud_watch_endpoint', d.instance.cw_endpoint 60 | assert_equal 'AWS/EC2', d.instance.namespace 61 | assert_equal 'CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput', d.instance.metric_name 62 | assert_equal 'InstanceId', d.instance.dimensions_name 63 | assert_equal 'ec2-01', d.instance.dimensions_value 64 | assert_equal [{ :name => 'InstanceId', :value => 'ec2-01' }], d.instance.dimensions 65 | end 66 | 67 | ### for StorageGateway 68 | CONFIG_SG = %[ 69 | tag cloudwatch 70 | aws_key_id test_key_id 71 | aws_sec_key test_sec_key 72 | cw_endpoint test_cloud_watch_endpoint 73 | namespace AWS/StorageGateway 74 | metric_name CacheHitPercent,CachePercentUsed 75 | dimensions_name GatewayId,GatewayName 76 | dimensions_value sgw-XXXXXXXX,mygateway 77 | ] 78 | 79 | def create_driver_sg(conf = CONFIG_SG) 80 | Fluent::Test::InputTestDriver.new(Fluent::CloudwatchInput).configure(conf) 81 | end 82 | 83 | def test_configure_sg 84 | d = create_driver_sg 85 | assert_equal 'cloudwatch', d.instance.tag 86 | assert_equal 'test_key_id', d.instance.aws_key_id 87 | assert_equal 'test_sec_key', d.instance.aws_sec_key 88 | assert_equal 'test_cloud_watch_endpoint', d.instance.cw_endpoint 89 | assert_equal 'AWS/StorageGateway', d.instance.namespace 90 | assert_equal 'CacheHitPercent,CachePercentUsed', d.instance.metric_name 91 | assert_equal 'GatewayId,GatewayName', d.instance.dimensions_name 92 | assert_equal 'sgw-XXXXXXXX,mygateway', d.instance.dimensions_value 93 | assert_equal [{ :name => "GatewayId", :value => "sgw-XXXXXXXX" }, { :name => "GatewayName", :value => "mygateway" }], d.instance.dimensions 94 | end 95 | 96 | ### delayed_start 97 | CONFIG_DELAYED_START = CONFIG_RDS + %[ 98 | delayed_start true 99 | ] 100 | 101 | def create_driver_delayed_start(conf = CONFIG_DELAYED_START) 102 | Fluent::Test::InputTestDriver.new(Fluent::CloudwatchInput).configure(conf) 103 | end 104 | 105 | def test_configure_delayed_start 106 | d = create_driver_delayed_start 107 | assert_equal 'cloudwatch', d.instance.tag 108 | assert_equal 'test_key_id', d.instance.aws_key_id 109 | assert_equal 'test_sec_key', d.instance.aws_sec_key 110 | assert_equal 'test_cloud_watch_endpoint', d.instance.cw_endpoint 111 | assert_equal 'AWS/RDS', d.instance.namespace 112 | assert_equal 'CPUUtilization,FreeStorageSpace,DiskQueueDepth,FreeableMemory,SwapUsage,ReadIOPS,ReadLatency,ReadThroughput,WriteIOPS,WriteLatency,WriteThroughput', d.instance.metric_name 113 | assert_equal 'DBInstanceIdentifier', d.instance.dimensions_name 114 | assert_equal 'rds01', d.instance.dimensions_value 115 | assert_equal [{ :name => 'DBInstanceIdentifier', :value => 'rds01' }], d.instance.dimensions 116 | assert_equal true, d.instance.delayed_start 117 | end 118 | 119 | ### for CloudWatchLogsMetricFilters 120 | CONFIG_CWLOG_MF = %[ 121 | tag cloudwatch 122 | aws_key_id test_key_id 123 | aws_sec_key test_sec_key 124 | cw_endpoint test_cloud_watch_endpoint 125 | namespace LogMetrics 126 | metric_name LogAccessCount,LogErrorCount 127 | ] 128 | 129 | def create_driver_cwlog_mf(conf = CONFIG_CWLOG_MF) 130 | Fluent::Test::InputTestDriver.new(Fluent::CloudwatchInput).configure(conf) 131 | end 132 | 133 | def test_configure_cwlog_mf 134 | d = create_driver_cwlog_mf 135 | assert_equal 'cloudwatch', d.instance.tag 136 | assert_equal 'test_key_id', d.instance.aws_key_id 137 | assert_equal 'test_sec_key', d.instance.aws_sec_key 138 | assert_equal 'test_cloud_watch_endpoint', d.instance.cw_endpoint 139 | assert_equal 'LogMetrics', d.instance.namespace 140 | assert_equal 'LogAccessCount,LogErrorCount', d.instance.metric_name 141 | assert_nil d.instance.dimensions_name 142 | assert_nil d.instance.dimensions_value 143 | assert_equal [], d.instance.dimensions 144 | end 145 | end 146 | --------------------------------------------------------------------------------