-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
afbd363
commit 0ee5eed
Showing
10 changed files
with
276 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative '../../idempotency' | ||
|
||
class Idempotency | ||
module Instrumentation | ||
class DatadogListener | ||
EVENT_NAME_TO_METRIC_MAPPINGS = { | ||
Events::CACHE_HIT => 'idempotency_cache_hit_count', | ||
Events::CACHE_MISS => 'idempotency_cache_miss_count', | ||
Events::LOCK_CONFLICT => 'idempotency_lock_conflict_count' | ||
}.freeze | ||
|
||
def initialize(statsd_client, namespace = nil) | ||
@statsd_client = statsd_client | ||
@namespace = namespace | ||
end | ||
|
||
def setup_subscriptions | ||
EVENT_NAME_TO_METRIC_MAPPINGS.each do |event_name, metric| | ||
Idempotency.notifier.subscribe(event_name) do |event| | ||
send_metric(metric, event.payload) | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
attr_reader :namespace, :statsd_client | ||
|
||
def send_metric(metric_name, event_data) | ||
action = event_data[:action] || "#{event_data[:request].request_method}:#{event_data[:request].path}" | ||
tags = ["action:#{action}"] | ||
tags << "namespace:#{@namespace}" if @namespace | ||
|
||
@statsd_client.increment(metric_name, tags:) | ||
@statsd_client.histogram( | ||
'idempotency_cache_duration_seconds', event_data[:duration], tags: tags + ["metric:#{metric_name}"] | ||
) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
spec/idempotency/instrumentation/datadog_listener_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe Idempotency::Instrumentation::DatadogListener do | ||
let(:statsd_client) { double('statsd_client') } | ||
let(:namespace) { 'test_app' } | ||
let(:listener) { described_class.new(statsd_client, namespace) } | ||
let(:request) do | ||
double( | ||
'Request', | ||
request_method: 'POST', | ||
path: '/orders/123' | ||
) | ||
end | ||
let(:event_payload) do | ||
{ | ||
request: request, | ||
action: 'POST:/orders/create', | ||
duration: 0.1 | ||
} | ||
end | ||
let(:notifier) do | ||
Dry::Monitor::Notifications.new(:test).tap do |n| | ||
Idempotency::Events::ALL_EVENTS.each { |event| n.register_event(event) } | ||
end | ||
end | ||
|
||
before do | ||
allow(Idempotency).to receive(:notifier).and_return(notifier) | ||
listener.setup_subscriptions | ||
end | ||
|
||
context 'when cache hit event is triggered' do | ||
it 'sends correct metrics' do | ||
expect(statsd_client).to receive(:increment).with( | ||
'idempotency_cache_hit_count', | ||
tags: ['action:POST:/orders/create', 'namespace:test_app'] | ||
) | ||
expect(statsd_client).to receive(:histogram).with( | ||
'idempotency_cache_duration_seconds', | ||
0.1, | ||
tags: [ | ||
'action:POST:/orders/create', | ||
'namespace:test_app', | ||
'metric:idempotency_cache_hit_count' | ||
] | ||
) | ||
|
||
Idempotency.notifier.instrument(Idempotency::Events::CACHE_HIT, event_payload) | ||
end | ||
end | ||
|
||
context 'when cache miss event is triggered' do | ||
it 'sends correct metrics' do | ||
expect(statsd_client).to receive(:increment).with( | ||
'idempotency_cache_miss_count', | ||
tags: ['action:POST:/orders/create', 'namespace:test_app'] | ||
) | ||
expect(statsd_client).to receive(:histogram).with( | ||
'idempotency_cache_duration_seconds', | ||
0.1, | ||
tags: [ | ||
'action:POST:/orders/create', | ||
'namespace:test_app', | ||
'metric:idempotency_cache_miss_count' | ||
] | ||
) | ||
|
||
Idempotency.notifier.instrument(Idempotency::Events::CACHE_MISS, event_payload) | ||
end | ||
end | ||
|
||
context 'when lock conflict event is triggered' do | ||
it 'sends correct metrics' do | ||
expect(statsd_client).to receive(:increment).with( | ||
'idempotency_lock_conflict_count', | ||
tags: ['action:POST:/orders/create', 'namespace:test_app'] | ||
) | ||
expect(statsd_client).to receive(:histogram).with( | ||
'idempotency_cache_duration_seconds', | ||
0.1, | ||
tags: [ | ||
'action:POST:/orders/create', | ||
'namespace:test_app', | ||
'metric:idempotency_lock_conflict_count' | ||
] | ||
) | ||
|
||
Idempotency.notifier.instrument(Idempotency::Events::LOCK_CONFLICT, event_payload) | ||
end | ||
end | ||
|
||
context 'when action is not provided' do | ||
let(:event_payload) do | ||
{ | ||
request: request, | ||
duration: 0.1 | ||
} | ||
end | ||
|
||
it 'uses request method and path as action' do | ||
expect(statsd_client).to receive(:increment).with( | ||
'idempotency_cache_hit_count', | ||
tags: ['action:POST:/orders/123', 'namespace:test_app'] | ||
) | ||
expect(statsd_client).to receive(:histogram).with( | ||
'idempotency_cache_duration_seconds', | ||
0.1, | ||
tags: [ | ||
'action:POST:/orders/123', | ||
'namespace:test_app', | ||
'metric:idempotency_cache_hit_count' | ||
] | ||
) | ||
|
||
Idempotency.notifier.instrument(Idempotency::Events::CACHE_HIT, event_payload) | ||
end | ||
end | ||
|
||
context 'when namespace is not provided' do | ||
let(:listener) { described_class.new(statsd_client) } | ||
|
||
it 'does not include namespace tag' do | ||
expect(statsd_client).to receive(:increment).with( | ||
'idempotency_cache_hit_count', | ||
tags: ['action:POST:/orders/create'] | ||
) | ||
expect(statsd_client).to receive(:histogram).with( | ||
'idempotency_cache_duration_seconds', | ||
0.1, | ||
tags: [ | ||
'action:POST:/orders/create', | ||
'metric:idempotency_cache_hit_count' | ||
] | ||
) | ||
|
||
Idempotency.notifier.instrument(Idempotency::Events::CACHE_HIT, event_payload) | ||
end | ||
end | ||
end |
Oops, something went wrong.