Skip to content

Commit

Permalink
Allow setting statsd_client to automatically configure StatsdListener
Browse files Browse the repository at this point in the history
  • Loading branch information
vu-hoang-kaligo committed Jan 15, 2025
1 parent b38b50e commit db4eeb5
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

## [0.1.4] - 2025-01-14

- Support instrumentation via event hook approach
- Support metrics logging via StatsdListener

## [0.1.3] - 2025-01-14
Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ Idempotency.configure do |config|
}

config.idempotent_methods = %w[POST PUT PATCH]
config.idempotent_statuses = (200..299).to_a
config.idempotent_statuses = (200..299).to_a + (400..499).to_a

# Metrics configuration
config.metrics.statsd_client = statsd_client # Your StatsD client instance
config.metrics.namespace = 'my_service_name' # Optional namespace for metrics

# Custom instrumentation listeners (optional)
config.instrumentation_listeners = [my_custom_listener] # Array of custom listeners
end
```

Expand Down Expand Up @@ -102,7 +109,7 @@ end

### Instrumentation

The gem supports instrumentation through StatsD. It tracks the following metrics:
The gem supports instrumentation through StatsD out of the box. When you configure a StatsD client in the configuration, the StatsdListener will be automatically set up. It tracks the following metrics:

- `idempotency_cache_hit_count` - Incremented when a cached response is found
- `idempotency_cache_miss_count` - Incremented when no cached response exists
Expand All @@ -114,17 +121,11 @@ Each metric includes tags:
- `namespace` - Your configured namespace (if provided)
- `metric` - The metric name (for duration histogram only)

To enable above instrumentation, configure a StatsD listener:
To enable StatsD instrumentation, simply configure the metrics settings:

```ruby
statsd_client = Datadog::Statsd.new
statsd_listener = Idempotency::Instrumentation::StatsdListener.new(
statsd_client,
'my_service_name'
)

Idempotency.configure do |config|
config.instrumentation_listeners = [statsd_listener]
config.metrics.statsd_client = Datadog::Statsd.new
config.metrics.namespace = 'my_service_name'
end
```

11 changes: 11 additions & 0 deletions lib/idempotency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def self.notifier
setting :redis_pool
setting :logger
setting :instrumentation_listeners, default: []
setting :metrics do
setting :namespace
setting :statsd_client
end

setting :default_lock_expiry, default: 300 # 5 minutes
setting :idempotent_methods, default: %w[POST PUT PATCH DELETE]
Expand All @@ -37,6 +41,13 @@ def self.notifier
def self.configure
super

if config.metrics.statsd_client
config.instrumentation_listeners << Idempotency::Instrumentation::StatsdListener.new(
config.metrics.statsd_client,
config.metrics.namespace
)
end

config.instrumentation_listeners.each(&:setup_subscriptions)
end

Expand Down
38 changes: 38 additions & 0 deletions spec/idempotency_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,42 @@
expect(config.default_lock_expiry).to eq(60)
expect(config.response_body.concurrent_error).to eq({ errors: [{ code: 'GH0004', message: 'Some message' }] })
end

describe '#configure' do
let(:statsd_client) { double('statsd_client') }
let(:custom_listener) { double('custom_listener', setup_subscriptions: true) }

before do
described_class.config.metrics.statsd_client = nil
described_class.config.instrumentation_listeners = []
end

it 'sets up StatsdListener when statsd_client is configured' do
expect(Idempotency::Instrumentation::StatsdListener).to receive(:new)
.with(statsd_client, 'test_namespace')
.and_return(custom_listener)

described_class.configure do |config|
config.metrics.statsd_client = statsd_client
config.metrics.namespace = 'test_namespace'
end

expect(described_class.config.instrumentation_listeners).to include(custom_listener)
end

it 'calls setup_subscriptions on all listeners' do
described_class.config.instrumentation_listeners = [custom_listener]
expect(custom_listener).to receive(:setup_subscriptions)

described_class.configure
end

it 'does not add StatsdListener when statsd_client is not configured' do
described_class.configure do |config|
config.metrics.namespace = 'test_namespace'
end

expect(described_class.config.instrumentation_listeners).to be_empty
end
end
end

0 comments on commit db4eeb5

Please sign in to comment.