fileminer 1.1.1 → 1.2.0

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
  SHA256:
3
- metadata.gz: 40b0403c4675a8340fee70e155fd7e39ccc902144ca4ab1af03a08db4b8ef8d9
4
- data.tar.gz: f344c468064be5e3a594befbb62a43e5937f4351029fa88a7fef3a0d6310ce87
3
+ metadata.gz: 93670c0973d05575fdab215da684c633c9367f2288168cecab359b0464c539de
4
+ data.tar.gz: 55eaa5c573e308585da35ec30423988c049ef25669ea161a069a5c3392d75ee5
5
5
  SHA512:
6
- metadata.gz: 9f72907fd4e74d2bbbd93130fd1762101c1aa757a44923067b47eb62a515d7e3a18e4452cd2eb4ad73cb66f36d06ca2b3bc6bb4fe0a04c6131ba2b29256d40fc
7
- data.tar.gz: '022318a184a41042136a96d2691890ca3d78f4a3d12b2e9ea2ffe2774430d98861460e9e3a0fb0ae2a3e6f820791af24e39e7c7bc1bac2a53406fa5e74d82aed'
6
+ metadata.gz: 3786c83518c206f3a1bec0ed6b13ce46f3c1604655be8a2d48afa66e8bf202d40fb3bbda5c4c3521e5bbd7265ce7773fa114f03520f162876f6a19ce7ca0c474
7
+ data.tar.gz: 729cba5d996c05301a8ed4870180f89f74511b0709d96c666df43ba7755d17c4a56d5531f19d98e5180029ff8283268671a4ed258582dc8ef0d437d34d22272a
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # fileminer
2
- [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&type=6&v=1.1.0&x2=0)](https://rubygems.org/gems/fileminer)
2
+ [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&type=6&v=1.2.0&x2=0)](https://rubygems.org/gems/fileminer)
3
3
  [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/fmjsjx/fileminer/blob/master/LICENSE)
4
4
 
5
5
 
@@ -11,10 +11,10 @@ A simple line based file/log transfer tool coding by ruby.
11
11
  Install fileminer from RubyGems:
12
12
  ```
13
13
  $ gem install fileminer
14
- Fetching fileminer-1.1.0.gem
15
- Successfully installed fileminer-1.1.0
16
- Parsing documentation for fileminer-1.1.0
17
- Installing ri documentation for fileminer-1.1.0
14
+ Fetching fileminer-1.2.0.gem
15
+ Successfully installed fileminer-1.2.0
16
+ Parsing documentation for fileminer-1.2.0
17
+ Installing ri documentation for fileminer-1.2.0
18
18
  Done installing documentation for fileminer after 0 seconds
19
19
  1 gem installed
20
20
  $ _
@@ -32,7 +32,13 @@ At first, we should generate the fileminer configuration file.
32
32
  We provide a command tool 'fileminer-genconf' to generate configurations:
33
33
  ```
34
34
  $ fileminer-genconf -h
35
- Usage: fileminer-genconf [options]
35
+ Usage:
36
+ fileminer-genconf [options]
37
+
38
+ Samples:
39
+ fileminer-genconf -t fileminer -o Generate config on /etc/fileminer/fileminer.yml
40
+ fileminer-genconf -t supervisor -o -l Generate ./fileminer.ini with logfile on
41
+ /var/log/fileminer/stderr.log
36
42
 
37
43
  Options:
38
44
  -t, --type fileminer|supervisor Type of the config file to be generated
@@ -40,7 +46,10 @@ Options:
40
46
  -o, --out [path] Output content to a file
41
47
  For type fileminer, default is /etc/fileminer/fileminer.yml
42
48
  For type supervisor, default is ./fileminer.ini
49
+ -l, --logfile [path] Logfile configured on supervisor config file
50
+ Default is /var/log/fileminer/stderr.log
43
51
  -h, --help Print help
52
+
44
53
  $ _
45
54
  ```
46
55
 
@@ -29,6 +29,20 @@ def gen_fileminer_conf(options)
29
29
  end
30
30
 
31
31
  def gen_supervisor_conf(options)
32
+ logfile = options[:logfile]
33
+ if logfile.nil? && options.key?(:logfile)
34
+ logfile = '/var/log/fileminer/stderr.log'
35
+ end
36
+ stdouts = ''
37
+ unless logfile.nil?
38
+ stdouts = <<-EOS
39
+ stderr_logfile=#{logfile}
40
+ stderr_logfile_maxbytes=10MB
41
+ stderr_logfile_backups=10
42
+ EOS
43
+ log_dir = File.dirname logfile
44
+ Dir.mkdirs log_dir unless Dir.exists? log_dir
45
+ end
32
46
  wrapper_home = File.join ENV['GEM_HOME'], 'wrappers'
33
47
  content = <<-EOS
34
48
  [program:fileminer]
@@ -37,6 +51,7 @@ autostart=true
37
51
  autorestart=true
38
52
  stopsinal=INT
39
53
  user=root
54
+ #{stdouts}
40
55
  EOS
41
56
  if options.key? :out
42
57
  out = options[:out]
@@ -44,7 +59,6 @@ user=root
44
59
  unless dst.end_with?('.ini') || dst.end_with?('.conf')
45
60
  dst = File.join dst, 'fileminer.ini'
46
61
  end
47
-
48
62
  dst_dir = File.dirname dst
49
63
  Dir.mkdirs dst_dir unless Dir.exists? dst_dir
50
64
  File.open(dst, 'w') { |io| io.write content }
@@ -57,7 +71,13 @@ end
57
71
  options = Hash.new
58
72
  OptionParser.new do |opts|
59
73
  # banner
60
- opts.banner = "Usage: fileminer-genconf [options]"
74
+ opts.banner = "Usage:"
75
+ opts.separator ' fileminer-genconf [options]'
76
+ opts.separator ''
77
+ opts.separator 'Samples:'
78
+ opts.separator ' fileminer-genconf -t fileminer -o Generate config on /etc/fileminer/fileminer.yml'
79
+ opts.separator ' fileminer-genconf -t supervisor -o -l Generate ./fileminer.ini with logfile on'
80
+ opts.separator ' /var/log/fileminer/stderr.log'
61
81
  opts.separator ''
62
82
  opts.separator 'Options:'
63
83
 
@@ -83,6 +103,13 @@ OptionParser.new do |opts|
83
103
  options[:out] = value
84
104
  end
85
105
 
106
+ # logfile, just for type=supervisor
107
+ opts.on('-l', '--logfile [path]',
108
+ 'Logfile configured on supervisor config file',
109
+ 'Default is /var/log/fileminer/stderr.log') do |value|
110
+ options[:logfile] = value
111
+ end
112
+
86
113
  end.parse!
87
114
 
88
115
  case options[:type]
@@ -90,4 +117,4 @@ when :fileminer
90
117
  gen_fileminer_conf options
91
118
  when :supervisor
92
119
  gen_supervisor_conf options
93
- end
120
+ end
@@ -13,13 +13,27 @@
13
13
  # default value is -1
14
14
  #max_lines_of_each_file: -1
15
15
 
16
+ # default value is 5s
17
+ #sleep_time_when_no_more_data: 5s
18
+
16
19
  # fileminer inputs
17
20
  fileminer.inputs:
18
21
 
22
+ # setup the path of work dir
23
+ # default value is /var/lib/fileminer
24
+ #work_dir: /var/lib/fileminer
25
+
19
26
  # setup the path of the registry file
20
- # default value is /var/lib/fileminer/registry
27
+ # default value is ${work_dir}/registry
21
28
  #registry_path: /var/lib/fileminer/registry
22
29
 
30
+ # setup the path of the history file
31
+ # default value is ${work_dir}/history
32
+ #history_path: /var/lib/fileminer/history
33
+
34
+ # default value is 20
35
+ #max_eof_files: 20
36
+
23
37
  # file paths
24
38
  paths:
25
39
  - /path/to/*.log
@@ -6,7 +6,8 @@ require_relative 'tools/io'
6
6
  class Miner
7
7
 
8
8
  DEFAULTS = {
9
- registry_path: '/var/lib/fileminer/registry',
9
+ work_dir: '/var/lib/fileminer',
10
+ max_eof_files: 20,
10
11
  eof_seconds: 86400,
11
12
  batch_lines: 200,
12
13
  }
@@ -25,6 +26,14 @@ class Miner
25
26
  # fix options by DEFAULTS
26
27
  DEFAULTS.each { |k, v| options[k] = v unless options.key? k }
27
28
  @registry_path = options[:registry_path]
29
+ if @registry_path.nil?
30
+ @registry_path = "#{options[:work_dir]}/registry"
31
+ end
32
+ @history_path = options[:history_path]
33
+ if @history_path.nil?
34
+ @history_path = "#{options[:work_dir]}/history"
35
+ end
36
+ @max_eof_files = options[:max_eof_files]
28
37
  @paths = options[:paths]
29
38
  @eof_seconds = options[:eof_seconds]
30
39
  @batch_lines = options[:batch_lines]
@@ -35,8 +44,15 @@ class Miner
35
44
  end
36
45
  @files = []
37
46
  @active_files = []
47
+ @history = []
48
+ if File.exist? @history_path
49
+ @history = File.open(@history_path) { |io| JSON.parse(io.read) }
50
+ else
51
+ parent_dir = File.dirname @history_path
52
+ Dir.mkdirs parent_dir unless Dir.exist? parent_dir
53
+ end
38
54
  if File.exist? @registry_path
39
- File.open(@registry_path) { |io| @files = JSON.parse(io.read, {symbolize_names: true}) }
55
+ @files = File.open(@registry_path) { |io| JSON.parse(io.read, {symbolize_names: true}) }
40
56
  @active_files = @files.select { |record| !record[:eof] }
41
57
  else
42
58
  parent_dir = File.dirname @registry_path
@@ -44,37 +60,40 @@ class Miner
44
60
  end
45
61
  end
46
62
 
63
+ # Save work status
64
+ def save_work_status
65
+ save_history
66
+ save_registry
67
+ end
68
+
47
69
  # Save registry
48
70
  def save_registry
49
71
  File.open(@registry_path, 'w') { |io| io.write @files.to_json }
50
72
  end
51
73
 
74
+ # Save history
75
+ def save_history
76
+ File.open(@history_path, 'w') { |io| io.write @history.to_json }
77
+ end
78
+
52
79
  # Refresh
53
80
  def refresh_files
54
81
  now = Time.now
55
82
  file_paths = Set.new
56
83
  file_paths.merge Dir[*@paths].select { |path| File.file? path }
57
- @active_file = @files.select do |record|
58
- path = record[:path]
59
- file_exists = file_paths.delete? path
60
- unless record[:eof]
61
- if file_exists
62
- # check if EOF
63
- if record[:pos] == File.size(path) && now - File.mtime(path) > @eof_seconds
64
- record[:eof] = true
65
- end
66
- else
67
- # missing file, set :eof to true
68
- record[:eof] = true
69
- end
70
- end
71
- !record[:eof]
84
+ active_files, eof_size = select_active_files now, file_paths
85
+ if eof_size > @max_eof_files
86
+ move_eof_to_history
72
87
  end
73
- file_paths.each do |path|
88
+ history_files = Set.new @history
89
+ file_paths.select do |path|
90
+ ! history_files.member? path
91
+ end.each do |path|
74
92
  record = {path: path, pos: 0, eof: false}
75
93
  @files << record
76
- @active_files << record
94
+ active_files << record
77
95
  end
96
+ @active_files = active_files
78
97
  @files_refresh_time = now
79
98
  end
80
99
 
@@ -108,4 +127,43 @@ class Miner
108
127
  Time.now - @files_refresh_time >= refresh_files_time_trigger
109
128
  end
110
129
 
130
+ private
131
+ def select_active_files(now, file_paths)
132
+ eof_seconds = @eof_seconds
133
+ eof_size = 0
134
+ active_files = @files.select do |record|
135
+ path = record[:path]
136
+ file_exists = file_paths.delete? path
137
+ if record[:eof]
138
+ eof_size += 1
139
+ else
140
+ if file_exists
141
+ # check if EOF
142
+ if record[:pos] == File.size(path) && now - File.mtime(path) > eof_seconds
143
+ record[:eof] = true
144
+ eof_size += 1
145
+ end
146
+ else
147
+ # missing file, set :eof to true
148
+ record[:eof] = true
149
+ eof_size += 1
150
+ end
151
+ end
152
+ !record[:eof]
153
+ end
154
+ [active_files, eof_size]
155
+ end
156
+
157
+ private
158
+ def move_eof_to_history
159
+ to_removed_paths = @files.select do |record|
160
+ record[:eof]
161
+ end.map do |record|
162
+ record[:path]
163
+ end
164
+ path_set = Set.new to_removed_paths
165
+ @files.delete_if { |record| path_set.member? record[:path] }
166
+ @history.concat to_removed_paths
167
+ end
168
+
111
169
  end
@@ -1,5 +1,5 @@
1
1
  class FileMiner
2
2
 
3
- VERSION = '1.1.1'
3
+ VERSION = '1.2.0'
4
4
 
5
5
  end
data/lib/fileminer.rb CHANGED
@@ -14,6 +14,7 @@ class FileMiner
14
14
  max_time_of_each_mining: '5s',
15
15
  max_lines_of_each_mining: -1,
16
16
  max_lines_of_each_file: -1,
17
+ sleep_time_when_no_more_data: '5s',
17
18
  }
18
19
 
19
20
  attr_reader :miner, :output, :running
@@ -59,6 +60,8 @@ class FileMiner
59
60
  end
60
61
  # refresh_files_time_trigger
61
62
  @refresh_files_time_trigger = parse_time conf[:refresh_files_time_trigger], 'refresh_files_time_trigger on fileminer.settings'
63
+ # sleep seconds when no more data
64
+ @sleep_seconds_when_no_more_data = parse_time conf[:sleep_time_when_no_more_data], 'sleep_time_when_no_more_data on fileminer.settings'
62
65
  end
63
66
 
64
67
  def parse_time(value, conf_name)
@@ -168,12 +171,13 @@ class FileMiner
168
171
  def mine_once
169
172
  start_time = Time.now
170
173
  full_lines = 0
171
- @miner.active_files.all? do |record|
174
+ miner = @miner
175
+ miner.active_files.all? do |record|
172
176
  mining_next = true
173
177
  if record[:pos] < File.size(record[:path])
174
178
  file_lines = 0
175
179
  loop do
176
- lines = @miner.read_lines record
180
+ lines = miner.read_lines record
177
181
  break if lines.empty?
178
182
  send_lines record, lines
179
183
  file_lines += lines.size
@@ -193,6 +197,7 @@ class FileMiner
193
197
  def start_mining
194
198
  unless @running
195
199
  @running = true
200
+ sleep_seconds = @sleep_seconds_when_no_more_data
196
201
  while @running
197
202
  begin
198
203
  files_refreshed = check_files
@@ -200,13 +205,13 @@ class FileMiner
200
205
  # sleep 5 seconds if no more data
201
206
  # TODO using settings instead in future
202
207
  if sent_lines == 0
203
- @miner.save_registry if files_refreshed
204
- sleep 5
208
+ @miner.save_work_status if files_refreshed
209
+ sleep sleep_seconds
205
210
  end
206
211
  rescue => e
207
212
  @logger.error e
208
213
  # sleep for a little while to wait output recover
209
- sleep 5 if @running
214
+ sleep sleep_seconds if @running
210
215
  end
211
216
  end
212
217
  @miner.save_registry
metadata CHANGED
@@ -1,16 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fileminer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fang MinJie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-24 00:00:00.000000000 Z
11
+ date: 2019-06-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: A simple file/log transfer tool coding by ruby.
13
+ description: |2
14
+ FileMiner is a simple file/log transfer tool implemented in Ruby.
15
+ Up to now, FileMiner has only tested on CRuby.
14
16
  email:
15
17
  - fmjsjx@163.com
16
18
  executables:
@@ -57,5 +59,5 @@ requirements: []
57
59
  rubygems_version: 3.0.4
58
60
  signing_key:
59
61
  specification_version: 4
60
- summary: A simple file/log transfer tool coding by ruby.
62
+ summary: A simple file/log transfer tool.
61
63
  test_files: []