log-monitor 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +5 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/log_monitor/application.js +13 -0
  6. data/app/assets/stylesheets/log_monitor/application.css +15 -0
  7. data/app/controllers/log_monitor/application_controller.rb +4 -0
  8. data/app/helpers/log_monitor/application_helper.rb +4 -0
  9. data/app/views/layouts/log_monitor/application.html.erb +14 -0
  10. data/bin/log-monitor.rb +51 -0
  11. data/bin/rails.bak +12 -0
  12. data/config/log-monitor.yml +48 -0
  13. data/config/log-monitor.yml.example +46 -0
  14. data/config/routes.rb +2 -0
  15. data/lib/log_monitor.rb +30 -0
  16. data/lib/log_monitor/alerter.rb +169 -0
  17. data/lib/log_monitor/engine.rb +5 -0
  18. data/lib/log_monitor/version.rb +3 -0
  19. data/lib/tasks/log_monitor_tasks.rake +4 -0
  20. data/test/dummy/Gemfile +42 -0
  21. data/test/dummy/Gemfile.lock +127 -0
  22. data/test/dummy/README.rdoc +28 -0
  23. data/test/dummy/Rakefile +6 -0
  24. data/test/dummy/app/assets/javascripts/application.js +16 -0
  25. data/test/dummy/app/assets/javascripts/monitor.js.coffee +3 -0
  26. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  27. data/test/dummy/app/assets/stylesheets/monitor.css.scss +3 -0
  28. data/test/dummy/app/controllers/application_controller.rb +5 -0
  29. data/test/dummy/app/controllers/monitor_controller.rb +11 -0
  30. data/test/dummy/app/helpers/application_helper.rb +2 -0
  31. data/test/dummy/app/helpers/monitor_helper.rb +2 -0
  32. data/test/dummy/app/log_monitor_test.rb +8 -0
  33. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  34. data/test/dummy/bin/bundle +3 -0
  35. data/test/dummy/bin/rails +4 -0
  36. data/test/dummy/bin/rake +4 -0
  37. data/test/dummy/bin/spring +18 -0
  38. data/test/dummy/config.ru +4 -0
  39. data/test/dummy/config/application.rb +26 -0
  40. data/test/dummy/config/boot.rb +4 -0
  41. data/test/dummy/config/database.yml +25 -0
  42. data/test/dummy/config/environment.rb +5 -0
  43. data/test/dummy/config/environments/development.rb +37 -0
  44. data/test/dummy/config/environments/production.rb +78 -0
  45. data/test/dummy/config/environments/test.rb +39 -0
  46. data/test/dummy/config/initializers/assets.rb +8 -0
  47. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  48. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  49. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  50. data/test/dummy/config/initializers/inflections.rb +16 -0
  51. data/test/dummy/config/initializers/log_monitor.rb +8 -0
  52. data/test/dummy/config/initializers/mime_types.rb +4 -0
  53. data/test/dummy/config/initializers/session_store.rb +3 -0
  54. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/test/dummy/config/locales/en.yml +23 -0
  56. data/test/dummy/config/log-monitor.yml +50 -0
  57. data/test/dummy/config/log-monitor.yml.example +49 -0
  58. data/test/dummy/config/routes.rb +5 -0
  59. data/test/dummy/config/secrets.yml +22 -0
  60. data/test/dummy/db/development.sqlite3 +0 -0
  61. data/test/dummy/db/seeds.rb +7 -0
  62. data/test/dummy/lib/log_monitor_runner.rb +13 -0
  63. data/test/dummy/log/development.log +8273 -0
  64. data/test/dummy/log/production.log +0 -0
  65. data/test/dummy/public/404.html +67 -0
  66. data/test/dummy/public/422.html +67 -0
  67. data/test/dummy/public/500.html +66 -0
  68. data/test/dummy/public/favicon.ico +0 -0
  69. data/test/dummy/public/robots.txt +5 -0
  70. data/test/dummy/test/controllers/monitor_controller_test.rb +7 -0
  71. data/test/dummy/test/helpers/monitor_helper_test.rb +4 -0
  72. data/test/dummy/test/test_helper.rb +10 -0
  73. data/test/integration/navigation_test.rb +10 -0
  74. data/test/log_monitor_test.rb +7 -0
  75. data/test/test_helper.rb +17 -0
  76. data/test/test_regexp.rb +7 -0
  77. metadata +204 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b0073f0ec1bd9256ccec677419ee4b7415c15da
4
+ data.tar.gz: 9d01494850a405caa93c0d1329b4b0a65810e7f8
5
+ SHA512:
6
+ metadata.gz: 0fd7738856473c34f86240c7bed942f1d9dffad600f4f66e3cd196cf91a6158e3306eb4c2302eedbf9b60eef19dcb20390d4634479316db662dee32196ca7803
7
+ data.tar.gz: 4952802dff00177c37e2d936826b6d4689c40931d373fae9bb6d78698f7090b2c3ca69311303e45b0fd4150cf341d44eafb431fb48c646a920a912be6449b154
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
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.
@@ -0,0 +1,5 @@
1
+ = LogMonitor
2
+
3
+ Monitoring web server's log. And raise alert with email, webpost, file, or console.
4
+
5
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'LogMonitor'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ module LogMonitor
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module LogMonitor
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>LogMonitor</title>
5
+ <%= stylesheet_link_tag "log_monitor/application", media: "all" %>
6
+ <%= javascript_include_tag "log_monitor/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env ruby
2
+ require 'log_monitor'
3
+
4
+ if ARGV[0] == '-c'
5
+ puts <<EOF
6
+ monitor:
7
+ target: /tmp/log/development.log
8
+ words:
9
+ - Completed 500 Internal Server Error
10
+ - No route matches
11
+ method: file # or console or email or webpost
12
+ file: /tmp/log-monitor.log
13
+ webpost: http://localhost:3000/monitor/post # ignored which not selected as method
14
+ email: # ignored which not selected as method
15
+ to:
16
+ - *@*.com
17
+ from: *@gmail.com
18
+ subject: Alert! *.com Error occured!
19
+ address: smtp.gmail.com
20
+ port: 587
21
+ user_name: *@gmail.com
22
+ password: [password]
23
+ EOF
24
+
25
+ elsif ARGV[0] == '-i'
26
+ puts <<EOF
27
+ require 'log_monitor'
28
+
29
+ Thread.new do
30
+ config_file = Rails.root.join('config', 'log-monitor.yml')
31
+ config = YAML.load_file(config_file)#[Rails.env]
32
+ alerter = LogMonitor::Factory.get(config)
33
+ alerter.monitor
34
+ end
35
+ EOF
36
+
37
+ elsif !ARGV[0].nil? && File.exist?(ARGV[0])
38
+ config = YAML.load_file(ARGV[0])
39
+ Thread.new(config) do | prm_cfg |
40
+ alerter = LogMonitor::Factory.get(prm_cfg)
41
+ alerter.monitor
42
+ end
43
+ sleep
44
+ else
45
+ puts <<EOF
46
+ (none or other) : show help (this message)
47
+ -c : show example of config file. Please use with rediret.
48
+ -i : show example of initializer of RAILS's file. Please use with rediret.
49
+ [config file] : run monitoring log
50
+ EOF
51
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/log_monitor/engine', __FILE__)
6
+
7
+ # Set up gems listed in the Gemfile.
8
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
9
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
10
+
11
+ require 'rails/all'
12
+ require 'rails/engine/commands'
@@ -0,0 +1,48 @@
1
+ production: &base
2
+ monitor:
3
+ target: ~/work/talk-talk-srv/log/development.log
4
+ words: Completed 500 Internal Server Error
5
+ method: email
6
+ email:
7
+ to: jironbach@gmail.com
8
+ from: shimoda@agilebooster.com
9
+ address: smtp.gmail.com
10
+ port: 587
11
+ user_name: shimoda@agilebooster.com
12
+ password: agilebooster
13
+ subject: [Alert! talktalk.mydns.jp 500 error occured!]
14
+
15
+ development:
16
+ monitor:
17
+ target: ~/work/talk-talk-srv/log/development.log
18
+ words:
19
+ - Completed 500 Internal Server Error
20
+ - Completed 404 Not Found
21
+ method:
22
+ - email
23
+ - webhook
24
+ email:
25
+ to:
26
+ - jironbach@gmail.com
27
+ - admin@agilebooster.com
28
+ - shimoda@agilebooster.com
29
+ from: shimoda@agilebooster.com
30
+ address: smtp.gmail.com
31
+ port: 587
32
+ user_name: shimoda@agilebooster.com
33
+ password: agilebooster
34
+ subject: [Alert! talktalk.mydns.jp Error occured!]
35
+ webhook: http://talktalk.mydns.jp/monitor/post/
36
+
37
+ staging:
38
+ <<: *base
39
+
40
+ test:
41
+ monitor:
42
+ target: ~/work/logmonitor/test/dummy/log/development.log
43
+ words:
44
+ - Completed 500 Internal Server Error
45
+ - Completed 404 Not Found
46
+ method: webhook
47
+ webhook: http://localhost:3000/monitor/post
48
+
@@ -0,0 +1,46 @@
1
+ production: &base
2
+ monitor:
3
+ target: /var/log/production.log
4
+ words: Completed 500 Internal Server Error
5
+ method: email
6
+ email:
7
+ to: admin@*.com
8
+ from: monitor@*.com
9
+ address: smtp.gmail.com
10
+ port: 587
11
+ user_name: *@gmail.com
12
+ password: *****
13
+ subject: [Alert! *.com 500 error occured!]
14
+
15
+ development:
16
+ monitor:
17
+ target: /var/log/development.log
18
+ words:
19
+ - Completed 500 Internal Server Error
20
+ - Completed 404 Not Found
21
+ method:
22
+ - email
23
+ - webhook
24
+ email:
25
+ to:
26
+ - admin@*.com
27
+ - develper@*.com
28
+ - tester@*.com
29
+ from: monitor@*.com
30
+ address: smtp.gmail.com
31
+ port: 587
32
+ user_name: *@gmail.com
33
+ password: *****
34
+ subject: [Alert! *.com Error occured!]
35
+ webhook: http://localhost:3000/monitor/post/
36
+
37
+ staging:
38
+ <<: *base
39
+
40
+ test:
41
+ monitor:
42
+ target: ~/log/test.log
43
+ words: Completed 404 Not Found
44
+ method: webhook
45
+ webhook: http://localhost:3000/monitor/post/
46
+
@@ -0,0 +1,2 @@
1
+ LogMonitor::Engine.routes.draw do
2
+ end
@@ -0,0 +1,30 @@
1
+ require "log_monitor/engine" if defined? Rails
2
+ require "log_monitor/alerter"
3
+
4
+ module LogMonitor
5
+ class Factory
6
+ def self.get(config)
7
+ alerter = self.get_alerter(config)
8
+ alerter.set_in(config['monitor']['target'])
9
+ alerter.set_words(config['monitor']['words'])
10
+ alerter
11
+ end
12
+
13
+ def self.get_alerter(config)
14
+ if config['method'] == 'email'
15
+ alerter = LogMonitor::EmailAlerter.new
16
+ alerter.set_email(config['email'])
17
+ elsif config['method'] == 'webpost'
18
+ alerter = LogMonitor::WebPostAlerter.new
19
+ alerter.set_webpost(config['webpost'])
20
+ elsif config['method'] == 'file'
21
+ alerter = LogMonitor::FileAlerter.new
22
+ alerter.set_out(config['file'])
23
+ else
24
+ alerter = LogMonitor::Alerter.new
25
+ end
26
+ alerter
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,169 @@
1
+ module LogMonitor
2
+ class Alerter
3
+ def initialize
4
+ clear_alert
5
+ end
6
+
7
+ def set_in(io_in)
8
+ @io_in = io_in
9
+ FileUtils.touch(io_in) unless File.exists?(io_in)
10
+ @in = File.open(io_in, 'r')
11
+ end
12
+
13
+ def set_words(words)
14
+ @words = words
15
+ end
16
+
17
+ def monitor
18
+ @in.seek(0, IO::SEEK_END)
19
+ begin
20
+ revival_monitor
21
+ ensure
22
+ @in.close
23
+ end
24
+ end
25
+
26
+ def check_words
27
+ is_alert = false
28
+ @words.each do | word |
29
+ if @alert_body.match(/#{word}/)
30
+ is_alert = true
31
+ break
32
+ end
33
+ end
34
+ if is_alert
35
+ alert
36
+ end
37
+ clear_alert
38
+ end
39
+
40
+ def clear_alert
41
+ @alert_body = ''
42
+ @blank_line_count = 0
43
+ end
44
+
45
+ def alert
46
+ begin
47
+ $stdout.puts @alert_body
48
+ rescue => e
49
+ $stderr.puts "LogMonitor error"
50
+ $stderr.puts e.message
51
+ 2.times $stderr.puts
52
+ end
53
+ clear_alert
54
+ end
55
+
56
+ protected
57
+
58
+ def revival_monitor
59
+ return if @in.nil?
60
+ while true
61
+ sleep(1) if @in.eof
62
+ line = @in.gets
63
+ @alert_body += "#{line}"
64
+ if line.blank?
65
+ @blank_line_count += 1
66
+ else
67
+ @blank_line_count = 0
68
+ end
69
+ check_words if @blank_line_count >= 2
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+
76
+ class FileAlerter < Alerter
77
+ def set_out(filename)
78
+ @filename = filename
79
+ end
80
+
81
+ def alert
82
+ begin
83
+ File.open(@filename, 'a') do | io_out |
84
+ io_out.puts @alert_body
85
+ end
86
+ rescue => e
87
+ $stderr.puts "LogMonitor error"
88
+ $stderr.puts e.message
89
+ 2.times $stderr.puts
90
+ end
91
+ clear_alert
92
+ end
93
+
94
+ end
95
+
96
+
97
+ require 'mail'
98
+ class EmailAlerter < Alerter
99
+ def set_email(config)
100
+ @config = config
101
+ @smtp_settings = {
102
+ address: config['address'],
103
+ port: config['port'],
104
+ user_name: config['user_name'],
105
+ password: config['password'],
106
+ domain: config['domain'],
107
+ authentication: config['authentication'].nil? ? :plain : config['authentication'],
108
+ enable_starttls_auto: true
109
+ }
110
+ end
111
+
112
+ def alert
113
+ begin
114
+ mail = Mail.new
115
+ mail[:from] = @config['from']
116
+ mail[:to] = @config['to']
117
+ mail.subject = @config['subject']
118
+ smtpserver = Net::SMTP.new(@smtp_settings[:address], @smtp_settings[:port])
119
+ smtpserver.enable_tls(OpenSSL::SSL::VERIFY_NONE)
120
+ smtpserver.start(@smtp_settings[:domain], @smtp_settings[:user_name], @smtp_settings[:password], :login) do |smtp|
121
+ mail.body = @alert_body
122
+ smtp.send_message(mail.encoded, mail.from, mail.to)
123
+ end
124
+ rescue => e
125
+ $stderr.puts "LogMonitor error"
126
+ $stderr.puts e.message
127
+ 2.times $stderr.puts
128
+ end
129
+ clear_alert
130
+ end
131
+
132
+ end
133
+
134
+
135
+ class WebPostAlerter < Alerter
136
+ def set_webpost(config)
137
+ @url = config
138
+ end
139
+
140
+ def alert
141
+ begin
142
+ Net::HTTP.post_form(URI.parse(@url), { checker: 'logmonitor-webpost-log', body: "#{ @alert_body }"})
143
+ rescue => e
144
+ $stderr.puts "LogMonitor error"
145
+ $stderr.puts e.message
146
+ 2.times $stderr.puts
147
+ end
148
+ clear_alert
149
+ end
150
+
151
+ def check_words
152
+ is_alert = false
153
+ @words.each do | word |
154
+ if @alert_body.match(/#{word}/) && !@alert_body.include?('logmonitor-webpost-log')
155
+ is_alert = true
156
+ break
157
+ end
158
+ end
159
+ if is_alert
160
+ alert
161
+ end
162
+ clear_alert
163
+ end
164
+
165
+ end
166
+
167
+
168
+ end
169
+