diff --git a/README.md b/README.md index 9ace93b..e5755d9 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ Or if you need to set multiple dimensions, you could use something like: Then you can get metrics for your `demo-web-puma` app. List of metrics: +* busy_threads: "wholistic" stat reflecting the overall current state of work to be done and the capacity to do it. * pool_capacity: the number of requests that the server is capable of taking right now. -* max_threads: preconfigured maximum number of worker threads. +* max_threads: preconfigured maximum number of worker threads. * running: the number of running threads (spawned threads) for any Puma worker. * backlog: the number of connections in that worker's "todo" set waiting for a worker thread. diff --git a/lib/puma_cloudwatch/metrics/parser.rb b/lib/puma_cloudwatch/metrics/parser.rb index 9e67c86..bcd9ed1 100644 --- a/lib/puma_cloudwatch/metrics/parser.rb +++ b/lib/puma_cloudwatch/metrics/parser.rb @@ -1,6 +1,6 @@ class PumaCloudwatch::Metrics class Parser - METRICS = [:backlog, :running, :pool_capacity, :max_threads] + METRICS = [:backlog, :busy_threads, :running, :pool_capacity, :max_threads] def initialize(data) @data = data @@ -14,6 +14,7 @@ def call # Build this structure: # # [{:backlog=>[0, 0], + # :busy_threads=>[0, 0], # :running=>[0, 0], # :pool_capacity=>[16, 16], # :max_threads=>[16, 16]}] diff --git a/lib/puma_cloudwatch/metrics/sender.rb b/lib/puma_cloudwatch/metrics/sender.rb index 6dfd052..e77ea69 100644 --- a/lib/puma_cloudwatch/metrics/sender.rb +++ b/lib/puma_cloudwatch/metrics/sender.rb @@ -54,19 +54,28 @@ def call # # [{:backlog=>[0, 0], # :running=>[0, 0], + # :busy_threads=>[0, 0], # :pool_capacity=>[16, 16], # :max_threads=>[16, 16]}] # # Output example: # # [{:metric_name=>"backlog", - # :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}}, + # :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + # :storage_resolution=>60}, + # {:metric_name=>"busy_threads", + # :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + # :storage_resolution=>60}, # {:metric_name=>"running", - # :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}}, + # :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + # :storage_resolution=>60}, # {:metric_name=>"pool_capacity", - # :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}}, + # :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}, + # :storage_resolution=>60}, # {:metric_name=>"max_threads", - # :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}}] + # :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}, + # :storage_resolution=>60 + # }] # # Resources: # pool_capcity and max_threads are the important metrics diff --git a/spec/puma_cloudwatch/metrics/fetcher_spec.rb b/spec/puma_cloudwatch/metrics/fetcher_spec.rb index 39c062d..31df499 100644 --- a/spec/puma_cloudwatch/metrics/fetcher_spec.rb +++ b/spec/puma_cloudwatch/metrics/fetcher_spec.rb @@ -1,11 +1,16 @@ RSpec.describe PumaCloudwatch::Metrics::Fetcher do - subject(:fetcher) { described_class.new(control_url: '', control_auth_token: '') } + subject(:fetcher) { described_class.new(control_url: 'unix:///tmp/fake.sock', control_auth_token: '') } describe "fetcher" do - it "call" do - fake_data = {"fake" => "data"} - json_data = JSON.dump(fake_data) - allow(Socket).to receive(:unix).and_return(json_data) + it "calls and parses the socket response" do + fake_data = { "fake" => "data" } + response_body = "HTTP/1.0 200 OK\r\n\r\n#{JSON.dump(fake_data)}" + + mock_socket = double("socket") + allow(mock_socket).to receive(:print) + allow(mock_socket).to receive(:read).and_return(response_body) + + allow(Socket).to receive(:unix).and_yield(mock_socket) stats = fetcher.call expect(stats).to eq(fake_data) diff --git a/spec/puma_cloudwatch/metrics/parser_spec.rb b/spec/puma_cloudwatch/metrics/parser_spec.rb index 3407279..2bb2a88 100644 --- a/spec/puma_cloudwatch/metrics/parser_spec.rb +++ b/spec/puma_cloudwatch/metrics/parser_spec.rb @@ -5,6 +5,7 @@ let(:data) do {"started_at"=>"2019-09-16T19:20:12Z", "backlog"=>0, + "busy_threads"=>0, "running"=>16, "pool_capacity"=>8, "max_threads"=>16} @@ -15,6 +16,7 @@ expect(results).to be_a(Array) expect(results).to eq( [{:backlog=>[0], + :busy_threads=>[0], :running=>[16], :pool_capacity=>[8], :max_threads=>[16]}] @@ -69,7 +71,7 @@ "booted"=>true, "last_checkin"=>"2019-09-16T16:12:41Z", "last_status"=> - {"backlog"=>0, "running"=>1, "pool_capacity"=>16, "max_threads"=>16}}, + {"backlog"=>0, "busy_threads"=>0, "running"=>1, "pool_capacity"=>16, "max_threads"=>16}}, {"started_at"=>"2019-09-16T16:12:11Z", "pid"=>19836, "index"=>1, @@ -78,6 +80,7 @@ "last_checkin"=>"2019-09-16T16:12:41Z", "last_status"=> {"backlog"=>0, + "busy_threads"=>0, "running"=>16, "pool_capacity"=>8, "max_threads"=>16}}]} @@ -89,6 +92,7 @@ expect(results).to be_a(Array) expect(results).to eq( [{:backlog=>[0, 0], + :busy_threads=>[0, 0], :running=>[1, 16], :pool_capacity=>[16, 8], :max_threads=>[16, 16]}] diff --git a/spec/puma_cloudwatch/metrics/sender_spec.rb b/spec/puma_cloudwatch/metrics/sender_spec.rb index fb6c1a8..9755cd2 100644 --- a/spec/puma_cloudwatch/metrics/sender_spec.rb +++ b/spec/puma_cloudwatch/metrics/sender_spec.rb @@ -5,6 +5,7 @@ context "metrics filled out" do let(:metrics) { [{:backlog=>[0], + :busy_threads=>[0], :running=>[16], :pool_capacity=>[8], :max_threads=>[16]}] @@ -14,17 +15,30 @@ data = sender.metric_data expect(data).to eq( [{:metric_name=>"backlog", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>1, :sum=>0, :minimum=>0, :maximum=>0}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>1, :sum=>0, :minimum=>0, :maximum=>0}, + :storage_resolution=>60 + }, + {:metric_name=>"busy_threads", + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>1, :sum=>0, :minimum=>0, :maximum=>0}, + :storage_resolution=>60 + }, {:metric_name=>"running", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>1, :sum=>16, :minimum=>16, :maximum=>16}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>1, :sum=>16, :minimum=>16, :maximum=>16}, + :storage_resolution=>60 + }, {:metric_name=>"pool_capacity", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>1, :sum=>8, :minimum=>8, :maximum=>8}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>1, :sum=>8, :minimum=>8, :maximum=>8}, + :storage_resolution=>60 + }, {:metric_name=>"max_threads", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>1, :sum=>16, :minimum=>16, :maximum=>16}}] + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>1, :sum=>16, :minimum=>16, :maximum=>16}, + :storage_resolution=>60 + }] ) end @@ -40,6 +54,7 @@ context "metrics filled out" do let(:metrics) { [{:backlog=>[0, 0], + :busy_threads=>[0, 0], :running=>[0, 0], :pool_capacity=>[16, 16], :max_threads=>[16, 16]}] @@ -49,17 +64,30 @@ data = sender.metric_data expect(data).to eq( [{:metric_name=>"backlog", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + :storage_resolution=>60 + }, + {:metric_name=>"busy_threads", + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + :storage_resolution=>60 + }, {:metric_name=>"running", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>2, :sum=>0, :minimum=>0, :maximum=>0}, + :storage_resolution=>60 + }, {:metric_name=>"pool_capacity", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}}, + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}, + :storage_resolution=>60 + }, {:metric_name=>"max_threads", - :dimensions=>[{:name=>"App", :value=>"demo-puma"}], - :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}}] + :dimensions=>[{:name=>"App", :value=>"puma"}], + :statistic_values=>{:sample_count=>2, :sum=>32, :minimum=>16, :maximum=>16}, + :storage_resolution=>60 + }] ) end