From d548e7fccb8a2f55f30ab427dc284a696beae62a Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 08:03:19 +1100 Subject: [PATCH 01/11] commit changes --- Gemfile | 1 + Gemfile.lock | 2 ++ bin/datadog_statsd | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100755 bin/datadog_statsd diff --git a/Gemfile b/Gemfile index 57b85832..669653b0 100644 --- a/Gemfile +++ b/Gemfile @@ -23,4 +23,5 @@ group :development, :test do gem "rubocop", "~> 1.70" gem "simplecov", "~> 0.0" gem "yard", ">= 0.9.36", "< 1.0" + gem "dogstatsd-ruby", "~> 5.7", ">= 5.7.1" end diff --git a/Gemfile.lock b/Gemfile.lock index da3e51fb..f8553ac3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,6 +46,7 @@ GEM database_cleaner-core (2.0.1) diff-lcs (1.5.1) docile (1.4.0) + dogstatsd-ruby (5.7.1) dotenv (3.1.2) drb (2.2.3) factory_bot (6.4.6) @@ -169,6 +170,7 @@ PLATFORMS DEPENDENCIES coveralls_reborn database_cleaner (~> 2.0) + dogstatsd-ruby (~> 5.7, >= 5.7.1) dotenv (~> 3.0) factory_bot (~> 6.0) foreman (~> 0.0) diff --git a/bin/datadog_statsd b/bin/datadog_statsd new file mode 100755 index 00000000..1880ffb0 --- /dev/null +++ b/bin/datadog_statsd @@ -0,0 +1,46 @@ +#!/usr/bin/env ruby + +require "bundler/setup" +require "datadog/statsd" +require "outboxer" + +environment = ENV["RAILS_ENV"] || "development" +db_config = Outboxer::Database.config(environment: environment, pool: 1) +Outboxer::Database.connect(config: db_config) + +running = true + +["TERM", "INT"].each do |sig| + Signal.trap(sig) { running = false } +end + +dogstatsd = Datadog::Statsd.new( + "127.0.0.1", 8125, + tags: ["env:#{environment}", "service:outboxer", "version:#{Outboxer::VERSION}"] +) + +interval = 10 +tick = 1 + +logger = Outboxer::Logger.new($stdout, level: 1) +logger.info "Sending outboxer.messages.* statsd metrics to datadog..." + +while running + Outboxer::Message.metrics_by_status.each do |status, metrics| + dogstatsd.gauge("outboxer.messages.count", metrics[:count], tags: ["status:#{status}"]) + + if metrics[:latency] + dogstatsd.gauge("outboxer.messages.latency", metrics[:latency], tags: ["status:#{status}"]) + end + end + + slept = 0 + + while running && slept < interval + sleep tick + + slept += tick + end +end + +logger.info "Shutting down" From 0d289eeec119b982efd2891f6695952765bf345f Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 08:10:04 +1100 Subject: [PATCH 02/11] fix build --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 669653b0..efc7ffeb 100644 --- a/Gemfile +++ b/Gemfile @@ -12,6 +12,7 @@ gem "sinatra", "~> 4.2" group :development, :test do gem "database_cleaner", "~> 2.0" + gem "dogstatsd-ruby", "~> 5.7", ">= 5.7.1" gem "dotenv", "~> 3.0" gem "factory_bot", "~> 6.0" gem "foreman", "~> 0.0" @@ -23,5 +24,4 @@ group :development, :test do gem "rubocop", "~> 1.70" gem "simplecov", "~> 0.0" gem "yard", ">= 0.9.36", "< 1.0" - gem "dogstatsd-ruby", "~> 5.7", ">= 5.7.1" end From 162cb1d1f313b9bab1ca132b49686aa8ea05044b Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 09:23:55 +1100 Subject: [PATCH 03/11] commit broken spec --- docker-compose.yml | 16 +++++++++++++++ spec/bin/datadog_statsd_spec.rb | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 docker-compose.yml create mode 100644 spec/bin/datadog_statsd_spec.rb diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..3579435c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: "3.9" + +services: + datadog: + image: datadog/agent:7.54.0 + container_name: datadog + environment: + DD_API_KEY: "fake" + + DD_DOGSTATSD_ONLY: "true" + DD_DOGSTATSD_NON_LOCAL_TRAFFIC: "true" + + DD_DOGSTATSD_LOG_LEVEL: "debug" + + ports: + - "18125:8125/udp" diff --git a/spec/bin/datadog_statsd_spec.rb b/spec/bin/datadog_statsd_spec.rb new file mode 100644 index 00000000..9dce1b0b --- /dev/null +++ b/spec/bin/datadog_statsd_spec.rb @@ -0,0 +1,35 @@ +require "open3" +require "timeout" + +RSpec.describe "Outboxer StatsD (Datadog agent logs)" do + before do + system("docker restart datadog") + sleep 2 + end + + it "emits expected statsd metrics" do + Open3.popen3( + { + "RAILS_ENV" => "test", + "STATSD_HOST" => "127.0.0.1", + "STATSD_PORT" => "18125" + }, + "ruby bin/statsd_publisher" + ) do |_stdin, _stdout, _stderr, wait_thr| + sleep 3 + + if wait_thr.alive? + Process.kill("TERM", wait_thr.pid) + end + + wait_thr.value + end + + logs = `docker logs datadog` + + expect(logs).to include("Processing metric sample") + expect(logs).to include("outboxer.messages.count") + expect(logs).to include("outboxer.messages.latency") + expect(logs).to include("status:") + end +end From a25d9a291f4f74a94e183fdd6c61ad7d5ba3a8e9 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 20:40:09 +1100 Subject: [PATCH 04/11] rename script --- bin/{datadog_statsd => outboxer_datadog_metrics} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename bin/{datadog_statsd => outboxer_datadog_metrics} (100%) diff --git a/bin/datadog_statsd b/bin/outboxer_datadog_metrics similarity index 100% rename from bin/datadog_statsd rename to bin/outboxer_datadog_metrics From c22a465e8555664bdfbb79c67125646b97f160e2 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 20:50:28 +1100 Subject: [PATCH 05/11] update require --- bin/outboxer_datadog_metrics | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/bin/outboxer_datadog_metrics b/bin/outboxer_datadog_metrics index 1880ffb0..dfcac3e7 100755 --- a/bin/outboxer_datadog_metrics +++ b/bin/outboxer_datadog_metrics @@ -1,7 +1,21 @@ #!/usr/bin/env ruby require "bundler/setup" -require "datadog/statsd" + +begin + require "datadog/statsd" +rescue LoadError + abort <<~MSG + dogstatsd-ruby is not installed. + + Add it to your Gemfile: + + gem "dogstatsd-ruby" + + Then run bundle install. + MSG +end + require "outboxer" environment = ENV["RAILS_ENV"] || "development" From a7cad67e1a40ee14b28c492877cd7707ad17b714 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:05:21 +1100 Subject: [PATCH 06/11] add datadog metrics generator --- generators/datadog_metrics_generator.rb | 29 +++++++++++++++++++++++++ generators/install_generator.rb | 2 ++ 2 files changed, 31 insertions(+) create mode 100644 generators/datadog_metrics_generator.rb diff --git a/generators/datadog_metrics_generator.rb b/generators/datadog_metrics_generator.rb new file mode 100644 index 00000000..69f46b50 --- /dev/null +++ b/generators/datadog_metrics_generator.rb @@ -0,0 +1,29 @@ +module Outboxer + class InstallDatadogMetricsGenerator < Rails::Generators::Base + source_root File.expand_path("../", __dir__) + + def copy_bin_file + template "bin/outboxer_datadog_metrics", "bin/outboxer_datadog_metrics" + run "chmod +x bin/outboxer_datadog_metrics" + end + + def print_instructions + say <<~MSG + + To complete setup: + + 1. Add to Gemfile: + gem "dogstatsd-ruby" + + 2. Run: + bundle install + + 3. Start: + bin/outboxer_datadog_metrics + + MSG + end + end +end + +# bundle exec rails g outboxer:install_datadog_metrics diff --git a/generators/install_generator.rb b/generators/install_generator.rb index 710a6ad5..1e64b92c 100644 --- a/generators/install_generator.rb +++ b/generators/install_generator.rb @@ -48,3 +48,5 @@ def copy_bin_file end end end + +# bundle exec rails g outboxer:install From e2dc0472647278e35bcf5738457c52daea48ecb3 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:20:38 +1100 Subject: [PATCH 07/11] update generator --- generators/datadog_metrics_generator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/generators/datadog_metrics_generator.rb b/generators/datadog_metrics_generator.rb index 69f46b50..6576c270 100644 --- a/generators/datadog_metrics_generator.rb +++ b/generators/datadog_metrics_generator.rb @@ -27,3 +27,4 @@ def print_instructions end # bundle exec rails g outboxer:install_datadog_metrics +# bin/outboxer_datadog_metrics From 2c15b2fe0e2c06a5edb632d8dce001c2788d445f Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:21:57 +1100 Subject: [PATCH 08/11] delete files --- docker-compose.yml | 16 --------------- spec/bin/datadog_statsd_spec.rb | 35 --------------------------------- 2 files changed, 51 deletions(-) delete mode 100644 docker-compose.yml delete mode 100644 spec/bin/datadog_statsd_spec.rb diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 3579435c..00000000 --- a/docker-compose.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: "3.9" - -services: - datadog: - image: datadog/agent:7.54.0 - container_name: datadog - environment: - DD_API_KEY: "fake" - - DD_DOGSTATSD_ONLY: "true" - DD_DOGSTATSD_NON_LOCAL_TRAFFIC: "true" - - DD_DOGSTATSD_LOG_LEVEL: "debug" - - ports: - - "18125:8125/udp" diff --git a/spec/bin/datadog_statsd_spec.rb b/spec/bin/datadog_statsd_spec.rb deleted file mode 100644 index 9dce1b0b..00000000 --- a/spec/bin/datadog_statsd_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -require "open3" -require "timeout" - -RSpec.describe "Outboxer StatsD (Datadog agent logs)" do - before do - system("docker restart datadog") - sleep 2 - end - - it "emits expected statsd metrics" do - Open3.popen3( - { - "RAILS_ENV" => "test", - "STATSD_HOST" => "127.0.0.1", - "STATSD_PORT" => "18125" - }, - "ruby bin/statsd_publisher" - ) do |_stdin, _stdout, _stderr, wait_thr| - sleep 3 - - if wait_thr.alive? - Process.kill("TERM", wait_thr.pid) - end - - wait_thr.value - end - - logs = `docker logs datadog` - - expect(logs).to include("Processing metric sample") - expect(logs).to include("outboxer.messages.count") - expect(logs).to include("outboxer.messages.latency") - expect(logs).to include("status:") - end -end From df77661109a3a883762fa623cccbf0a7bc387617 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:28:18 +1100 Subject: [PATCH 09/11] update gemspec dev deps --- outboxer.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/outboxer.gemspec b/outboxer.gemspec index e810d7c1..eefd277c 100644 --- a/outboxer.gemspec +++ b/outboxer.gemspec @@ -33,4 +33,5 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "activerecord", ">= 7.0.8.6" + spec.add_development_dependency "dogstatsd-ruby" end From 603a5b5ab8815752c279ba7d469d43dd6607ea55 Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:43:24 +1100 Subject: [PATCH 10/11] rename variables --- bin/outboxer_datadog_metrics | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/outboxer_datadog_metrics b/bin/outboxer_datadog_metrics index dfcac3e7..b5699b79 100755 --- a/bin/outboxer_datadog_metrics +++ b/bin/outboxer_datadog_metrics @@ -33,8 +33,8 @@ dogstatsd = Datadog::Statsd.new( tags: ["env:#{environment}", "service:outboxer", "version:#{Outboxer::VERSION}"] ) -interval = 10 -tick = 1 +sleep_interval = 60 +tick_interval = 1 logger = Outboxer::Logger.new($stdout, level: 1) logger.info "Sending outboxer.messages.* statsd metrics to datadog..." @@ -50,10 +50,10 @@ while running slept = 0 - while running && slept < interval - sleep tick + while running && slept < sleep_interval + sleep tick_interval - slept += tick + slept += tick_interval end end From ab4d8855de774525db4613b36d7da7ca093b5b1d Mon Sep 17 00:00:00 2001 From: bedrock-adam Date: Sat, 10 Jan 2026 21:49:48 +1100 Subject: [PATCH 11/11] fix build --- outboxer.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/outboxer.gemspec b/outboxer.gemspec index eefd277c..e810d7c1 100644 --- a/outboxer.gemspec +++ b/outboxer.gemspec @@ -33,5 +33,4 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.add_dependency "activerecord", ">= 7.0.8.6" - spec.add_development_dependency "dogstatsd-ruby" end