memosig 0.0.1 → 0.0.2
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 +4 -4
- data/.rspec +2 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/memosig/app.rb +7 -4
- data/lib/memosig/matcher.rb +28 -11
- data/lib/memosig/version.rb +1 -1
- data/memosig.gemspec +7 -4
- data/spec/memosig/app_spec.rb +76 -4
- data/spec/memosig/matcher_spec.rb +60 -0
- data/spec/memosig/output_spec.rb +23 -0
- data/spec/spec_helper.rb +4 -0
- metadata +20 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c880791fc4181394f342e11786014bf822463364
|
4
|
+
data.tar.gz: b62e09190fcc3e8dd8b17b09d9d64199b2efda5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d6dbcea19b281cbc93d074a2c5e9c493e207af94adbf2e704e5e1c447ac2155eef302c1bf62edc72b9657af21d740d241ae9b12315a33ab3d4a3cc4f03ea850
|
7
|
+
data.tar.gz: de76ecef394151e6be0ac1c2f7a8b3920a6f7e76e412b075d9fd77926d7f778ba4250ac5752ed549959938ee47d0e9d4ae5a7b11321b4e7547209d9ba486ee78
|
data/.rspec
ADDED
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/memosig/app.rb
CHANGED
@@ -14,7 +14,7 @@ class Memosig::App
|
|
14
14
|
|
15
15
|
def run
|
16
16
|
check_memory
|
17
|
-
sleep (@config.wait_period || 300)
|
17
|
+
sleep (@config.wait_period? || 300)
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
@@ -23,14 +23,17 @@ class Memosig::App
|
|
23
23
|
processes.any? do |process|
|
24
24
|
Memosig::Matcher.new(pattern, config).match? process
|
25
25
|
end and return
|
26
|
-
error "pattern #{pattern.
|
26
|
+
error "pattern #{pattern.to_s.inspect} didn't match any processes"
|
27
|
+
end
|
28
|
+
|
29
|
+
def current_processes
|
30
|
+
Memosig::ProcStat.all
|
27
31
|
end
|
28
32
|
|
29
33
|
def check_memory
|
30
34
|
output "checking memory limits"
|
31
|
-
processes =
|
35
|
+
processes = current_processes
|
32
36
|
for (pattern, config) in Array(@config.processes)
|
33
|
-
pattern = Regexp.new(pattern.to_s)
|
34
37
|
check_memory_for pattern, config, processes
|
35
38
|
end
|
36
39
|
end
|
data/lib/memosig/matcher.rb
CHANGED
@@ -4,22 +4,39 @@ class ::Memosig::Matcher
|
|
4
4
|
include Memosig::Output
|
5
5
|
|
6
6
|
def initialize(pattern, config)
|
7
|
-
@pattern, @config = pattern, config
|
7
|
+
@pattern, @config = prepare_pattern(pattern), config
|
8
8
|
end
|
9
9
|
|
10
10
|
def match?(process)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"rss #{process.rss}>#{@config.rss_max}"
|
16
|
-
Process.kill @config.signal, process.pid
|
11
|
+
@process = process
|
12
|
+
if @process.command =~ @pattern
|
13
|
+
if @process.rss > @config.rss_max
|
14
|
+
take_action
|
17
15
|
else
|
18
|
-
|
19
|
-
"pattern=#{@pattern.source.inspect} "\
|
20
|
-
"rss #{process.rss}<=#{@config.rss_max}"
|
16
|
+
lay_low
|
21
17
|
end
|
22
|
-
|
18
|
+
true
|
19
|
+
else
|
20
|
+
false
|
23
21
|
end
|
24
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def prepare_pattern(pattern)
|
27
|
+
Regexp.new(pattern.to_s)
|
28
|
+
end
|
29
|
+
|
30
|
+
def take_action
|
31
|
+
output "sending signal #{@config.signal} to process pid=#{@process.pid} "\
|
32
|
+
"pattern=#{@pattern.source.inspect} "\
|
33
|
+
"rss #{@process.rss}>#{@config.rss_max}"
|
34
|
+
Process.kill @config.signal, @process.pid
|
35
|
+
end
|
36
|
+
|
37
|
+
def lay_low
|
38
|
+
output "no action on process pid=#{@process.pid} "\
|
39
|
+
"pattern=#{@pattern.source.inspect} "\
|
40
|
+
"rss #{@process.rss}<=#{@config.rss_max}"
|
41
|
+
end
|
25
42
|
end
|
data/lib/memosig/version.rb
CHANGED
data/memosig.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: memosig 0.0.
|
2
|
+
# stub: memosig 0.0.2 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "memosig"
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.2"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib"]
|
@@ -13,13 +13,13 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.email = "flori@ping.de"
|
14
14
|
s.executables = ["memosig"]
|
15
15
|
s.extra_rdoc_files = ["README.md", "lib/memosig.rb", "lib/memosig/app.rb", "lib/memosig/matcher.rb", "lib/memosig/output.rb", "lib/memosig/proc_stat.rb", "lib/memosig/version.rb"]
|
16
|
-
s.files = [".gitignore", "COPYING", "Gemfile", "README.md", "Rakefile", "VERSION", "bin/memosig", "lib/memosig.rb", "lib/memosig/app.rb", "lib/memosig/matcher.rb", "lib/memosig/output.rb", "lib/memosig/proc_stat.rb", "lib/memosig/version.rb", "memosig.gemspec", "spec/assets/memosig.yml", "spec/memosig/app_spec.rb", "spec/memosig/proc_stat_spec.rb", "spec/spec_helper.rb"]
|
16
|
+
s.files = [".gitignore", ".rspec", "COPYING", "Gemfile", "README.md", "Rakefile", "VERSION", "bin/memosig", "lib/memosig.rb", "lib/memosig/app.rb", "lib/memosig/matcher.rb", "lib/memosig/output.rb", "lib/memosig/proc_stat.rb", "lib/memosig/version.rb", "memosig.gemspec", "spec/assets/memosig.yml", "spec/memosig/app_spec.rb", "spec/memosig/matcher_spec.rb", "spec/memosig/output_spec.rb", "spec/memosig/proc_stat_spec.rb", "spec/spec_helper.rb"]
|
17
17
|
s.homepage = "http://flori.github.com/memosig"
|
18
18
|
s.licenses = ["Apache-2.0"]
|
19
19
|
s.rdoc_options = ["--title", "Memosig", "--main", "README.md"]
|
20
20
|
s.rubygems_version = "2.4.5"
|
21
21
|
s.summary = "Executable that supervises memory use of processes and signals them"
|
22
|
-
s.test_files = ["spec/memosig/app_spec.rb", "spec/memosig/proc_stat_spec.rb", "spec/spec_helper.rb"]
|
22
|
+
s.test_files = ["spec/memosig/app_spec.rb", "spec/memosig/matcher_spec.rb", "spec/memosig/output_spec.rb", "spec/memosig/proc_stat_spec.rb", "spec/spec_helper.rb"]
|
23
23
|
|
24
24
|
if s.respond_to? :specification_version then
|
25
25
|
s.specification_version = 4
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.add_development_dependency(%q<rake>, [">= 0"])
|
30
30
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
31
31
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
32
|
+
s.add_development_dependency(%q<byebug>, [">= 0"])
|
32
33
|
s.add_runtime_dependency(%q<tins>, ["~> 1.0"])
|
33
34
|
s.add_runtime_dependency(%q<complex_config>, [">= 0"])
|
34
35
|
else
|
@@ -36,6 +37,7 @@ Gem::Specification.new do |s|
|
|
36
37
|
s.add_dependency(%q<rake>, [">= 0"])
|
37
38
|
s.add_dependency(%q<rspec>, [">= 0"])
|
38
39
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
40
|
+
s.add_dependency(%q<byebug>, [">= 0"])
|
39
41
|
s.add_dependency(%q<tins>, ["~> 1.0"])
|
40
42
|
s.add_dependency(%q<complex_config>, [">= 0"])
|
41
43
|
end
|
@@ -44,6 +46,7 @@ Gem::Specification.new do |s|
|
|
44
46
|
s.add_dependency(%q<rake>, [">= 0"])
|
45
47
|
s.add_dependency(%q<rspec>, [">= 0"])
|
46
48
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
49
|
+
s.add_dependency(%q<byebug>, [">= 0"])
|
47
50
|
s.add_dependency(%q<tins>, ["~> 1.0"])
|
48
51
|
s.add_dependency(%q<complex_config>, [">= 0"])
|
49
52
|
end
|
data/spec/memosig/app_spec.rb
CHANGED
@@ -9,13 +9,85 @@ RSpec.describe Memosig::App do
|
|
9
9
|
Memosig::App.new(config: config)
|
10
10
|
end
|
11
11
|
|
12
|
+
let :current_processes do
|
13
|
+
[ Memosig::ProcStat.new($$, 666, 'unicorn worker') ]
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(app).to receive(:sleep)
|
18
|
+
allow(app).to receive(:current_processes).and_return(current_processes)
|
19
|
+
end
|
20
|
+
|
12
21
|
it 'loads config' do
|
13
22
|
expect(app.config).to be_a ComplexConfig::Settings
|
14
23
|
end
|
15
24
|
|
16
|
-
it '
|
17
|
-
expect(
|
18
|
-
|
19
|
-
|
25
|
+
it 'can gather process information' do
|
26
|
+
expect(
|
27
|
+
Memosig::App.new(config: config).instance_eval { current_processes }
|
28
|
+
).not_to be_empty
|
29
|
+
end
|
30
|
+
|
31
|
+
context '#run' do
|
32
|
+
it 'checks the memory and sleeps' do
|
33
|
+
expect(app).to receive(:check_memory)
|
34
|
+
expect(app).to receive(:sleep)
|
35
|
+
app.run
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context '#check_memory' do
|
40
|
+
it 'fetches all current processes' do
|
41
|
+
allow(app).to receive(:check_memory_for)
|
42
|
+
expect(app).to receive(:check_memory_for).with(
|
43
|
+
:'unicorn worker',
|
44
|
+
app.config.processes[:'unicorn worker'],
|
45
|
+
current_processes
|
46
|
+
)
|
47
|
+
expect(app).to receive(:output).with /checking memory limits/
|
48
|
+
app.instance_eval { check_memory }
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'calls check_memory_for for each pattern and config' do
|
52
|
+
allow(app).to receive(:output)
|
53
|
+
expect(app).to receive(:check_memory_for).with(
|
54
|
+
:'unicorn worker',
|
55
|
+
app.config.processes[:'unicorn worker'],
|
56
|
+
current_processes
|
57
|
+
)
|
58
|
+
expect(app).to receive(:check_memory_for).with(
|
59
|
+
:'\Asidekiq ',
|
60
|
+
app.config.processes[:'\Asidekiq '],
|
61
|
+
current_processes
|
62
|
+
)
|
63
|
+
app.instance_eval { check_memory }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context '#check_memory_for' do
|
68
|
+
after do
|
69
|
+
app.instance_eval do
|
70
|
+
check_memory_for(
|
71
|
+
:'unicorn worker',
|
72
|
+
config.processes[:'unicorn worker'],
|
73
|
+
current_processes
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'can match' do
|
79
|
+
expect_any_instance_of(Memosig::Matcher).to receive(:match?).with(
|
80
|
+
current_processes.first
|
81
|
+
).and_return true
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'cannot match' do
|
85
|
+
expect_any_instance_of(Memosig::Matcher).to receive(:match?).with(
|
86
|
+
current_processes.first
|
87
|
+
).and_return false
|
88
|
+
expect(app).to receive(:error).with(
|
89
|
+
/pattern "unicorn worker" didn't match any processes/
|
90
|
+
)
|
91
|
+
end
|
20
92
|
end
|
21
93
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
RSpec.describe Memosig::Matcher do
|
5
|
+
let :config do
|
6
|
+
ComplexConfig::Settings[
|
7
|
+
rss_max: 666,
|
8
|
+
signal: 14,
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
let :matcher do
|
13
|
+
Memosig::Matcher.new('command\z', config)
|
14
|
+
end
|
15
|
+
|
16
|
+
context '#match?' do
|
17
|
+
it 'does nothing if command does not match pattern' do
|
18
|
+
process = Memosig::ProcStat.new($$, 4242, 'not what we are looking for')
|
19
|
+
expect(matcher).not_to receive(:take_action)
|
20
|
+
expect(matcher).not_to receive(:lay_low)
|
21
|
+
expect(matcher).not_to be_match process
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'takes action if rss > configured rss_max' do
|
25
|
+
process = Memosig::ProcStat.new($$, 4242, 'our cool command')
|
26
|
+
expect(matcher).to receive(:take_action)
|
27
|
+
expect(matcher).not_to receive(:lay_low)
|
28
|
+
expect(matcher).to be_match process
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'lays low if rss <= configured rss_max' do
|
32
|
+
process = Memosig::ProcStat.new($$, 23, 'our cool command')
|
33
|
+
expect(matcher).not_to receive(:take_action)
|
34
|
+
expect(matcher).to receive(:lay_low)
|
35
|
+
expect(matcher).to be_match process
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context '#take_action' do
|
40
|
+
it 'signals process if take action is called' do
|
41
|
+
process = Memosig::ProcStat.new($$, 4242, 'our cool command')
|
42
|
+
expect(matcher).to receive(:take_action).and_call_original
|
43
|
+
expect(matcher).to receive(:output).with /sending signal 14 to process/
|
44
|
+
alrm = false
|
45
|
+
trap(:ALRM) { alrm = true }
|
46
|
+
expect(matcher).to be_match process
|
47
|
+
Timeout.timeout(1) { sleep 0.1 until alrm } rescue Timeout::Error
|
48
|
+
expect(alrm).to eq true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context '#lay_low' do
|
53
|
+
it 'outputs a message if laying low' do
|
54
|
+
process = Memosig::ProcStat.new($$, 23, 'our cool command')
|
55
|
+
expect(matcher).to receive(:lay_low).and_call_original
|
56
|
+
expect(matcher).to receive(:output).with /no action on process/
|
57
|
+
expect(matcher).to be_match process
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Memosig::Output do
|
4
|
+
let :object do
|
5
|
+
Object.new.tap do |o|
|
6
|
+
o.extend(Memosig::Output)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can generate the process_prefix' do
|
11
|
+
expect(object.process_prefix).to match /\w+ pid=\d+/
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can output messages with prefix' do
|
15
|
+
expect(STDOUT).to receive(:puts).with /\w+ pid=\d+.*foo/
|
16
|
+
object.output 'foo'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'can output error messages with prefix' do
|
20
|
+
expect(STDERR).to receive(:puts).with /\w+ pid=\d+.*foo/
|
21
|
+
object.error 'foo'
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memosig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: tins
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,6 +124,7 @@ extra_rdoc_files:
|
|
110
124
|
- lib/memosig/version.rb
|
111
125
|
files:
|
112
126
|
- ".gitignore"
|
127
|
+
- ".rspec"
|
113
128
|
- COPYING
|
114
129
|
- Gemfile
|
115
130
|
- README.md
|
@@ -125,6 +140,8 @@ files:
|
|
125
140
|
- memosig.gemspec
|
126
141
|
- spec/assets/memosig.yml
|
127
142
|
- spec/memosig/app_spec.rb
|
143
|
+
- spec/memosig/matcher_spec.rb
|
144
|
+
- spec/memosig/output_spec.rb
|
128
145
|
- spec/memosig/proc_stat_spec.rb
|
129
146
|
- spec/spec_helper.rb
|
130
147
|
homepage: http://flori.github.com/memosig
|
@@ -157,5 +174,7 @@ specification_version: 4
|
|
157
174
|
summary: Executable that supervises memory use of processes and signals them
|
158
175
|
test_files:
|
159
176
|
- spec/memosig/app_spec.rb
|
177
|
+
- spec/memosig/matcher_spec.rb
|
178
|
+
- spec/memosig/output_spec.rb
|
160
179
|
- spec/memosig/proc_stat_spec.rb
|
161
180
|
- spec/spec_helper.rb
|