snoopit 0.0.1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +39 -0
  4. data/.idea/.name +1 -0
  5. data/.idea/.rakeTasks +7 -0
  6. data/.idea/dictionaries/rbirch.xml +9 -0
  7. data/.idea/encodings.xml +5 -0
  8. data/.idea/misc.xml +5 -0
  9. data/.idea/modules.xml +9 -0
  10. data/.idea/scopes/scope_settings.xml +5 -0
  11. data/.idea/snoopit.iml +233 -0
  12. data/.idea/vcs.xml +7 -0
  13. data/.rspec +2 -0
  14. data/.travis.yml +7 -0
  15. data/Gemfile +15 -0
  16. data/LICENSE.txt +22 -0
  17. data/README.md +411 -0
  18. data/Rakefile +1 -0
  19. data/bin/snoopit +173 -0
  20. data/lib/snoopit.rb +22 -0
  21. data/lib/snoopit/detected.rb +50 -0
  22. data/lib/snoopit/file_info.rb +104 -0
  23. data/lib/snoopit/file_tracker.rb +83 -0
  24. data/lib/snoopit/logger.rb +30 -0
  25. data/lib/snoopit/notification_manager.rb +123 -0
  26. data/lib/snoopit/notifier.rb +25 -0
  27. data/lib/snoopit/notifiers/email.rb +61 -0
  28. data/lib/snoopit/notifiers/http.rb +85 -0
  29. data/lib/snoopit/notifiers/https.rb +21 -0
  30. data/lib/snoopit/notifiers/stomp.rb +59 -0
  31. data/lib/snoopit/register.rb +69 -0
  32. data/lib/snoopit/sniffer.rb +51 -0
  33. data/lib/snoopit/snooper.rb +149 -0
  34. data/lib/snoopit/snoopy.rb +67 -0
  35. data/lib/snoopit/version.rb +3 -0
  36. data/snoopit.gemspec +27 -0
  37. data/spec/bin/snoopit_spec.rb +258 -0
  38. data/spec/file_info_spec.rb +131 -0
  39. data/spec/file_tracker_spec.rb +172 -0
  40. data/spec/notification_manager_spec.rb +103 -0
  41. data/spec/notifiers/email_spec.rb +36 -0
  42. data/spec/notifiers/http_spec.rb +37 -0
  43. data/spec/notifiers/https_spec.rb +38 -0
  44. data/spec/notifiers/stomp_spec.rb +34 -0
  45. data/spec/register_spec.rb +105 -0
  46. data/spec/snooper_spec.rb +538 -0
  47. data/spec/spec_helper.rb +24 -0
  48. data/spec/support/log/snoop_log.test +593 -0
  49. data/spec/support/log/snoop_log_2.test +593 -0
  50. data/spec/support/multiple_snoopies.json +82 -0
  51. data/spec/support/regexp_tester.rb +10 -0
  52. data/spec/support/snoopies.json +93 -0
  53. data/spec/support/snoopies_notifiers.json +66 -0
  54. data/spec/support/test_notifier.rb +18 -0
  55. data/spec/support/test_notifier_load.rb +18 -0
  56. data/support/snoopies.json +110 -0
  57. metadata +190 -0
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'logger'
4
+ require 'snoopit'
5
+
6
+ options = {}
7
+ options[:snoopies_file]='snoopies.json'
8
+ options[:snoopies] = []
9
+ options[:verbose] = false
10
+ options[:line_numbers] = false
11
+ options[:new_line] = true
12
+ options[:json] = false
13
+ options[:pretty_json] = false
14
+ options[:notifications] = false
15
+ options[:tracking] = false
16
+ options[:tracking_file] = './snoopit_db.json'
17
+
18
+ OptionParser.new do |opts|
19
+
20
+ opts.banner = 'Usage: snoopit [options]'
21
+
22
+ opts.on('-s', '--snoopers snoopies.json', 'File contains one or more regular expressions to locate a line of interest in a file' ) do |snoopies_file|
23
+ options[:snoopies_file] = snoopies_file
24
+ end
25
+
26
+ opts.on('-S', '--snooper snooper_name', 'Only use the named snooper. This option can be used more than once to use several snoopers.' ) do |snooper|
27
+ options[:snoopies] << snooper
28
+ end
29
+
30
+ opts.on('-t', '--template', 'Generate a template snoopies.json file to stdout' ) do
31
+ template = File.expand_path '../../support/snoopies.json', __FILE__
32
+ File.readlines(template).each do |line|
33
+ puts line
34
+ end
35
+ exit
36
+ end
37
+
38
+ opts.on('-T', '--tracking', 'Enable log file tracking using file ./snoopit_db.json') do
39
+ options[:tracking] = true
40
+ end
41
+
42
+ opts.on('-f', '--tracking-file file_name', 'Specify a different tracking file name and location instead of the default ./snoopit_db.json') do |tracking_file|
43
+ options[:tracking] = true
44
+ options[:tracking_file] = tracking_file
45
+ end
46
+
47
+ opts.on('-j', '--json', 'Generate output in json' ) do
48
+ options[:json] = true
49
+ end
50
+
51
+ opts.on('-J', '--pretty-json', 'Generate output in pretty json' ) do
52
+ options[:json] = true
53
+ options[:pretty_json] = true
54
+ end
55
+
56
+ opts.on('-N', '--no-newline', 'Do not output new line between found items' ) do |l|
57
+ options[:new_line] = false
58
+ end
59
+
60
+ opts.on('-n', '--enable-notifications', 'Enable notifications' ) do |n|
61
+ options[:notifications] = true
62
+ end
63
+
64
+ opts.on('-l', '--line-numbers', 'show line numbers' ) do |l|
65
+ options[:line_numbers] = true
66
+ end
67
+
68
+ opts.on_tail('-v', '--verbose', 'prints out file name, matched line number') do
69
+ options[:verbose] = true
70
+ end
71
+
72
+ opts.on_tail('-h', '--help') do
73
+ puts opts
74
+ exit
75
+ end
76
+
77
+ end.parse!
78
+
79
+ def verbose(snoopy_name, sniffed)
80
+ puts ''
81
+ puts "File: #{sniffed.file}"
82
+ puts "Snooper: #{snoopy_name}"
83
+ puts "Match at line number: #{sniffed.line_no}"
84
+ puts "** Sniffed Out ** #{sniffed.match}"
85
+ puts ''
86
+ end
87
+
88
+ def get_start_line_number(sniffed)
89
+ start = sniffed.line_no - sniffed.after.size
90
+ start = 1 if start <= 0
91
+ start
92
+ end
93
+
94
+ def line_before(line_no, sniffed)
95
+ sniffed.before.register.each do |b|
96
+ unless b.nil?
97
+ puts "#{line_no}: #{b}"
98
+ line_no += 1
99
+ end
100
+ end
101
+ line_no
102
+ end
103
+
104
+ def line_after(line_no, sniffed)
105
+ sniffed.after.register.each do |a|
106
+ unless a.nil?
107
+ puts "#{line_no}: #{a}"
108
+ line_no += 1
109
+ end
110
+ end
111
+ line_no
112
+ end
113
+
114
+ def line_numbers(sniffed)
115
+ line_no = get_start_line_number sniffed
116
+ line_no = line_before line_no, sniffed
117
+ puts "#{line_no}: #{sniffed.match}"
118
+ line_no += 1
119
+ line_after line_no, sniffed
120
+ end
121
+
122
+ def no_line_numbers(sniffed)
123
+ sniffed.before.register.each {|b| puts b unless b.nil? }
124
+ puts sniffed.match
125
+ sniffed.after.register.each {|a| puts a unless a.nil? }
126
+ end
127
+
128
+ def dump_lines(snoopies, newline, line_no, is_verbose)
129
+ snoopies.each do |snoopie|
130
+ snoopie.sniffers.each do |sniffer|
131
+ sniffer.sniffed.each do |sniffed|
132
+ verbose snoopie.name, sniffed if is_verbose
133
+ line_no ? line_numbers(sniffed) : no_line_numbers(sniffed)
134
+ puts '' if newline
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ def dump_json(snoopies, pretty=false)
141
+ if pretty
142
+ puts JSON.pretty_generate snoopies
143
+ else
144
+ puts snoopies.to_json
145
+ end
146
+ end
147
+
148
+ if options[:tracking]
149
+ puts "File tracking database: #{options[:tracking_file]}"
150
+ else
151
+ options[:tracking_file] = nil
152
+ end
153
+
154
+ unless File.exist? options[:snoopies_file]
155
+ puts "Snooper json file does not exist: #{options[:snoopies_file]}"
156
+ exit 1
157
+ end
158
+
159
+ #debug_file = File.open(File.expand_path('../../tmp/debug.log', __FILE__), 'w+')
160
+ #snooper = Snoopit::Snooper.new options[:notifications], options[:tracking_file], debug_file, ::Logger::DEBUG
161
+ #snooper = Snoopit::Snooper.new options[:notifications], options[:tracking_file], STDOUT, ::Logger::DEBUG
162
+ snooper = Snoopit::Snooper.new options[:notifications], options[:tracking_file]
163
+ snooper.load_file options[:snoopies_file]
164
+ snoopies = snooper.snoop options[:snoopies]
165
+ if options[:json]
166
+ dump_json snoopies, options[:pretty_json]
167
+ else
168
+ dump_lines snoopies, options[:new_line], options[:line_numbers], options[:verbose]
169
+ end
170
+
171
+
172
+
173
+
@@ -0,0 +1,22 @@
1
+ require 'snoopit/version'
2
+ require 'snoopit/logger'
3
+ require 'snoopit/register'
4
+ require 'snoopit/snooper'
5
+ require 'snoopit/snoopy'
6
+ require 'snoopit/sniffer'
7
+ require 'snoopit/detected'
8
+ require 'snoopit/file_info'
9
+ require 'snoopit/file_tracker'
10
+ require 'snoopit/notification_manager'
11
+ require 'snoopit/notifier'
12
+ require 'snoopit/notifiers/email'
13
+ require 'snoopit/notifiers/http'
14
+ require 'snoopit/notifiers/https'
15
+
16
+ module Snoopit
17
+
18
+ def self.logger
19
+ Snoopit::Logging.logger
20
+ end
21
+
22
+ end
@@ -0,0 +1,50 @@
1
+ module Snoopit
2
+ class Detected
3
+
4
+ attr :comment, :before, :after, :after_count, :regexp, :match, :finished, :file, :line_no
5
+
6
+ def initialize(comment, pre_before, after, match, file, line_no)
7
+ setup_before pre_before
8
+ @comment = comment
9
+ @after_count = 0
10
+ @after = Register.new(after)
11
+ @match = match
12
+ @file = file
13
+ @line_no = line_no
14
+ @finished = false
15
+ end
16
+
17
+ def setup_before(pre_before)
18
+ @before = Register.new pre_before.size, pre_before.register
19
+ end
20
+
21
+ def track(line)
22
+ return if line == @match
23
+ if @after_count < @after.size
24
+ @after.push_front line
25
+ @after_count += 1
26
+ else
27
+ @finished = true
28
+ end
29
+ end
30
+
31
+ def finished?
32
+ @finished
33
+ end
34
+
35
+ def as_json(options=nil)
36
+ {
37
+ after: @after,
38
+ match: @match,
39
+ before: @before,
40
+ file: @file,
41
+ line_no: @line_no
42
+ }
43
+ end
44
+
45
+ def to_json(*a)
46
+ as_json.to_json(*a)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,104 @@
1
+ require 'time'
2
+
3
+ module Snoopit
4
+ class FileInfo
5
+
6
+ attr_accessor :file, :line_no, :offset, :size, :mtime, :last_line, :init_stat
7
+
8
+ def initialize(file=nil)
9
+ @file = file
10
+ @line_no = 0
11
+ @offset = 0
12
+ @size = 0
13
+ @mtime = nil
14
+ @last_line = nil
15
+ @init_stat = true
16
+ end
17
+
18
+ # Update file Info if the file has changed use the file handle to move the file pointer
19
+ # to the character where reading will start
20
+ #
21
+ # @return [boolean] true if updated false not updated
22
+ def updated?(file_handle)
23
+ c_stat = File.stat @file
24
+ if (c_stat.size == @size) && (c_stat.mtime.to_i == @mtime.to_i) && (! @init_stat)
25
+ Snoopit.logger.debug 'FileTracker.updated? file has not changed: ' + @file
26
+ updated = false
27
+ elsif c_stat.size < @size
28
+ Snoopit.logger.debug 'FileTracker.updated? file size is smaller it is a new new file: ' + @file
29
+ updated = new_file? file_handle, c_stat
30
+ elsif (c_stat.size == @size) && (! @mtime.nil?) && (c_stat.mtime.to_i > @mtime.to_i)
31
+ Snoopit.logger.debug 'FileTracker.updated? file size is same but file time is newer it is a new file: ' + @file
32
+ updated = new_file? file_handle, c_stat
33
+ else
34
+ Snoopit.logger.debug 'FileTracker.updated? reading from last read location: ' + @file
35
+ updated = read_from_last? file_handle, c_stat
36
+ end
37
+ @init_stat = false
38
+ updated
39
+ end
40
+
41
+ def new_file?(file_handle, stat)
42
+ # seek to 0
43
+ Snoopit.logger.debug 'FileTracker.updated? file new read from start of file: ' + @file
44
+ @offset = 0
45
+ @size = stat.size
46
+ @mtime = stat.mtime
47
+ @last_line = nil
48
+ file_handle.seek 0, IO::SEEK_SET
49
+ true
50
+ end
51
+
52
+ def read_from_last?(file_handle, stat)
53
+ # seek to last position + 1
54
+ old_size = @size
55
+ @size = stat.size
56
+ @mtime = stat.mtime
57
+ Snoopit.logger.debug "File pointer at byte: #{file_handle.tell}"
58
+ file_handle.seek old_size, IO::SEEK_SET
59
+ Snoopit.logger.debug "Starting read from byte: #{file_handle.tell} destination byte #{old_size} new size #{@size}"
60
+ true
61
+ end
62
+
63
+ def get_last_line(file_handle)
64
+ line = nil
65
+ unless @last_line.nil?
66
+ Snoopit.logger.debug "File point at byte: #{file_handle.tell}"
67
+ file_handle.seek (-@last_line.bytesize), IO::SEEK_END
68
+ Snoopit.logger.debug "Seeked to byte: #{file_handle.tell}"
69
+ line = file_handle.readline
70
+ end
71
+ line
72
+ end
73
+
74
+ def as_json(*)
75
+ {
76
+ file: @file,
77
+ line_no: @line_no,
78
+ offset: @offset,
79
+ size: @size,
80
+ mtime: @mtime.iso8601,
81
+ last_line: @last_line
82
+ }
83
+ end
84
+
85
+ def to_json(*args)
86
+ as_json.to_json(*args)
87
+ end
88
+
89
+ def from_json(json_str)
90
+ from_hash JSON.parse(json_str)
91
+ end
92
+
93
+ def from_hash(hash)
94
+ @file = hash['file']
95
+ @line_no = hash['line_no']
96
+ @offset = hash['offset']
97
+ @size = hash['size']
98
+ @mtime = Time.parse hash['mtime']
99
+ @last_line = hash['last_line']
100
+ @init_stat = false
101
+ end
102
+
103
+ end
104
+ end
@@ -0,0 +1,83 @@
1
+ module Snoopit
2
+ class FileTracker
3
+
4
+ attr_accessor :files, :db_file
5
+
6
+ def initialize(db_file='./snooper_db.json', remove=false)
7
+ @files = { }
8
+ @db_file = db_file
9
+ if remove
10
+ remove_db @db_file
11
+ else
12
+ load_db @db_file
13
+ end
14
+ end
15
+
16
+ def foreach(file, &block)
17
+ file_info = get_file(file)
18
+ unless file_info.nil?
19
+ read_lines(file_info, block)
20
+ save_db @db_file
21
+ end
22
+ end
23
+
24
+ def get_file(file)
25
+ return nil unless File.exist? file
26
+ @files[file] = FileInfo.new(file) if @files[file].nil?
27
+ @files[file]
28
+ end
29
+
30
+ def read_lines(file_info, block)
31
+ begin
32
+ fh = File.new(file_info.file)
33
+ if file_info.updated? fh
34
+ fh.each_line do |line|
35
+ file_info.offset += line.bytesize
36
+ file_info.line_no += 1
37
+ file_info.last_line = line
38
+ block.call line, file_info.line_no
39
+ end
40
+ end
41
+ ensure
42
+ fh.close
43
+ end
44
+ end
45
+
46
+ def load_db(db_file)
47
+ if (! db_file.nil?) && (File.exist? db_file)
48
+ Snoopit.logger.debug 'Loading from db file: ' + db_file
49
+ hash_db = JSON.parse(IO.read db_file)
50
+ hash_db.each do |key, file_info|
51
+ unless file_info.nil?
52
+ fi = FileInfo.new
53
+ fi.from_hash(file_info)
54
+ @files[key] = fi
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def save_db(db_file)
61
+ unless db_file.nil?
62
+ File.open db_file, 'w' do |f|
63
+ f.write @files.to_json
64
+ end
65
+ end
66
+ end
67
+
68
+ def remove_db(db_file)
69
+ if (! db_file.nil?) && (File.exist? db_file)
70
+ File.delete db_file
71
+ end
72
+ end
73
+
74
+ def as_json(*)
75
+ { files: @files }
76
+ end
77
+
78
+ def to_json(*args)
79
+ as_json.to_json(*args)
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ require 'logger'
2
+ require 'awesome_print'
3
+
4
+ module Snoopit
5
+ module Logging
6
+
7
+ LEVEL_MAP = {
8
+ info: ::Logger::INFO,
9
+ warn: ::Logger::WARN,
10
+ error: ::Logger::ERROR,
11
+ fatal: ::Logger::FATAL,
12
+ debug: ::Logger::DEBUG
13
+ }
14
+
15
+ def self.create_logger(out=STDOUT, level=::Logger::INFO)
16
+ @logger = ::Logger.new(out)
17
+ @logger.level = level
18
+ @logger
19
+ end
20
+
21
+ def self.logger
22
+ @logger || create_logger
23
+ end
24
+
25
+ def logger
26
+ Snoopit::Logging.logger
27
+ end
28
+
29
+ end
30
+ end