wealthsimple/dogstatsd-instrumentation

View on GitHub
lib/dogstatsd/instrumentation/request.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

require 'active_support'
require 'gem_config'
require 'datadog/statsd'
require_relative 'client_provider'

module DogStatsd
  module Instrumentation
    module Request
      include GemConfig::Base

      with_configuration do
        has :statsd, classes: Object
      end

      # From GemConfig::Base
      def self.configure
        super
        @@subscriber.unsubscribe if @@subscriber

        @@subscriber = Subscriber.new(configuration.statsd || ClientProvider.new)
      end

      @@subscriber = nil

      class Subscriber
        def initialize(statsd)
          @statsd = statsd

          @subscriber = ActiveSupport::Notifications.subscribe /process_action.action_controller/ do |*args|
            event = ActiveSupport::Notifications::Event.new(*args)
            tags = {
              controller: event.payload[:controller],
              method: event.payload[:method],
              status: event.payload[:status],
            }

            tags[:action] = "#{tags[:controller]}##{event.payload[:action]}" if event.payload[:action]

            instrument stat: 'process_action.action_controller.duration', value: event.duration, tags: tags

            event.payload.select { |key, _| key.to_s.end_with? '_runtime' }.each do |name, duration|
              instrument stat: "process_action.action_controller.#{name}", value: duration, tags: tags
            end
          end
        end

        def instrument(stat:, value:, tags:)
          @statsd.histogram stat, value, tags: Subscriber.tagify(tags)
        end

        def self.tagify(hash)
          hash.select { |_, value| value.present? }.map { |key, value| "#{key}:#{value}" }
        end

        def unsubscribe
          ActiveSupport::Notifications.unsubscribe @subscriber
          nil
        end
      end
    end
  end
end