memosig 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|