class CloudwatchToGraphite::Base

This class is responsible for retrieving metrics from CloudWatch and sending the results to a Graphite server.

Attributes

carbon_prefix[R]
graphite_port[RW]
graphite_server[RW]
protocol[RW]

Public Class Methods

new(aws_access_key, aws_secret_key, region) click to toggle source

Initialize the CloudwatchToGraphite::Base object.

aws_access_key

The AWS user key

aws_secret_key

The AWS secret

region

The AWS region (eg: us-west-1)

verbose

boolean to enable verbose output

# File lib/cloudwatchtographite.rb, line 33
def initialize(aws_access_key, aws_secret_key, region)
  @logger          = Log4r::Logger.new('cloudwatchtographite::base')
  @protocol        = 'udp'
  @carbon_prefix   = 'cloudwatch'
  @graphite_server = 'localhost'
  @graphite_port   = 2003

  @logger.debug("Fog setting up for region #{region}")

  @cloudwatch = Fog::AWS::CloudWatch.new(
    :aws_access_key_id => aws_access_key,
    :aws_secret_access_key => aws_secret_key,
    :region => region
  )
end

Public Instance Methods

carbon_prefix=(p) click to toggle source

set the carbon prefix

p

the string prefix to use

# File lib/cloudwatchtographite.rb, line 152
def carbon_prefix=(p)
  Validator::string_longer_than(p, 0)
  @carbon_prefix=p
end
fetch_and_forward(metrics) click to toggle source
# File lib/cloudwatchtographite.rb, line 133
def fetch_and_forward(metrics)
  results = retrieve_datapoints(metrics)
  if results.length == 0
    false
  else
    case @protocol
    when 'tcp'
      send_tcp(results)
    when 'udp'
      send_udp(results)
    else
      @logger.debug("Unknown protocol #{@protocol}")
      raise ProtocolError
    end
  end
end
retrieve_datapoints(metrics) click to toggle source
# File lib/cloudwatchtographite.rb, line 95
def retrieve_datapoints(metrics)
  ret = []
  Array(metrics).each do |m|
    begin
      ret.concat retrieve_one_datapoint(m)
    rescue Excon::Errors::SocketError, Excon::Errors::BadRequest => e
      @logger.error("[Error in CloudWatch call] #{e.message}")
    rescue Excon::Errors::Forbidden
      @logger.error(
        "[Error in CloudWatch call] permission denied - check keys!"
      )
    end
  end
  ret
end
retrieve_one_datapoint(metric) click to toggle source
# File lib/cloudwatchtographite.rb, line 111
def retrieve_one_datapoint(metric)
  @logger.debug("Sending to CloudWatch: #{metric.to_h}")
  data_points = @cloudwatch.get_metric_statistics(
    metric.to_h
  ).body['GetMetricStatisticsResult']['Datapoints']
  @logger.debug("Received from CloudWatch: #{data_points}")

  return retrieve_statistics(metric, order_data_points(data_points))
end
retrieve_statistics(metric, data_points) click to toggle source
# File lib/cloudwatchtographite.rb, line 121
def retrieve_statistics(metric, data_points)
  ret = []
  metric.Statistics.each do |stat|
    name = "#{@carbon_prefix}.#{metric.graphite_path(stat)}"
    data_points.each do |d|
      ret.push "#{name} #{d[stat]} #{d['Timestamp'].utc.to_i}"
    end
  end
  @logger.debug("Returning Statistics: #{ret}")
  ret
end
send_tcp(contents) click to toggle source

Send data to a Graphite server via the TCP protocol

contents

a string or array containing the contents to send

# File lib/cloudwatchtographite.rb, line 75
def send_tcp(contents)
  sock = nil
  contents = contents.join("\n") if contents.kind_of?(Array)

  @logger.debug("Attempting to send #{contents.length}  bytes " +
    "to #{@graphite_server}:#{@graphite_port} via tcp")

  retval = false
  begin
    sock = TCPSocket.open(@graphite_server, @graphite_port)
    sock.print(contents)
    retval = true
  rescue Exception => e
    @logger.debug("Caught exception! [#{e}]")
  ensure
    sock.close if sock
  end
  retval
end
send_udp(contents) click to toggle source

Send data to a Graphite server via the UDP protocol

contents

a string or array containing the contents to send

# File lib/cloudwatchtographite.rb, line 52
def send_udp(contents)
  sock = nil
  contents = contents.join("\n") if contents.kind_of?(Array)

  @logger.debug("Attempting to send #{contents.length}  bytes " +
    "to #{@graphite_server}:#{@graphite_port} via udp")

  begin
    sock = UDPSocket.open
    sock.send(contents, 0, @graphite_server, @graphite_port)
    retval = true
  rescue Exception => e
    @logger.debug("Caught exception! [#{e}]")
    retval = false
  ensure
    sock.close if sock
  end
  retval
end

Private Instance Methods

order_data_points(data_points) click to toggle source
# File lib/cloudwatchtographite.rb, line 158
def order_data_points(data_points)
  if data_points.nil?
    data_points = []
  else
    data_points = Array(data_points)
  end

  if data_points.length == 0
    logger.debug("No data points!")
    data_points
  else
    data_points = data_points.sort_by {|array| array['Timestamp'] }
  end
end