From d181fb242e1e2cee8aaf10ce446a9f836ce1adb0 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Fri, 9 Oct 2020 11:02:23 +0800 Subject: [PATCH 01/22] minor clean-up and bump bundler version --- event_tracer.gemspec | 29 ++++++++++++++--------------- spec/spec_helper.rb | 11 ++++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/event_tracer.gemspec b/event_tracer.gemspec index a931c78..7f1292f 100644 --- a/event_tracer.gemspec +++ b/event_tracer.gemspec @@ -1,25 +1,24 @@ -# coding: utf-8 -lib = File.expand_path("../lib", __FILE__) +lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require "event_tracer/version" +require 'event_tracer/version' Gem::Specification.new do |spec| - spec.name = "event_tracer" + spec.name = 'event_tracer' spec.version = EventTracer::VERSION - spec.authors = ["melvrickgoh"] - spec.email = ["melvrickgoh@hotmail.com"] + spec.authors = ['melvrickgoh'] + spec.email = ['melvrickgoh@hotmail.com'] - spec.summary = %q{Thin wrapper for formatted logging/ metric services to be used as a single service} - spec.description = %q{Thin wrapper for formatted logging/ metric services to be used as a single service. External service(s) supported: Appsignal} - spec.homepage = "https://github.com/melvrickgoh/event_tracer" - spec.license = "MIT" + spec.summary = 'Thin wrapper for formatted logging/ metric services to be used as a single service' + spec.description = 'Thin wrapper for formatted logging/ metric services to be used as a single service. External service(s) supported: Appsignal' + spec.homepage = 'https://github.com/melvrickgoh/event_tracer' + spec.license = 'MIT' spec.files = Dir['lib/**/*.rb'] - spec.bindir = "exe" + spec.bindir = 'exe' spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib/event_tracer", "lib"] + spec.require_paths = %w[lib/event_tracer lib] - spec.add_development_dependency "bundler", "~> 1.17" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "rspec", "~> 3.0" + spec.add_development_dependency 'bundler', '~> 2.0' + spec.add_development_dependency 'rake', '~> 10.0' + spec.add_development_dependency 'rspec', '~> 3.0' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b007403..299fbac 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,11 +1,12 @@ -require "bundler/setup" -require "event_tracer" -require "data_helpers/mock_logger" -require "data_helpers/mock_appsignal" +require 'bundler/setup' +require 'event_tracer' +require 'data_helpers/mock_logger' +require 'data_helpers/mock_appsignal' +require 'data_helpers/mock_datadog' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure - config.example_status_persistence_file_path = ".rspec_status" + config.example_status_persistence_file_path = '.rspec_status' config.expect_with :rspec do |c| c.syntax = :expect From 338bc878a125cc1f9479281b2e9d8b5ea27fbcaf Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Mon, 12 Oct 2020 17:02:03 +0800 Subject: [PATCH 02/22] add datadog integration --- lib/event_tracer/datadog_logger.rb | 57 ++++++++++++ spec/data_helpers/mock_datadog.rb | 21 +++++ spec/event_tracer/datadog_logger_spec.rb | 110 +++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 lib/event_tracer/datadog_logger.rb create mode 100644 spec/data_helpers/mock_datadog.rb create mode 100644 spec/event_tracer/datadog_logger_spec.rb diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb new file mode 100644 index 0000000..ae997a6 --- /dev/null +++ b/lib/event_tracer/datadog_logger.rb @@ -0,0 +1,57 @@ +require_relative '../event_tracer' +require_relative './basic_decorator' +# NOTES +# Datadog interface to send our usual actions +# BasicDecorator adds a transparent interface on top of the datadog interface +# +# Usage: EventTracer.register :datadog, EventTracer::DataDogLogger.new(DataDog) +# data_dog_logger.info datadog: { increment: { counter_1: 1, counter_2: 2 }, set: { gauge_1: 1 } } + +module EventTracer + class DatadogLogger < BasicDecorator + + SUPPORTED_METRICS ||= %i(increment set distribution gauge histogram).freeze + + LOG_TYPES.each do |log_type| + define_method log_type do |**args| + puts "args are: #{args}" + return LogResult.new(false, 'Invalid datadog config') unless args[:datadog] && args[:datadog].is_a?(Hash) + + applied_metrics(args[:datadog]).each do |metric| + metric_args = args[:datadog][metric] + return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args && metric_args.is_a?(Hash) + + send_metric metric, metric_args + end + + LogResult.new(true) + end + end + + private + + attr_reader :datadog, :decoratee + alias_method :datadog, :decoratee + + def applied_metrics(datadog_args) + datadog_args.keys.select { |metric| SUPPORTED_METRICS.include?(metric) } + end + + # increment + # while true do + # statsd.increment('example_metric.increment', tags: ['environment:dev']) + # statsd.decrement('example_metric.decrement', tags: ['environment:dev']) + # statsd.count('example_metric.count', 2, tags: ['environment:dev']) + # sleep 10 + # end + + def send_metric(metric, payload) + + payload.each do |increment, value| + puts "payload contains: increment: #{increment} value: #{value}" + datadog.send(metric, increment, value) + end + end + + end +end diff --git a/spec/data_helpers/mock_datadog.rb b/spec/data_helpers/mock_datadog.rb new file mode 100644 index 0000000..bd9100d --- /dev/null +++ b/spec/data_helpers/mock_datadog.rb @@ -0,0 +1,21 @@ +class MockDatadog < Struct.new(:_) + def increment(*_args) + 'increment' + end + + def distribution(*_args) + 'distribution' + end + + def set(*_args) + 'set' + end + + def gauge(*_args) + 'gauge' + end + + def histogram(*_args) + 'histogram' + end +end diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb new file mode 100644 index 0000000..f2daf6b --- /dev/null +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -0,0 +1,110 @@ +require 'spec_helper' + +describe EventTracer::DatadogLogger do + + INVALID_PAYLOADS ||= [ + nil, + [], + Object.new, + 'string', + 10, + :invalid_payload + ].freeze + + let(:datadog_payload) { nil } + let(:mock_datadog) { MockDatadog.new } + + subject { EventTracer::DatadogLogger.new(mock_datadog) } + + shared_examples_for 'rejects_invalid_datadog_args' do + INVALID_PAYLOADS.each do |datadog_value| + context "Invalid datadog top-level args" do + let(:datadog_payload) { datadog_value } + + it 'rejects the payload when invalid datadog values are given' do + expect(mock_datadog).not_to receive(:increment) + expect(mock_datadog).not_to receive(:distribution) + expect(mock_datadog).not_to receive(:histogram) + expect(mock_datadog).not_to receive(:set) + expect(mock_datadog).not_to receive(:gauge) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq false + expect(result.error).to eq 'Invalid datadog config' + end + end + end + end + + shared_examples_for 'skip_processing_empty_datadog_args' do + let(:datadog_payload) { {} } + + it 'skips any metric processing' do + expect(mock_datadog).not_to receive(:increment_counter) + expect(mock_datadog).not_to receive(:add_distribution_value) + expect(mock_datadog).not_to receive(:set_gauge) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq true + expect(result.error).to eq nil + end + end + + shared_examples_for 'processes_hashed_inputs' do + let(:datadog_payload) do + { + increment: { 'Counter_1' => 1, 'Counter_2' => 2 }, + distribution: { 'Distribution_1' => 10 }, + set: { 'Set_1' => 100 }, + gauge: { 'Gauge_1' => 100 } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).to receive(:increment).with('Counter_1', 1) + expect(mock_datadog).to receive(:increment).with('Counter_2', 2) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10) + expect(mock_datadog).to receive(:set).with('Set_1', 100) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq true + expect(result.error).to eq nil + end + end + + shared_examples_for "rejects_invalid_metric_args" do + EventTracer::DatadogLogger::SUPPORTED_METRICS.each do |metric| + INVALID_PAYLOADS.each do |payload| + context "Invalid metric values for #{metric}: #{payload}" do + let(:datadog_payload) { { metric => payload } } + + it 'rejects the payload when invalid datadog values are given' do + expect(mock_datadog).not_to receive(:increment_counter) + expect(mock_datadog).not_to receive(:add_distribution_value) + expect(mock_datadog).not_to receive(:set_gauge) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq false + expect(result.error).to eq "Datadog metric #{metric} invalid" + end + end + end + end + end + + EventTracer::LOG_TYPES.each do |log_type| + context "Log type: #{log_type}" do + let(:expected_call) { log_type } + + it_behaves_like 'processes_hashed_inputs' + it_behaves_like 'skip_processing_empty_datadog_args' + it_behaves_like 'rejects_invalid_datadog_args' + it_behaves_like 'rejects_invalid_metric_args' + end + end +end From 6b87216a931d6bc6a063386c6363fb942566829f Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Mon, 12 Oct 2020 17:07:36 +0800 Subject: [PATCH 03/22] update ReadMe --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 00e8c9b..32e4e37 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,12 @@ This gem currently supports only: 1. increment_counter 2. add_distribution_value 3. set_gauge +3. Datadog: Empty wrapper around the custom metric distributions + 1. increment + 2. distribution + 3. set + 4. gauge + 5. histogram No dependencies are declared for this as the @@ -50,6 +56,7 @@ Each initialised logger is then registered to `EventTracer`. ```ruby EventTracer.register :base, base_logger EventTracer.register :appsignal, appsignal_logger +EventTracer.register :datadog, datadog_logger ``` As this is a registry, you can set it up with your own implemented wrapper as long as it responds to the following `LOG_TYPES` methods: `info, warn, error` @@ -104,13 +111,43 @@ EventTracer.info action: 'Action', message: 'Message', appsignal: { increment_co # counter_2, 2 ``` +**3. Datadog** + +Datadog via dogstatsd-ruby (4.8.1) is currently supported for the following metric functions available for the EventTracer's log methods + +- increment +- distribution +- set +- gauge +- histogram + +All other functions are exposed transparently to the underlying Appsignal class + +The interface for using the Appsignal wrapper is: + +Key | Secondary key | Secondary key type | Values +--------------|-------------|------------------|------- +datadog | increment | Hash | Hash of key-value pairs featuring the metric name and the counter value to send +| | distribution | Hash | Hash of key-value pairs featuring the metric name and the distribution value to send +| | set | Hash | Hash of key-value pairs featuring the metric name and the set value to send +| | gauge | Hash | Hash of key-value pairs featuring the metric name and the gauge value to send +| | histogram | Hash | Hash of key-value pairs featuring the metric name and the histogram value to send + +```ruby +# Sample usage +EventTracer.info action: 'Action', message: 'Message', appsignal: { increment: { counter_1: 1, counter_2: 2 } } +# This calls .increment_counter on Datadog twice with the 2 sets of arguments +# counter_1, 1 +# counter_2, 2 +``` + **Summary** In all the generated interface for `EventTracer` logging could look something like this ```ruby EventTracer.info( - loggers: [:base, :appsignal, :custom_logging_service] + loggers: %(base appsignal custom_logging_service datadog), action: 'NewTransaction', message: "New transaction created by API", appsignal: { From e52f5a99e73ff0e2ed8b16de05dc578f2987efb7 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Mon, 12 Oct 2020 17:21:33 +0800 Subject: [PATCH 04/22] clean-up --- lib/event_tracer/datadog_logger.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index ae997a6..0d746d2 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -10,16 +10,15 @@ module EventTracer class DatadogLogger < BasicDecorator - SUPPORTED_METRICS ||= %i(increment set distribution gauge histogram).freeze + SUPPORTED_METRICS ||= %i[increment set distribution gauge histogram].freeze LOG_TYPES.each do |log_type| define_method log_type do |**args| - puts "args are: #{args}" - return LogResult.new(false, 'Invalid datadog config') unless args[:datadog] && args[:datadog].is_a?(Hash) + return LogResult.new(false, 'Invalid datadog config') unless args[:datadog]&.is_a?(Hash) applied_metrics(args[:datadog]).each do |metric| metric_args = args[:datadog][metric] - return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args && metric_args.is_a?(Hash) + return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args&.is_a?(Hash) send_metric metric, metric_args end @@ -37,14 +36,6 @@ def applied_metrics(datadog_args) datadog_args.keys.select { |metric| SUPPORTED_METRICS.include?(metric) } end - # increment - # while true do - # statsd.increment('example_metric.increment', tags: ['environment:dev']) - # statsd.decrement('example_metric.decrement', tags: ['environment:dev']) - # statsd.count('example_metric.count', 2, tags: ['environment:dev']) - # sleep 10 - # end - def send_metric(metric, payload) payload.each do |increment, value| From b5be852c16330b52546f657d5e826054b2fdee33 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 08:32:36 +0800 Subject: [PATCH 05/22] remove repl code --- lib/event_tracer/datadog_logger.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 0d746d2..06528dd 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -39,10 +39,8 @@ def applied_metrics(datadog_args) def send_metric(metric, payload) payload.each do |increment, value| - puts "payload contains: increment: #{increment} value: #{value}" datadog.send(metric, increment, value) end end - end end From e69d0e940d8045baa7b0baa15f2758d917d02efa Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 08:36:53 +0800 Subject: [PATCH 06/22] remove shared examples --- spec/event_tracer/datadog_logger_spec.rb | 133 +++++++++++------------ 1 file changed, 64 insertions(+), 69 deletions(-) diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index f2daf6b..bab9cbf 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -16,95 +16,90 @@ subject { EventTracer::DatadogLogger.new(mock_datadog) } - shared_examples_for 'rejects_invalid_datadog_args' do - INVALID_PAYLOADS.each do |datadog_value| - context "Invalid datadog top-level args" do - let(:datadog_payload) { datadog_value } - - it 'rejects the payload when invalid datadog values are given' do - expect(mock_datadog).not_to receive(:increment) - expect(mock_datadog).not_to receive(:distribution) - expect(mock_datadog).not_to receive(:histogram) - expect(mock_datadog).not_to receive(:set) - expect(mock_datadog).not_to receive(:gauge) + EventTracer::LOG_TYPES.each do |log_type| + context "Log type: #{log_type}" do + let(:expected_call) { log_type } + + context 'processes_hashed_inputs' do + let(:datadog_payload) do + { + increment: { 'Counter_1' => 1, 'Counter_2' => 2 }, + distribution: { 'Distribution_1' => 10 }, + set: { 'Set_1' => 100 }, + gauge: { 'Gauge_1' => 100 } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).to receive(:increment).with('Counter_1', 1) + expect(mock_datadog).to receive(:increment).with('Counter_2', 2) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10) + expect(mock_datadog).to receive(:set).with('Set_1', 100) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100) result = subject.send(expected_call, datadog: datadog_payload) - expect(result.success?).to eq false - expect(result.error).to eq 'Invalid datadog config' + expect(result.success?).to eq true + expect(result.error).to eq nil end end - end - end - shared_examples_for 'skip_processing_empty_datadog_args' do - let(:datadog_payload) { {} } + context 'skip_processing_empty_datadog_args' do + let(:datadog_payload) { {} } - it 'skips any metric processing' do - expect(mock_datadog).not_to receive(:increment_counter) - expect(mock_datadog).not_to receive(:add_distribution_value) - expect(mock_datadog).not_to receive(:set_gauge) + it 'skips any metric processing' do + expect(mock_datadog).not_to receive(:increment_counter) + expect(mock_datadog).not_to receive(:add_distribution_value) + expect(mock_datadog).not_to receive(:set_gauge) - result = subject.send(expected_call, datadog: datadog_payload) + result = subject.send(expected_call, datadog: datadog_payload) - expect(result.success?).to eq true - expect(result.error).to eq nil - end - end + expect(result.success?).to eq true + expect(result.error).to eq nil + end + end - shared_examples_for 'processes_hashed_inputs' do - let(:datadog_payload) do - { - increment: { 'Counter_1' => 1, 'Counter_2' => 2 }, - distribution: { 'Distribution_1' => 10 }, - set: { 'Set_1' => 100 }, - gauge: { 'Gauge_1' => 100 } - } - end + context 'rejects_invalid_datadog_args' do + INVALID_PAYLOADS.each do |datadog_value| + context 'Invalid datadog top-level args' do + let(:datadog_payload) { datadog_value } - it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:increment).with('Counter_1', 1) - expect(mock_datadog).to receive(:increment).with('Counter_2', 2) - expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10) - expect(mock_datadog).to receive(:set).with('Set_1', 100) - expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100) + it 'rejects the payload when invalid datadog values are given' do + expect(mock_datadog).not_to receive(:increment) + expect(mock_datadog).not_to receive(:distribution) + expect(mock_datadog).not_to receive(:histogram) + expect(mock_datadog).not_to receive(:set) + expect(mock_datadog).not_to receive(:gauge) - result = subject.send(expected_call, datadog: datadog_payload) + result = subject.send(expected_call, datadog: datadog_payload) - expect(result.success?).to eq true - expect(result.error).to eq nil - end - end + expect(result.success?).to eq false + expect(result.error).to eq 'Invalid datadog config' + end + end + end + end - shared_examples_for "rejects_invalid_metric_args" do - EventTracer::DatadogLogger::SUPPORTED_METRICS.each do |metric| - INVALID_PAYLOADS.each do |payload| - context "Invalid metric values for #{metric}: #{payload}" do - let(:datadog_payload) { { metric => payload } } + context 'rejects_invalid_metric_args' do + EventTracer::DatadogLogger::SUPPORTED_METRICS.each do |metric| + INVALID_PAYLOADS.each do |payload| + context "Invalid metric values for #{metric}: #{payload}" do + let(:datadog_payload) { { metric => payload } } - it 'rejects the payload when invalid datadog values are given' do - expect(mock_datadog).not_to receive(:increment_counter) - expect(mock_datadog).not_to receive(:add_distribution_value) - expect(mock_datadog).not_to receive(:set_gauge) + it 'rejects the payload when invalid datadog values are given' do + expect(mock_datadog).not_to receive(:increment_counter) + expect(mock_datadog).not_to receive(:add_distribution_value) + expect(mock_datadog).not_to receive(:set_gauge) - result = subject.send(expected_call, datadog: datadog_payload) + result = subject.send(expected_call, datadog: datadog_payload) - expect(result.success?).to eq false - expect(result.error).to eq "Datadog metric #{metric} invalid" + expect(result.success?).to eq false + expect(result.error).to eq "Datadog metric #{metric} invalid" + end + end end end end end end - - EventTracer::LOG_TYPES.each do |log_type| - context "Log type: #{log_type}" do - let(:expected_call) { log_type } - - it_behaves_like 'processes_hashed_inputs' - it_behaves_like 'skip_processing_empty_datadog_args' - it_behaves_like 'rejects_invalid_datadog_args' - it_behaves_like 'rejects_invalid_metric_args' - end - end end From 7c3fdc10b4ab971ced93b2c0e696184178325124 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 09:43:34 +0800 Subject: [PATCH 07/22] remove safe navigation --- lib/event_tracer/datadog_logger.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 06528dd..8036d2d 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -18,7 +18,7 @@ class DatadogLogger < BasicDecorator applied_metrics(args[:datadog]).each do |metric| metric_args = args[:datadog][metric] - return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args&.is_a?(Hash) + return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args.is_a?(Hash) send_metric metric, metric_args end From ba1d2db63afcf3cb8010023216799aafa3d766e2 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 09:44:31 +0800 Subject: [PATCH 08/22] update travis config --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4810b7c..30055ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,5 @@ sudo: false language: ruby cache: bundler rvm: - - 2.3.0 -before_install: gem install bundler -v 1.17.1 + - 2.6.6 +before_install: gem install bundler From 0a389e512c6f075bfaa62e1b2a416934c94234fe Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 09:45:23 +0800 Subject: [PATCH 09/22] bump version --- lib/event_tracer/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/event_tracer/version.rb b/lib/event_tracer/version.rb index d5e1c94..9b47e0d 100644 --- a/lib/event_tracer/version.rb +++ b/lib/event_tracer/version.rb @@ -1,3 +1,3 @@ module EventTracer - VERSION = "0.1.2" + VERSION = '0.1.4'.freeze end From da952d219f8b7c9d23a0efcc83f35f9686cdc25e Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 09:58:10 +0800 Subject: [PATCH 10/22] add tag support as indicated by datadog --- lib/event_tracer/datadog_logger.rb | 22 +++++++++++-- spec/event_tracer/datadog_logger_spec.rb | 41 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 8036d2d..ef6990b 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -6,10 +6,13 @@ # # Usage: EventTracer.register :datadog, EventTracer::DataDogLogger.new(DataDog) # data_dog_logger.info datadog: { increment: { counter_1: 1, counter_2: 2 }, set: { gauge_1: 1 } } +# data_dog_logger.info datadog: { increment: { counter_1: { value: 1, tags: ['tag1, tag2']} } } module EventTracer class DatadogLogger < BasicDecorator + class InvalidTagError < StandardError; end + SUPPORTED_METRICS ||= %i[increment set distribution gauge histogram].freeze LOG_TYPES.each do |log_type| @@ -21,6 +24,8 @@ class DatadogLogger < BasicDecorator return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args.is_a?(Hash) send_metric metric, metric_args + rescue InvalidTagError => e + return LogResult.new(false, e.message) end LogResult.new(true) @@ -37,9 +42,22 @@ def applied_metrics(datadog_args) end def send_metric(metric, payload) + payload.each do |increment, attribute| + if attribute.is_a?(Hash) + begin + datadog.send( + metric, + increment, + attribute.fetch(:value), + attribute.fetch(:tags) + ) + rescue KeyError + raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" + end + else + datadog.send(metric, increment, attribute) + end - payload.each do |increment, value| - datadog.send(metric, increment, value) end end end diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index bab9cbf..e8abb69 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -44,6 +44,30 @@ end end + context 'processes_hashed_inputs with tags' do + let(:datadog_payload) do + { + increment: { 'Counter_1' => { value: 1, tags: ['test']}, 'Counter_2' => { value: 2, tags: ['test']} }, + distribution: { 'Distribution_1' => { value: 10, tags: ['test']} }, + set: { 'Set_1' => { value: 100, tags: ['test'] } }, + gauge: { 'Gauge_1' => { value: 100, tags: ['test'] } } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).to receive(:increment).with('Counter_1', 1, ['test']) + expect(mock_datadog).to receive(:increment).with('Counter_2', 2, ['test']) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test']) + expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test']) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test']) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq true + expect(result.error).to eq nil + end + end + context 'skip_processing_empty_datadog_args' do let(:datadog_payload) { {} } @@ -59,6 +83,23 @@ end end + context 'processes_hashed_inputs with invalid tag' do + let(:datadog_payload) do + { + increment: { 'Counter_1' => { value: 1, invalid_tag: ['foo'] } } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).not_to receive(:increment).with('Counter_1', 1) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq false + expect(result.error).to eq 'Datadog payload { Counter_1: {:value=>1, :invalid_tag=>["foo"]} } invalid' + end + end + context 'rejects_invalid_datadog_args' do INVALID_PAYLOADS.each do |datadog_value| context 'Invalid datadog top-level args' do From abeee2c10fa78e7c5175d4c1b587b506d9280cad Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 15 Oct 2020 09:58:24 +0800 Subject: [PATCH 11/22] update README with datadog usage --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 32e4e37..9ade246 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ datadog | increment | Hash | Hash of key-value pairs featuring the metric name a ```ruby # Sample usage -EventTracer.info action: 'Action', message: 'Message', appsignal: { increment: { counter_1: 1, counter_2: 2 } } +EventTracer.info action: 'Action', message: 'Message', datadog: { increment: { counter_1: 1, counter_2: { value: 2, tag: ['foo']} } } # This calls .increment_counter on Datadog twice with the 2 sets of arguments # counter_1, 1 # counter_2, 2 @@ -155,6 +155,12 @@ EventTracer.info( "distribution_metric_1" => 1000, "distribution_metric_2" => 2000 } + }, + datadog: { + distribution: { + "distribution_metric_1" => 1000, + "distribution_metric_2" => { value: 2000, tags: ['eu'] } + } } ) ``` From 97cd12e3dc7bf004f9a9724ee85f8f5bdee1721d Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 5 Nov 2020 12:13:56 +0800 Subject: [PATCH 12/22] address typo in usage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ade246..667c46a 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ datadog | increment | Hash | Hash of key-value pairs featuring the metric name a ```ruby # Sample usage -EventTracer.info action: 'Action', message: 'Message', datadog: { increment: { counter_1: 1, counter_2: { value: 2, tag: ['foo']} } } +EventTracer.info action: 'Action', message: 'Message', datadog: { increment: { counter_1: 1, counter_2: { value: 2, tags: ['foo']} } } # This calls .increment_counter on Datadog twice with the 2 sets of arguments # counter_1, 1 # counter_2, 2 From 101b8f5fd20a1968c9d0fc2f0bcd104d2b4b2c75 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Thu, 5 Nov 2020 15:50:24 +0800 Subject: [PATCH 13/22] support both tags as array and hash --- lib/event_tracer/datadog_logger.rb | 9 +++++++- spec/event_tracer/datadog_logger_spec.rb | 29 +++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index ef6990b..9f10ff4 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -49,7 +49,7 @@ def send_metric(metric, payload) metric, increment, attribute.fetch(:value), - attribute.fetch(:tags) + format_tags(attribute.fetch(:tags)) ) rescue KeyError raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" @@ -57,7 +57,14 @@ def send_metric(metric, payload) else datadog.send(metric, increment, attribute) end + end + end + + def format_tags(tags) + return tags if tags.is_a?(Array) + tags.inject([]) do |acc, (tag, value)| + acc << "#{tag}|#{value}" end end end diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index e8abb69..96d0f30 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -44,7 +44,7 @@ end end - context 'processes_hashed_inputs with tags' do + context 'processes_hashed_inputs with tags in correct format' do let(:datadog_payload) do { increment: { 'Counter_1' => { value: 1, tags: ['test']}, 'Counter_2' => { value: 2, tags: ['test']} }, @@ -68,6 +68,33 @@ end end + context 'processes_hashed_inputs with tags as hash' do + let(:datadog_payload) do + { + increment: { + 'Counter_1' => { value: 1, tags: { test: 'value' } }, + 'Counter_2' => { value: 2, tags: { test: 'value' } } + }, + distribution: { 'Distribution_1' => { value: 10, tags: { test: 'value' } } }, + set: { 'Set_1' => { value: 100, tags: { test: 'value' } } }, + gauge: { 'Gauge_1' => { value: 100, tags: { test: 'value' } } } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).to receive(:increment).with('Counter_1', 1, ['test|value']) + expect(mock_datadog).to receive(:increment).with('Counter_2', 2, ['test|value']) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test|value']) + expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test|value']) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test|value']) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq true + expect(result.error).to eq nil + end + end + context 'skip_processing_empty_datadog_args' do let(:datadog_payload) { {} } From 1fb53476fdf282b105c508c1010219796427ae29 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Fri, 6 Nov 2020 15:47:32 +0800 Subject: [PATCH 14/22] add mapper to use count instead of increment --- lib/event_tracer/datadog_logger.rb | 8 ++++++-- spec/event_tracer/datadog_logger_spec.rb | 16 ++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 9f10ff4..5ca68c3 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -46,7 +46,7 @@ def send_metric(metric, payload) if attribute.is_a?(Hash) begin datadog.send( - metric, + format_metric(metric), increment, attribute.fetch(:value), format_tags(attribute.fetch(:tags)) @@ -55,7 +55,7 @@ def send_metric(metric, payload) raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" end else - datadog.send(metric, increment, attribute) + datadog.send(format_metric(metric), increment, attribute) end end end @@ -67,5 +67,9 @@ def format_tags(tags) acc << "#{tag}|#{value}" end end + + def format_metric(metric) + metric == :increment ? :count : metric + end end end diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index 96d0f30..4689e34 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -31,8 +31,8 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:increment).with('Counter_1', 1) - expect(mock_datadog).to receive(:increment).with('Counter_2', 2) + expect(mock_datadog).to receive(:count).with('Counter_1', 1) + expect(mock_datadog).to receive(:count).with('Counter_2', 2) expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10) expect(mock_datadog).to receive(:set).with('Set_1', 100) expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100) @@ -55,8 +55,8 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:increment).with('Counter_1', 1, ['test']) - expect(mock_datadog).to receive(:increment).with('Counter_2', 2, ['test']) + expect(mock_datadog).to receive(:count).with('Counter_1', 1, ['test']) + expect(mock_datadog).to receive(:count).with('Counter_2', 2, ['test']) expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test']) expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test']) expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test']) @@ -82,8 +82,8 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:increment).with('Counter_1', 1, ['test|value']) - expect(mock_datadog).to receive(:increment).with('Counter_2', 2, ['test|value']) + expect(mock_datadog).to receive(:count).with('Counter_1', 1, ['test|value']) + expect(mock_datadog).to receive(:count).with('Counter_2', 2, ['test|value']) expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test|value']) expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test|value']) expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test|value']) @@ -118,7 +118,7 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).not_to receive(:increment).with('Counter_1', 1) + expect(mock_datadog).not_to receive(:count).with('Counter_1', 1) result = subject.send(expected_call, datadog: datadog_payload) @@ -133,7 +133,7 @@ let(:datadog_payload) { datadog_value } it 'rejects the payload when invalid datadog values are given' do - expect(mock_datadog).not_to receive(:increment) + expect(mock_datadog).not_to receive(:count) expect(mock_datadog).not_to receive(:distribution) expect(mock_datadog).not_to receive(:histogram) expect(mock_datadog).not_to receive(:set) From 0a9732d601c45285cf79844caf638e9261b1b1ba Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Fri, 6 Nov 2020 15:57:49 +0800 Subject: [PATCH 15/22] add build_options as safety net for options --- lib/event_tracer/datadog_logger.rb | 18 ++++--- spec/event_tracer/datadog_logger_spec.rb | 62 ++++++++++++++++-------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 5ca68c3..9ff52f9 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -49,7 +49,7 @@ def send_metric(metric, payload) format_metric(metric), increment, attribute.fetch(:value), - format_tags(attribute.fetch(:tags)) + build_options(attribute.dig(:tags)) ) rescue KeyError raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" @@ -60,12 +60,18 @@ def send_metric(metric, payload) end end - def format_tags(tags) - return tags if tags.is_a?(Array) + def build_options(tags) + return {} unless tags - tags.inject([]) do |acc, (tag, value)| - acc << "#{tag}|#{value}" - end + formattted_tags = + if tags.is_a?(Array) + tags + else + tags.inject([]) do |acc, (tag, value)| + acc << "#{tag}|#{value}" + end + end + { tags: formattted_tags } end def format_metric(metric) diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index 4689e34..475f86f 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -47,7 +47,7 @@ context 'processes_hashed_inputs with tags in correct format' do let(:datadog_payload) do { - increment: { 'Counter_1' => { value: 1, tags: ['test']}, 'Counter_2' => { value: 2, tags: ['test']} }, + increment: { 'Counter_1' => { value: 1 }, 'Counter_2' => { value: 2, tags: ['test']} }, distribution: { 'Distribution_1' => { value: 10, tags: ['test']} }, set: { 'Set_1' => { value: 100, tags: ['test'] } }, gauge: { 'Gauge_1' => { value: 100, tags: ['test'] } } @@ -55,11 +55,11 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:count).with('Counter_1', 1, ['test']) - expect(mock_datadog).to receive(:count).with('Counter_2', 2, ['test']) - expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test']) - expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test']) - expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test']) + expect(mock_datadog).to receive(:count).with('Counter_1', 1, {}) + expect(mock_datadog).to receive(:count).with('Counter_2', 2, tags: ['test']) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, tags: ['test']) + expect(mock_datadog).to receive(:set).with('Set_1', 100, tags: ['test']) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, tags: ['test']) result = subject.send(expected_call, datadog: datadog_payload) @@ -72,7 +72,7 @@ let(:datadog_payload) do { increment: { - 'Counter_1' => { value: 1, tags: { test: 'value' } }, + 'Counter_1' => { value: 1 }, 'Counter_2' => { value: 2, tags: { test: 'value' } } }, distribution: { 'Distribution_1' => { value: 10, tags: { test: 'value' } } }, @@ -82,11 +82,11 @@ end it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).to receive(:count).with('Counter_1', 1, ['test|value']) - expect(mock_datadog).to receive(:count).with('Counter_2', 2, ['test|value']) - expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, ['test|value']) - expect(mock_datadog).to receive(:set).with('Set_1', 100, ['test|value']) - expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, ['test|value']) + expect(mock_datadog).to receive(:count).with('Counter_1', 1, {}) + expect(mock_datadog).to receive(:count).with('Counter_2', 2, tags: ['test|value']) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, tags: ['test|value']) + expect(mock_datadog).to receive(:set).with('Set_1', 100, tags: ['test|value']) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, tags: ['test|value']) result = subject.send(expected_call, datadog: datadog_payload) @@ -99,9 +99,11 @@ let(:datadog_payload) { {} } it 'skips any metric processing' do - expect(mock_datadog).not_to receive(:increment_counter) - expect(mock_datadog).not_to receive(:add_distribution_value) - expect(mock_datadog).not_to receive(:set_gauge) + expect(mock_datadog).not_to receive(:count) + expect(mock_datadog).not_to receive(:distribution) + expect(mock_datadog).not_to receive(:histogram) + expect(mock_datadog).not_to receive(:set) + expect(mock_datadog).not_to receive(:gauge) result = subject.send(expected_call, datadog: datadog_payload) @@ -110,10 +112,26 @@ end end - context 'processes_hashed_inputs with invalid tag' do + context 'processes_hashed_inputs with value and tag is nil' do let(:datadog_payload) do { - increment: { 'Counter_1' => { value: 1, invalid_tag: ['foo'] } } + increment: { 'Counter_1' => { value: 1, tag: nil } } + } + end + + it 'processes each hash keyset as a metric iteration' do + expect(mock_datadog).to receive(:count).with('Counter_1', 1, {}) + + result = subject.send(expected_call, datadog: datadog_payload) + + expect(result.success?).to eq true + end + end + + context 'processes_hashed_inputs with no value key' do + let(:datadog_payload) do + { + increment: { 'Counter_1' => { no_value: 1 } } } end @@ -123,7 +141,7 @@ result = subject.send(expected_call, datadog: datadog_payload) expect(result.success?).to eq false - expect(result.error).to eq 'Datadog payload { Counter_1: {:value=>1, :invalid_tag=>["foo"]} } invalid' + expect(result.error).to eq 'Datadog payload { Counter_1: {:no_value=>1} } invalid' end end @@ -155,9 +173,11 @@ let(:datadog_payload) { { metric => payload } } it 'rejects the payload when invalid datadog values are given' do - expect(mock_datadog).not_to receive(:increment_counter) - expect(mock_datadog).not_to receive(:add_distribution_value) - expect(mock_datadog).not_to receive(:set_gauge) + expect(mock_datadog).not_to receive(:count) + expect(mock_datadog).not_to receive(:distribution) + expect(mock_datadog).not_to receive(:histogram) + expect(mock_datadog).not_to receive(:set) + expect(mock_datadog).not_to receive(:gauge) result = subject.send(expected_call, datadog: datadog_payload) From 8fbfb9ccf7c46ca00402b20116c1d01dd8ef7e76 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Tue, 10 Nov 2020 19:50:09 +0800 Subject: [PATCH 16/22] remove dig --- lib/event_tracer/datadog_logger.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 9ff52f9..65a6bd8 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -49,7 +49,7 @@ def send_metric(metric, payload) format_metric(metric), increment, attribute.fetch(:value), - build_options(attribute.dig(:tags)) + build_options(attribute[:tags]) ) rescue KeyError raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" From 42b7e6ae27b0a1a0a22ec278e3f7a631b5c1d5a3 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Tue, 10 Nov 2020 19:53:36 +0800 Subject: [PATCH 17/22] use count instead of mapping increment --- README.md | 8 ++++---- lib/event_tracer/datadog_logger.rb | 15 ++++++--------- spec/event_tracer/datadog_logger_spec.rb | 10 +++++----- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 667c46a..a741c7f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This gem currently supports only: 2. add_distribution_value 3. set_gauge 3. Datadog: Empty wrapper around the custom metric distributions - 1. increment + 1. count 2. distribution 3. set 4. gauge @@ -127,7 +127,7 @@ The interface for using the Appsignal wrapper is: Key | Secondary key | Secondary key type | Values --------------|-------------|------------------|------- -datadog | increment | Hash | Hash of key-value pairs featuring the metric name and the counter value to send +datadog | count | Hash | Hash of key-value pairs featuring the metric name and the counter value to send | | distribution | Hash | Hash of key-value pairs featuring the metric name and the distribution value to send | | set | Hash | Hash of key-value pairs featuring the metric name and the set value to send | | gauge | Hash | Hash of key-value pairs featuring the metric name and the gauge value to send @@ -135,8 +135,8 @@ datadog | increment | Hash | Hash of key-value pairs featuring the metric name a ```ruby # Sample usage -EventTracer.info action: 'Action', message: 'Message', datadog: { increment: { counter_1: 1, counter_2: { value: 2, tags: ['foo']} } } -# This calls .increment_counter on Datadog twice with the 2 sets of arguments +EventTracer.info action: 'Action', message: 'Message', datadog: { count: { counter_1: 1, counter_2: { value: 2, tags: ['foo']} } } +# This calls .count on Datadog twice with the 2 sets of arguments # counter_1, 1 # counter_2, 2 ``` diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 65a6bd8..e9ef599 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -1,19 +1,20 @@ require_relative '../event_tracer' require_relative './basic_decorator' +require 'pry' # NOTES # Datadog interface to send our usual actions # BasicDecorator adds a transparent interface on top of the datadog interface # # Usage: EventTracer.register :datadog, EventTracer::DataDogLogger.new(DataDog) -# data_dog_logger.info datadog: { increment: { counter_1: 1, counter_2: 2 }, set: { gauge_1: 1 } } -# data_dog_logger.info datadog: { increment: { counter_1: { value: 1, tags: ['tag1, tag2']} } } +# data_dog_logger.info datadog: { count: { counter_1: 1, counter_2: 2 }, set: { gauge_1: 1 } } +# data_dog_logger.info datadog: { count: { counter_1: { value: 1, tags: ['tag1, tag2']} } } module EventTracer class DatadogLogger < BasicDecorator class InvalidTagError < StandardError; end - SUPPORTED_METRICS ||= %i[increment set distribution gauge histogram].freeze + SUPPORTED_METRICS ||= %i[count set distribution gauge histogram].freeze LOG_TYPES.each do |log_type| define_method log_type do |**args| @@ -46,7 +47,7 @@ def send_metric(metric, payload) if attribute.is_a?(Hash) begin datadog.send( - format_metric(metric), + metric, increment, attribute.fetch(:value), build_options(attribute[:tags]) @@ -55,7 +56,7 @@ def send_metric(metric, payload) raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" end else - datadog.send(format_metric(metric), increment, attribute) + datadog.send(metric, increment, attribute) end end end @@ -73,9 +74,5 @@ def build_options(tags) end { tags: formattted_tags } end - - def format_metric(metric) - metric == :increment ? :count : metric - end end end diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index 475f86f..43f58a2 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -23,7 +23,7 @@ context 'processes_hashed_inputs' do let(:datadog_payload) do { - increment: { 'Counter_1' => 1, 'Counter_2' => 2 }, + count: { 'Counter_1' => 1, 'Counter_2' => 2 }, distribution: { 'Distribution_1' => 10 }, set: { 'Set_1' => 100 }, gauge: { 'Gauge_1' => 100 } @@ -47,7 +47,7 @@ context 'processes_hashed_inputs with tags in correct format' do let(:datadog_payload) do { - increment: { 'Counter_1' => { value: 1 }, 'Counter_2' => { value: 2, tags: ['test']} }, + count: { 'Counter_1' => { value: 1 }, 'Counter_2' => { value: 2, tags: ['test']} }, distribution: { 'Distribution_1' => { value: 10, tags: ['test']} }, set: { 'Set_1' => { value: 100, tags: ['test'] } }, gauge: { 'Gauge_1' => { value: 100, tags: ['test'] } } @@ -71,7 +71,7 @@ context 'processes_hashed_inputs with tags as hash' do let(:datadog_payload) do { - increment: { + count: { 'Counter_1' => { value: 1 }, 'Counter_2' => { value: 2, tags: { test: 'value' } } }, @@ -115,7 +115,7 @@ context 'processes_hashed_inputs with value and tag is nil' do let(:datadog_payload) do { - increment: { 'Counter_1' => { value: 1, tag: nil } } + count: { 'Counter_1' => { value: 1, tag: nil } } } end @@ -131,7 +131,7 @@ context 'processes_hashed_inputs with no value key' do let(:datadog_payload) do { - increment: { 'Counter_1' => { no_value: 1 } } + count: { 'Counter_1' => { no_value: 1 } } } end From 4cf9a8a4ed8f06af24b543849a57093ae248dfe6 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Tue, 10 Nov 2020 20:00:33 +0800 Subject: [PATCH 18/22] remove invalidtag rescue --- lib/event_tracer/datadog_logger.rb | 2 -- spec/event_tracer/datadog_logger_spec.rb | 17 ----------------- 2 files changed, 19 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index e9ef599..2760a73 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -25,8 +25,6 @@ class InvalidTagError < StandardError; end return LogResult.new(false, "Datadog metric #{metric} invalid") unless metric_args.is_a?(Hash) send_metric metric, metric_args - rescue InvalidTagError => e - return LogResult.new(false, e.message) end LogResult.new(true) diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index 43f58a2..bc58f70 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -128,23 +128,6 @@ end end - context 'processes_hashed_inputs with no value key' do - let(:datadog_payload) do - { - count: { 'Counter_1' => { no_value: 1 } } - } - end - - it 'processes each hash keyset as a metric iteration' do - expect(mock_datadog).not_to receive(:count).with('Counter_1', 1) - - result = subject.send(expected_call, datadog: datadog_payload) - - expect(result.success?).to eq false - expect(result.error).to eq 'Datadog payload { Counter_1: {:no_value=>1} } invalid' - end - end - context 'rejects_invalid_datadog_args' do INVALID_PAYLOADS.each do |datadog_value| context 'Invalid datadog top-level args' do From 6d5361055521e4e9aecfbe956d0a45af41e8477f Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Tue, 10 Nov 2020 20:01:26 +0800 Subject: [PATCH 19/22] use public_send --- lib/event_tracer/datadog_logger.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 2760a73..262a1e6 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -44,7 +44,7 @@ def send_metric(metric, payload) payload.each do |increment, attribute| if attribute.is_a?(Hash) begin - datadog.send( + datadog.public_send( metric, increment, attribute.fetch(:value), @@ -54,7 +54,7 @@ def send_metric(metric, payload) raise InvalidTagError, "Datadog payload { #{increment}: #{attribute} } invalid" end else - datadog.send(metric, increment, attribute) + datadog.public_send(metric, increment, attribute) end end end From 1f024aa16ddd8f46e2fa3769432cad9ce2de3695 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Tue, 10 Nov 2020 21:00:08 +0800 Subject: [PATCH 20/22] remove pry --- lib/event_tracer/datadog_logger.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index 262a1e6..a55bf9b 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -1,6 +1,5 @@ require_relative '../event_tracer' require_relative './basic_decorator' -require 'pry' # NOTES # Datadog interface to send our usual actions # BasicDecorator adds a transparent interface on top of the datadog interface From ae719754307927510407bc649b8de7958b905c46 Mon Sep 17 00:00:00 2001 From: sylv3rblade Date: Wed, 11 Nov 2020 15:10:52 +0800 Subject: [PATCH 21/22] use colon as delimeter --- lib/event_tracer/datadog_logger.rb | 2 +- spec/event_tracer/datadog_logger_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/event_tracer/datadog_logger.rb b/lib/event_tracer/datadog_logger.rb index a55bf9b..dca8c37 100644 --- a/lib/event_tracer/datadog_logger.rb +++ b/lib/event_tracer/datadog_logger.rb @@ -66,7 +66,7 @@ def build_options(tags) tags else tags.inject([]) do |acc, (tag, value)| - acc << "#{tag}|#{value}" + acc << "#{tag}:#{value}" end end { tags: formattted_tags } diff --git a/spec/event_tracer/datadog_logger_spec.rb b/spec/event_tracer/datadog_logger_spec.rb index bc58f70..3827697 100644 --- a/spec/event_tracer/datadog_logger_spec.rb +++ b/spec/event_tracer/datadog_logger_spec.rb @@ -83,10 +83,10 @@ it 'processes each hash keyset as a metric iteration' do expect(mock_datadog).to receive(:count).with('Counter_1', 1, {}) - expect(mock_datadog).to receive(:count).with('Counter_2', 2, tags: ['test|value']) - expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, tags: ['test|value']) - expect(mock_datadog).to receive(:set).with('Set_1', 100, tags: ['test|value']) - expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, tags: ['test|value']) + expect(mock_datadog).to receive(:count).with('Counter_2', 2, tags: ['test:value']) + expect(mock_datadog).to receive(:distribution).with('Distribution_1', 10, tags: ['test:value']) + expect(mock_datadog).to receive(:set).with('Set_1', 100, tags: ['test:value']) + expect(mock_datadog).to receive(:gauge).with('Gauge_1', 100, tags: ['test:value']) result = subject.send(expected_call, datadog: datadog_payload) From 2a17bc7c5068d41fbbcc5ca0779632cdc30ba732 Mon Sep 17 00:00:00 2001 From: melvrickgoh Date: Thu, 12 Nov 2020 13:51:53 +0800 Subject: [PATCH 22/22] bump to 0.2 --- lib/event_tracer/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/event_tracer/version.rb b/lib/event_tracer/version.rb index 9b47e0d..14774e2 100644 --- a/lib/event_tracer/version.rb +++ b/lib/event_tracer/version.rb @@ -1,3 +1,3 @@ module EventTracer - VERSION = '0.1.4'.freeze + VERSION = '0.2.0'.freeze end