fluent-diagtool 0.1.3 → 0.1.4

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
  SHA256:
3
- metadata.gz: cec6d985c53b3d147c6d1eb5418ae15983b1bf2ec1bcd15f6c4c035f20a93cf3
4
- data.tar.gz: b58b0565d227ccc1f99d0dc3fbb482e03b1cb5faf38c9a5326fe753f0a222efc
3
+ metadata.gz: 180c7e58ee03d59778640b05042fca84197936b7bdd2b2fff236ef86f0639ef4
4
+ data.tar.gz: b1ffccfb3a92af08dfa17fe4796e7a229a25d0abe1bf0f1362ac4618bf5c99f0
5
5
  SHA512:
6
- metadata.gz: c1f5582d4f9835d158f09ee7256771406cf57c8753b6de9170c68d5b4f774ebb7397fce7fe70c8d247eb92bedf9f46a6af6f575b783a4718323b48a2a824b521
7
- data.tar.gz: 139b59e1c25cd34e745ba799d5c323c18421d3f5b4b95fbf9c59c63b75291e6663ee9a5cb43cb3cb8ac75ea99a1a495b6c3f9b731960643a93df0fc09e3ddfc1
6
+ metadata.gz: b482bfc75cda3285976980d2f8a04abfe848dd9bb6ff4992c0760f871f237811fbae361dfb15075482a781ec284974d7471937423e3400f0b576bc3dff03ccf0
7
+ data.tar.gz: 5810ec1b6f37b5ccf49f53bd8271beb885dde8c7b9e8be33aed38b5d137e8952085aaddbb8b7717e58535bd36decd19e1babde94a2ba78d07ba41d1ffd0cf9c5
@@ -0,0 +1,13 @@
1
+ ~*
2
+ #*
3
+ *~
4
+ [._]*.s[a-w][a-z]
5
+ .DS_Store
6
+
7
+ *.gem
8
+ .bundle
9
+ Gemfile.lock
10
+ vendor
11
+ .ruby-version
12
+
13
+ test/tmp/
data/AUTHORS CHANGED
@@ -1 +1 @@
1
- TOMONORI KUBOTA <tmnr.kubota _at_ gmail.com>
1
+ TOMONORI KUBOTA <tkubota _at_ ctc-america.com>
@@ -1,16 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-diagtool (0.1.2)
5
- fileutils (~> 1.0.2)
6
- json (~> 2.1.0)
4
+ fluent-diagtool (0.1.4)
5
+ fileutils (~> 1.0)
6
+ json (~> 2.1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
11
  diff-lcs (1.3)
12
- fileutils (1.0.2)
13
- json (2.1.0)
12
+ fileutils (1.4.1)
13
+ json (2.3.0)
14
14
  rake (12.3.3)
15
15
  rspec (3.9.0)
16
16
  rspec-core (~> 3.9.0)
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Fluentd Diagnostic Tool
2
2
 
3
- The diagtool enable users to automate the date collection which is required for trouble shooting. The data collected by diagtool include the configuration and log files of the td-agent and diagnostic information of operating system such as network and memory status and stats. In some cases, configuration and log files contains the security sensitive information, such as IP addresses and Hostname. The diagtool also provides the functions to generate mask on IP addresses, Hostname(in FQDN style) and user defined keywords described in the collected data.<br>
4
- The scope of data collection:<br>
3
+ The diagtool enable users to automate the date collection which is required for trouble shooting. The data collected by diagtool include the configuration and log files of the td-agent and diagnostic information of operating system such as network and memory status and stats. In some cases, configuration and log files contains the security sensitive information, such as IP addresses and Hostname. The diagtool also provides the functions to generate mask on IP addresses, Hostname(in FQDN style) and user defined keywords described in the collected data.
4
+ The scope of data collection:
5
5
  - TD Agent information
6
6
  - configuration files (*)
7
7
  - log files (*)
@@ -11,18 +11,21 @@ The scope of data collection:
11
11
  - OS log file
12
12
  - OS parameters
13
13
  - OS and kernel version
14
- - time/date information
15
- - maximum number of file descriptor(ulimit)
14
+ - time/date information(ntp -q/chronyc sources)
15
+ - maximum number of file descriptor(ulimit -n)
16
16
  - kernel network parameters(sysctl)
17
- - network conectivity status/stats
18
- - memory information
17
+ - snapshot of current process(ps)
18
+ - network conectivity status/stats(netstat -plan/netstat -s)
19
+ - memory information(/proc/meminfo)
19
20
  <br>
20
- (*) The diagtool automatically gather the path of td-agent configuration files and log files and use them during data collection.
21
+ (*) The diagtool automatically gather the path of td-agent configuration files and log files from td-agent daemon and use them during data collection.
21
22
 
22
23
  ## Prerequisite
24
+ The diagtool provides support for td-agent based installation running on Linux OS. The td-agent is a stable distribution package of Fluentd.
25
+ The differences between Fluentd and td-agent are described in followed url:
26
+ https://www.fluentd.org/faqs
23
27
 
24
-
25
- ## Installation
28
+ ## Diagtool Installation
26
29
 
27
30
  ```
28
31
  # gem install fluent-diagtool
@@ -114,8 +117,8 @@ NOTE: When user specified the keywork, only the exact match words will be masked
114
117
  2020-05-12 18:21:22 -0400: [Diagtool] [INFO] [Collect] Generate tar file /tmp/work1/diagout-20200512182119.tar.gz
115
118
  ```
116
119
  ## Mask Function
117
- When run diagtool with mask option, the log of mask is also created in 'mask_{timestamp}.json' file. Users are able to confirm how the mask was generated on each files.
118
- <br>
120
+ When run diagtool with mask option, the log of mask is also created in 'mask_{timestamp}.json' file. Users are able to confirm how the mask was generated on each files.
121
+ The diagtool provides hash-seed option with '-s'. When hash-seed is specified, the mask will be generated with original word and hash-seed so that users could use unique mask value.
119
122
  #### Mask sample - IP address: IPv4_{md5hash}
120
123
  ```
121
124
  "Line112-8": {
@@ -26,13 +26,21 @@ include Diagtool
26
26
  params = {}
27
27
  OptionParser.new do |opt|
28
28
  opt.banner = "Usage: #{$0} -o OUTPUT_DIR -m {yes | no} -w {word1,[word2...]} -f {listfile} -s {hash seed}"
29
+ opt.on('--precheck', 'Run Precheck (Optional)')
29
30
  opt.on('-o','--output DIR', String, 'Output directory (Mandatory)')
30
31
  opt.on('-m','--mask yes|no', String, 'Enable mask function (Optional : Default=no)')
31
32
  opt.on('-w','--word-list word1,word2', Array, 'Provide a list of user-defined words which will to be masked (Optional : Default=None)')
32
- opt.on('-f','--word-file listfile', String, 'provide a file which describes a List of user-defined words (Optional : Default=None)')
33
+ opt.on('-f','--word-file list_file', String, 'provide a file which describes a List of user-defined words (Optional : Default=None)')
33
34
  opt.on('-s','--hash-seed seed', String, 'provide a word which will be used when generate the mask (Optional : Default=None)')
35
+ opt.on('-c','--conf config_file', String, 'provide a full path of td-agent configuration file (Optional : Default=None)')
36
+ opt.on('-l','--log log_file', String, 'provide a full path of td-agent log file (Optional : Default=None)')
34
37
  end.parse!(into: params)
38
+
35
39
  diag = DiagUtils.new(params)
36
- diag.diagtool()
40
+ if params[:precheck]
41
+ diag.run_precheck()
42
+ else
43
+ diag.run_diagtool()
44
+ end
37
45
 
38
46
 
@@ -24,17 +24,35 @@ module Diagtool
24
24
  @logger = Logger.new(STDOUT, level: log_level, formatter: proc {|severity, datetime, progname, msg|
25
25
  "#{datetime}: [Diagutils] [#{severity}] #{msg}\n"
26
26
  })
27
+ @precheck = conf[:precheck]
27
28
  @time_format = conf[:time]
28
29
  @basedir = conf[:basedir]
29
30
  @workdir = conf[:workdir]
30
31
  @outdir = conf[:outdir]
31
-
32
+
32
33
  @tdenv = get_tdenv()
33
- @tdconf = @tdenv['FLUENT_CONF'].split('/')[-1]
34
- @tdconf_path = @tdenv['FLUENT_CONF'].gsub(@tdconf,'')
35
- @tdlog = @tdenv['TD_AGENT_LOG_FILE'].split('/')[-1]
36
- @tdlog_path = @tdenv['TD_AGENT_LOG_FILE'].gsub(@tdlog,'')
37
-
34
+ if not conf[:tdconf].empty?
35
+ @tdconf = conf[:tdconf].split('/')[-1]
36
+ @tdconf_path = conf[:tdconf].gsub(@tdconf,'')
37
+ elsif
38
+ if not @tdenv['FLUENT_CONF'].empty?
39
+ @tdconf = @tdenv['FLUENT_CONF'].split('/')[-1]
40
+ @tdconf_path = @tdenv['FLUENT_CONF'].gsub(@tdconf,'')
41
+ else
42
+ raise "The path of td-agent configuration file need to be specified." if conf[:precheck] == false
43
+ end
44
+ end
45
+ if not conf[:tdlog].empty?
46
+ @tdlog = conf[:tdlog].split('/')[-1]
47
+ @tdlog_path = conf[:tdlog].gsub(@tdlog,'')
48
+ elsif
49
+ if not @tdenv['TD_AGENT_LOG_FILE'].empty?
50
+ @tdlog = @tdenv['TD_AGENT_LOG_FILE'].split('/')[-1]
51
+ @tdlog_path = @tdenv['TD_AGENT_LOG_FILE'].gsub(@tdlog,'')
52
+ else
53
+ raise "The path of td-agent log file need to be specified." if conf[:precheck] == false
54
+ end
55
+ end
38
56
  @osenv = get_osenv()
39
57
  @oslog_path = '/var/log/'
40
58
  @oslog = 'messages'
@@ -57,8 +75,10 @@ module Diagtool
57
75
  s = l.split(":")
58
76
  os_dict[s[0].chomp.strip] = s[1].chomp.strip
59
77
  }
60
- File.open(@workdir+'/os_env.output', 'w') do |f|
61
- f.puts(stdout)
78
+ if @precheck == false # SKip if precheck is true
79
+ File.open(@outdir+'/os_env.output', 'w') do |f|
80
+ f.puts(stdout)
81
+ end
62
82
  end
63
83
  return os_dict
64
84
  end
@@ -66,13 +86,43 @@ module Diagtool
66
86
  def get_tdenv()
67
87
  stdout, stderr, status = Open3.capture3('systemctl cat td-agent')
68
88
  env_dict = {}
69
- File.open(@workdir+'/td-agent_env.output', 'w') do |f|
70
- f.puts(stdout)
71
- end
89
+ if status.success?
90
+ if @precheck == false # SKip if precheck is true
91
+ File.open(@outdir+'/td-agent_env.output', 'w') do |f|
92
+ f.puts(stdout)
93
+ end
94
+ end
72
95
  stdout.split().each do | l |
73
- if l.include?('Environment')
74
- env_dict[l.split('=')[1]] = l.split('=')[2]
75
- end
96
+ if l.include?('Environment')
97
+ env_dict[l.split('=')[1]] = l.split('=')[2]
98
+ end
99
+ end
100
+ else
101
+ exe = 'fluentd'
102
+ stdout, stderr, status = Open3.capture3("ps aux | grep #{exe} | grep -v grep")
103
+ line = stdout.split(/\n/)
104
+ log_path = ''
105
+ conf_path = ''
106
+ line.each { |l|
107
+ cmd = l.split.drop(10)
108
+ i = 0
109
+ log_pos = 0
110
+ conf_pos = 0
111
+ if cmd[-1] != '--under-supervisor'
112
+ cmd.each { |c|
113
+ if c.include?("--log") || c.include?("-l")
114
+ log_pos = i + 1
115
+ log_path = cmd[log_pos]
116
+ elsif c.include?("--conf") || c.include?("-c")
117
+ conf_pos = i + 1
118
+ conf_path = cmd[conf_pos]
119
+ end
120
+ i+=1
121
+ }
122
+ end
123
+ }
124
+ env_dict['FLUENT_CONF'] = conf_path
125
+ env_dict['TD_AGENT_LOG_FILE'] = log_path
76
126
  end
77
127
  return env_dict
78
128
  end
@@ -90,27 +140,34 @@ module Diagtool
90
140
  end
91
141
 
92
142
  def collect_tdconf()
93
- FileUtils.mkdir_p(@workdir+@tdconf_path)
94
- FileUtils.cp(@tdconf_path+@tdconf, @workdir+@tdconf_path)
95
- return @workdir+@tdconf_path+@tdconf
143
+ target_dir = @workdir+@tdconf_path
144
+ FileUtils.mkdir_p(target_dir)
145
+ FileUtils.cp(@tdconf_path+@tdconf, target_dir)
146
+ return target_dir+@tdconf
96
147
  end
97
148
 
98
149
  def collect_tdlog()
99
- FileUtils.mkdir_p(@workdir+@tdlog_path)
100
- FileUtils.cp_r(@tdlog_path, @workdir+@oslog_path)
101
- return Dir.glob(@workdir+@tdlog_path+@tdlog+'*')
150
+ target_dir = @workdir+@tdlog_path
151
+ p target_dir
152
+ FileUtils.mkdir_p(target_dir)
153
+ Dir.glob(@tdlog_path+@tdlog+'*').each{ |f|
154
+ FileUtils.cp(f, target_dir)
155
+ }
156
+ return Dir.glob(target_dir+@tdlog+'*')
102
157
  end
103
158
 
104
159
  def collect_sysctl()
105
- FileUtils.mkdir_p(@workdir+@sysctl_path)
106
- FileUtils.cp(@sysctl_path+@sysctl, @workdir+@sysctl_path)
107
- return @workdir+@sysctl_path+@sysctl
160
+ target_dir = @workdir+@sysctl_path
161
+ FileUtils.mkdir_p(target_dir)
162
+ FileUtils.cp(@sysctl_path+@sysctl, target_dir)
163
+ return target_dir+@sysctl
108
164
  end
109
165
 
110
166
  def collect_oslog()
111
- FileUtils.mkdir_p(@workdir+@oslog_path)
112
- FileUtils.cp(@oslog_path+@oslog, @workdir+@oslog_path)
113
- return @workdir+@oslog_path+@oslog
167
+ target_dir = @workdir+@oslog_path
168
+ FileUtils.mkdir_p(target_dir)
169
+ FileUtils.cp(@oslog_path+@oslog, target_dir)
170
+ return target_dir+@oslog
114
171
  end
115
172
 
116
173
  def collect_ulimit()
@@ -27,14 +27,62 @@ module Diagtool
27
27
  time = Time.new
28
28
  @time_format = time.strftime("%Y%m%d%0k%M%0S")
29
29
  @conf = parse_diagconf(params)
30
+ #@conf[:time] = @time_format
31
+ #@conf[:workdir] = @conf[:basedir] + '/' + @time_format
32
+ #@conf[:outdir] = @conf[:workdir] + '/output'
33
+
34
+ #FileUtils.mkdir_p(@conf[:workdir])
35
+ #FileUtils.mkdir_p(@conf[:outdir])
36
+
37
+ #diaglog = @conf[:workdir] + '/diagtool.output'
38
+ #@masklog = './mask_' + @time_format + '.json'
39
+ #@logger = Logger.new(STDOUT, formatter: proc {|severity, datetime, progname, msg|
40
+ # "#{datetime}: [Diagtool] [#{severity}] #{msg}\n"
41
+ #})
42
+ #@logger_file = Logger.new(diaglog, formatter: proc {|severity, datetime, progname, msg|
43
+ # "#{datetime}: [Diagtool] [#{severity}] #{msg}\n"
44
+ #})
45
+ #diaglogger_info("Parsing command options...")
46
+ #diaglogger_info(" Option : Output directory = #{@conf[:basedir]}")
47
+ #diaglogger_info(" Option : Mask = #{@conf[:mask]}")
48
+ #diaglogger_info(" Option : Word list = #{@conf[:words]}")
49
+ #diaglogger_info(" Option : Hash Seed = #{@conf[:seed]}")
50
+ end
51
+
52
+ def run_precheck()
53
+ prechecklog = Logger.new(STDOUT, formatter: proc {|severity, datetime, progname, msg|
54
+ "#{datetime}: [Diagtool] [#{severity}] #{msg}\n"
55
+ })
56
+ loglevel = 'WARN'
57
+ c = CollectUtils.new(@conf, loglevel)
58
+ c_env = c.export_env()
59
+ prechecklog.info("[Precheck] Check OS parameters...")
60
+ prechecklog.info("[Precheck] operating system = #{c_env[:os]}")
61
+ prechecklog.info("[Precheck] kernel version = #{c_env[:kernel]}")
62
+ prechecklog.info("[Precheck] Check td-agent parameters...")
63
+ prechecklog.info("[Precheck] td-agent conf path = #{c_env[:tdconf_path]}")
64
+ prechecklog.info("[Precheck] td-agent conf file = #{c_env[:tdconf]}")
65
+ prechecklog.info("[Precheck] td-agent log path = #{c_env[:tdlog_path]}")
66
+ prechecklog.info("[Precheck] td-agent log = #{c_env[:tdlog]}")
67
+ if c_env[:tdconf_path] == nil || c_env[:tdconf] == nil
68
+ prechecklog.warn("[Precheck] can not find td-agent conf path: please run diagtool command with -c /path/to/<td-agent conf file>")
69
+ end
70
+ if c_env[:tdlog_path] == nil || c_env[:tdlog] == nil
71
+ prechecklog.warn("[Precheck] can not find td-agent log path: please run diagtool command with -l /path/to/<td-agent log file>")
72
+ end
73
+ if c_env[:tdconf_path] != nil && c_env[:tdconf] != nil && c_env[:tdlog_path] != nil && c_env[:tdlog] != nil
74
+ prechecklog.info("[Precheck] Precheck completed. You can run diagtool command without -c and -l options")
75
+ end
76
+ end
77
+
78
+ def run_diagtool()
30
79
  @conf[:time] = @time_format
31
80
  @conf[:workdir] = @conf[:basedir] + '/' + @time_format
32
81
  @conf[:outdir] = @conf[:workdir] + '/output'
33
-
34
82
  FileUtils.mkdir_p(@conf[:workdir])
35
83
  FileUtils.mkdir_p(@conf[:outdir])
36
-
37
84
  diaglog = @conf[:workdir] + '/diagtool.output'
85
+
38
86
  @masklog = './mask_' + @time_format + '.json'
39
87
  @logger = Logger.new(STDOUT, formatter: proc {|severity, datetime, progname, msg|
40
88
  "#{datetime}: [Diagtool] [#{severity}] #{msg}\n"
@@ -47,9 +95,7 @@ module Diagtool
47
95
  diaglogger_info(" Option : Mask = #{@conf[:mask]}")
48
96
  diaglogger_info(" Option : Word list = #{@conf[:words]}")
49
97
  diaglogger_info(" Option : Hash Seed = #{@conf[:seed]}")
50
- end
51
-
52
- def diagtool()
98
+
53
99
  loglevel = 'WARN'
54
100
  diaglogger_info("Initializing parameters...")
55
101
  c = CollectUtils.new(@conf, loglevel)
@@ -167,16 +213,23 @@ module Diagtool
167
213
 
168
214
  def parse_diagconf(params)
169
215
  options = {
170
- :basedir => '', :mask => '', :words => [], :wfile => '', :seed => ''
216
+ :precheck => '', :basedir => '', :mask => '', :words => [], :wfile => '', :seed => '', :tdconf =>'', :tdlog => ''
171
217
  }
172
- if params[:output] != nil
173
- if Dir.exist?(params[:output])
174
- options[:basedir] = params[:output]
218
+ if params[:precheck]
219
+ options[:precheck] = params[:precheck]
220
+ else
221
+ options[:precheck] = false
222
+ end
223
+ if options[:precheck] == false
224
+ if params[:output] != nil
225
+ if Dir.exist?(params[:output])
226
+ options[:basedir] = params[:output]
227
+ else
228
+ raise "output directory '#{basedir}' does not exist"
229
+ end
175
230
  else
176
- raise "output directory '#{basedir}' does not exist"
231
+ raise "output directory '-o' must be specified"
177
232
  end
178
- else
179
- raise "output directory '-o' must be specified"
180
233
  end
181
234
  if params[:mask] == nil
182
235
  options[:mask] = 'no'
@@ -200,6 +253,25 @@ module Diagtool
200
253
  end
201
254
  options[:words] = options[:words].uniq
202
255
  options[:seed] = params[:"hash-seed"] if params[:"hash-seed"] != nil
256
+
257
+ if params[:conf] != nil
258
+ f = params[:conf]
259
+ if File.exist?(f)
260
+ options[:tdconf] = params[:conf]
261
+ else
262
+ raise "#{params[:conf]} : No such file or directory"
263
+ end
264
+ end
265
+
266
+ if params[:log] != nil
267
+ f = params[:log]
268
+ if File.exist?(f)
269
+ options[:tdlog] = params[:log]
270
+ else
271
+ raise "#{params[:log]} : No such file or directory"
272
+ end
273
+ end
274
+
203
275
  return options
204
276
  end
205
277
 
@@ -1,5 +1,5 @@
1
1
  module Fluent
2
2
  module Diagtool
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-diagtool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - kubotat
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-19 00:00:00.000000000 Z
11
+ date: 2020-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fileutils
@@ -48,6 +48,7 @@ executables:
48
48
  extensions: []
49
49
  extra_rdoc_files: []
50
50
  files:
51
+ - ".gitignore"
51
52
  - AUTHORS
52
53
  - Gemfile
53
54
  - Gemfile.lock