Easily log custom metrics to AWS CloudWatch

Recently, I wanted to track the amount of time that Sidekiq jobs were taking to execute on a production Rails environment. I wanted an easy way to be able to track the arguments for the Sidekiq job, the user that initiated the job, and of course the duration that the job took to complete.

Since this is a Rails application, the code provided is Ruby but you can look up the put_data method on the AWS docs for your respective programming language.

Generate the user and key #

We need to head over to the AWS dashboard and create a new IAM policy with the following JSON (provided in this blog post):

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
            "Resource": "*"

I called this policy put-custom-metric.

Then, create an IAM user with programmatic access. Attach the custom put-custom-metric policy to this user. AWS will provide you with an access and secret key. Take note of these two strings as you’ll need them next.

Define the environment variables #

In your .bash_profile export the two new variables:

export cloudwatch_access_key_id='##your key here##'
export cloudwatch_secret_access_key='##your secret here##'

Save the file. Note: In your production environment, you’ll also have to define these two environment variables.

The code #

Insert the following in your Gemfile:

gem "aws-sdk-cloudwatch", require: false

And then execute bundle install to install the new package.

For my Rails application, I created a CloudWatchHelper module which is able to save the custom metrics to CloudWatch. I called the file cloudwatch.rb and placed it inside the /lib folder.

require "aws-sdk-cloudwatch"

module CloudWatchHelper

  def self.create_metric(some_arg, duration)
    options = {
      :access_key_id => ENV["cloudwatch_access_key_id"], 
      :secret_access_key => ENV["cloudwatch_secret_access_key"]

    client = Aws::CloudWatch::Client.new({
      :region => "us-west-1",
      :access_key_id => options[:access_key_id],
      :secret_access_key => options[:secret_access_key]

    # Get the environment based on ENV variables
    env = "development" if Rails.env.development?
    env = "production" if Rails.env.production?

    timestamp = Time.now.utc

    res = client.put_metric_data(
      namespace: "SidekiqJobTimes",
      metric_data: [
          metric_name: "SidekiqDuration",
          dimensions: [{
              name: "Environment",
              value: env
            }, {
              name: "Arg",
              value: some_arg
          timestamp: timestamp,
          value: duration,
          unit: "Seconds"

    return true


If you have other arguments you would like to send to CloudWatch along with the metric, simply add them into the dimensions array.

Next, I modified the application_job.rb file which is the parent class of all the Sidekiq jobs which get executed. The modification allows us to keep track of the start and end time of a job.

class ApplicationJob < ActiveJob::Base
  attr_accessor :before, :after, :duration

  def start_timer 
    @before = Time.now

  def end_timer 
    @after = Time.now
    @duration = @after - @before

The last thing to do is utilize the start_timer, end_timer, and create_metric functions within the actual job code.

require 'cloudwatch'

class HistoricalDataJob < ApplicationJob
  include CloudWatchHelper

  queue_as :default

  def perform(arg)
    # Start the timer for as soon as a job is created

    # Do some work in your job

    # End the timer after the job executes

    # Create the metric in CloudWatch
    CloudWatchHelper.create_metric(arg, @duration)

Testing your work #

Execute your job and within a minute of your Sidekiq job completing, you should start seeing your custom CloudWatch metrics coming into the CloudWatch AWS dashboard:


Feel free to let me know on twitter (@shahzebdev) if you found this helpful 😊.


Now read this

Launch a website for free.

Being able to launch a website for free* is really easy these days. I prefer writing vanilla HTML / JS / CSS. But to make my life a bit easier, I think I’ll be switching over to using Cactus. Developing your site # Write HTML / JS / CSS... Continue →