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 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