yabeda-hotcell 0.0.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9369f5229ab4571f30d14935b33d5c5de90da1db6319a7f2f2cf07f628658bd
4
- data.tar.gz: 5e0d716dcd184fcd9c9bd64b17d66645441d4c4b89fd9d262d68a3e664381de1
3
+ metadata.gz: 0fb7ba45b18d7d8edcaca91975fe68e3fc3acd213a676ca703564184d7df15fe
4
+ data.tar.gz: a709e9d5df13952723126af13d9189c2dbbff865ec1fb39813da9514737578df
5
5
  SHA512:
6
- metadata.gz: fd41b7aff574b0d969e17999149eda6471275d94d4e467b40dbee7be8a90e8661108ba224422eefe09098b9570aeabcbec968a7a0f45a54c12203cd7f2c22a88
7
- data.tar.gz: 12159d1d9cd1d04171457190c2cf02f537c97b3bf2692cbbc1080298c9a8d1fad31377f6eb7683f59889d48cf729a3f544b23b74e0fe265b2b6ffb1513fb384d
6
+ metadata.gz: 8a325a46e9342f07ecfbecef29fd42187c2e6594a255eca648df52c5eae98d1c13520aa5fae8756d32644d428747eb0b17242b18b5a5f98006fac0953d32aa51
7
+ data.tar.gz: 91b9ec082349f6a3e94f487ecb33dc172ee26f231bc22edfb33529728acf2e267e04007a67dc6c97bd4f979c1813ee77c0c8774f400df28c5db86a898aa167fa
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 37signals, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # yabeda-hotcell
2
2
 
3
- Yabeda metrics for [HotCell](https://github.com/basecamp/hotcell). This gem will be published shortly.
3
+ Part of [HotCell](https://github.com/basecamp/hotcell). See the repository README.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Yabeda
4
+ module HotCell
5
+ VERSION = "0.6.0"
6
+ end
7
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support"
4
+ require "hot_cell/client"
5
+ require "yabeda"
6
+
7
+ require "yabeda/hot_cell/version"
8
+
9
+ module Yabeda
10
+ # A cell's control socket is host-local, and the collect block runs in every scraped process on every host,
11
+ # which matches that topology exactly.
12
+ #
13
+ # Two namespace traps here, both silent. Inside `module Yabeda`, `HotCell` resolves to this module, so the
14
+ # client must be named ::HotCell. And `hotcell` is a DSL method that exists only inside Yabeda.configure, so
15
+ # anything factored out of the collect block must say Yabeda.hotcell.
16
+ module HotCell
17
+ def self.install!
18
+ Yabeda.configure do
19
+ group :hotcell
20
+
21
+ counter :requests, comment: "Calls through perform_in_hotcell, by outcome",
22
+ tags: %i[ cell operation code cause ]
23
+ histogram :perform, comment: "Time the cell spent performing", unit: :seconds,
24
+ tags: %i[ cell operation ], buckets: [ 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 120 ]
25
+
26
+ gauge :up, comment: "1 when the local cell answers its control socket",
27
+ tags: %i[ cell ], aggregation: :most_recent
28
+ gauge :running, comment: "Workers busy right now", tags: %i[ cell ], aggregation: :most_recent
29
+ gauge :queued, comment: "Connections waiting for a worker", tags: %i[ cell ], aggregation: :most_recent
30
+ gauge :queue_high_water, comment: "Deepest the queue has been since boot",
31
+ tags: %i[ cell ], aggregation: :most_recent
32
+ gauge :cancelled, comment: "Callers that gave up before the cell answered (a floor)",
33
+ tags: %i[ cell ], aggregation: :most_recent
34
+ gauge :killed, comment: "Workers killed since boot, by cause",
35
+ tags: %i[ cell cause ], aggregation: :most_recent
36
+ gauge :uptime_seconds, comment: "Seconds since the supervisor booted",
37
+ tags: %i[ cell ], aggregation: :most_recent
38
+
39
+ collect { Yabeda::HotCell.collect_stats }
40
+ end
41
+
42
+ subscribe_to_performs
43
+ end
44
+
45
+ def self.collect_stats
46
+ ::HotCell.cells.each_value do |cell|
47
+ next unless cell.enabled?
48
+
49
+ response = cell.metrics
50
+ Yabeda.hotcell.up.set({ cell: cell.name }, response&.ok? ? 1 : 0)
51
+ next unless response&.ok?
52
+
53
+ set_counters cell, response.result
54
+ end
55
+ rescue => error
56
+ # A scrape must not fail because a cell is misbehaving. In a Rails application this is Rails.error.
57
+ ::ActiveSupport.error_reporter.report error, handled: true
58
+ end
59
+
60
+ # The subscriber raises into whoever called instrument, so an unguarded bug here would arrive as a failed
61
+ # call rather than as missing metrics.
62
+ def self.subscribe_to_performs
63
+ ::ActiveSupport::Notifications.subscribe "perform.hot_cell" do |event|
64
+ record_perform event
65
+ rescue => error
66
+ ::ActiveSupport.error_reporter.report error, handled: true
67
+ end
68
+ end
69
+
70
+ # A failed call is not reported from here: the raise the caller sees already reaches the error reporter.
71
+ def self.record_perform(event)
72
+ labels = { cell: event.payload[:cell], operation: event.payload[:operation] }
73
+
74
+ # Empty rather than absent, because a label that is sometimes missing is a separate series in Prometheus
75
+ # and a query by code would silently split.
76
+ Yabeda.hotcell.requests.increment(labels.merge(code: event.payload[:code] || "ok",
77
+ cause: event.payload[:cause].to_s))
78
+ Yabeda.hotcell.perform.measure(labels, (event.payload[:perform_ms] || 0) / 1000.0)
79
+ end
80
+
81
+ private_class_method def self.set_counters(cell, counters)
82
+ tags = { cell: cell.name }
83
+
84
+ Yabeda.hotcell.running.set(tags, counters[:running])
85
+ Yabeda.hotcell.queued.set(tags, counters[:queued])
86
+ Yabeda.hotcell.queue_high_water.set(tags, counters[:queue_high_water])
87
+ Yabeda.hotcell.cancelled.set(tags, counters[:cancelled])
88
+ Yabeda.hotcell.uptime_seconds.set(tags, counters[:uptime_s])
89
+ ::HotCell::Codes::PERMANENT_BY_CAUSE.each_key do |cause|
90
+ Yabeda.hotcell.killed.set(tags.merge(cause: cause), counters[:killed_by].fetch(cause.to_sym, 0))
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Bundler auto-requires a gem named "yabeda-hotcell" as "yabeda-hotcell", then as "yabeda/hotcell". This gem
4
+ # uses neither path, because hot_cell/ is what yields the HotCell constant under the default inflection.
5
+ require "yabeda/hot_cell"
metadata CHANGED
@@ -1,25 +1,64 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yabeda-hotcell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Dalessio
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: hotcell-client
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 0.6.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '='
24
+ - !ruby/object:Gem::Version
25
+ version: 0.6.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: yabeda
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0.12'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0.12'
40
+ description: |
41
+ Yabeda metrics for an application that calls HotCell cells: a counter and a histogram for every call,
42
+ and gauges polled from each local cell's control socket.
12
43
  email:
13
44
  - mike@37signals.com
14
45
  executables: []
15
46
  extensions: []
16
47
  extra_rdoc_files: []
17
48
  files:
49
+ - MIT-LICENSE
18
50
  - README.md
51
+ - lib/yabeda-hotcell.rb
52
+ - lib/yabeda/hot_cell.rb
53
+ - lib/yabeda/hot_cell/version.rb
19
54
  homepage: https://github.com/basecamp/hotcell
20
55
  licenses:
21
56
  - MIT
22
57
  metadata:
58
+ homepage_uri: https://github.com/basecamp/hotcell
59
+ source_code_uri: https://github.com/basecamp/hotcell/tree/v0.6.0/yabeda-hotcell
60
+ changelog_uri: https://github.com/basecamp/hotcell/blob/v0.6.0/CHANGELOG.md
61
+ bug_tracker_uri: https://github.com/basecamp/hotcell/issues
23
62
  rubygems_mfa_required: 'true'
24
63
  rdoc_options: []
25
64
  require_paths:
@@ -28,7 +67,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
28
67
  requirements:
29
68
  - - ">="
30
69
  - !ruby/object:Gem::Version
31
- version: '0'
70
+ version: '3.3'
32
71
  required_rubygems_version: !ruby/object:Gem::Requirement
33
72
  requirements:
34
73
  - - ">="
@@ -37,6 +76,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
37
76
  requirements: []
38
77
  rubygems_version: 4.0.6
39
78
  specification_version: 4
40
- summary: Yabeda metrics for HotCell. Reserves the name; the real gem will be published
41
- shortly.
79
+ summary: Yabeda metrics for HotCell.
42
80
  test_files: []