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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bc87039a61f8c2c0bb212eaf57f1b5a5927f1ea
4
- data.tar.gz: 5fd57c20fcd76c16dcfbc8802cd5fcd4885996b9
3
+ metadata.gz: c880791fc4181394f342e11786014bf822463364
4
+ data.tar.gz: b62e09190fcc3e8dd8b17b09d9d64199b2efda5d
5
5
  SHA512:
6
- metadata.gz: ae5dca2ffff020a990897f50950caee7fb004bc38e8a3610704232c4f2890206b5193c918b662413421ad26e6db459b2b6bcda6d41dacdc6bfb880309310d8cb
7
- data.tar.gz: 37929e6cc0778ee32d0dc2d82f3ee4acea5d67c93f72357127fbdbbbb277ef2ed7c3153e286701af2431469ff342bdb0df559ed46c8070d8b3104d16ebf9ea38
6
+ metadata.gz: 4d6dbcea19b281cbc93d074a2c5e9c493e207af94adbf2e704e5e1c447ac2155eef302c1bf62edc72b9657af21d740d241ae9b12315a33ab3d4a3cc4f03ea850
7
+ data.tar.gz: de76ecef394151e6be0ac1c2f7a8b3920a6f7e76e412b075d9fd77926d7f778ba4250ac5752ed549959938ee47d0e9d4ae5a7b11321b4e7547209d9ba486ee78
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Rakefile CHANGED
@@ -25,6 +25,7 @@ GemHadar do
25
25
  development_dependency 'rake'
26
26
  development_dependency 'rspec'
27
27
  development_dependency 'simplecov'
28
+ development_dependency 'byebug'
28
29
  end
29
30
 
30
31
  task :default => :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
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.source.inspect} didn't match any processes"
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 = Memosig::ProcStat.all
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
@@ -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
- if process.command =~ @pattern
12
- if process.rss > @config.rss_max
13
- output "restarting process pid=#{process.pid} "\
14
- "pattern=#{@pattern.source.inspect} "\
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
- output "no action on process pid=#{process.pid} "\
19
- "pattern=#{@pattern.source.inspect} "\
20
- "rss #{process.rss}<=#{@config.rss_max}"
16
+ lay_low
21
17
  end
22
- matched = true
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
@@ -1,6 +1,6 @@
1
1
  module Memosig
2
2
  # Memosig version
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.2'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/memosig.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: memosig 0.0.1 ruby lib
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.1"
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
@@ -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 'checks the memory and sleeps if run' do
17
- expect(app).to receive(:check_memory)
18
- expect(app).to receive(:sleep)
19
- app.run
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
@@ -6,6 +6,10 @@ if ENV['START_SIMPLECOV'].to_i == 1
6
6
  end
7
7
 
8
8
  require 'rspec'
9
+ begin
10
+ require 'byebug'
11
+ rescue LoadError
12
+ end
9
13
  require 'memosig'
10
14
 
11
15
  def config_dir
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.1
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