fluent-plugin-dstat 0.1.0 → 0.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.
data/Gemfile CHANGED
@@ -7,9 +7,8 @@ source "http://rubygems.org"
7
7
  # Include everything needed to run rake, tests, features, etc.
8
8
  group :development do
9
9
  gem "shoulda", ">= 0"
10
- gem "bundler", "~> 1.0.0"
10
+ gem "bundler", "~> 1.0"
11
11
  gem "jeweler", "~> 1.6.4"
12
- gem "rcov", ">= 0"
13
12
  end
14
13
 
15
14
  gem "fluentd", "~> 0.10.7"
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ Dstat plugin for Fluent
2
+
3
+ Description goes here.
4
+
5
+ ## What's Dstat?
6
+
7
+ Dstat is a versatile replacement for vmstat, iostat, netstat and ifstat.
8
+ If you need more detail, see here[http://dag.wieers.com/home-made/dstat]
9
+ This plugin use Dstat, so you need to install Dstat before using this plugin.
10
+
11
+ ## Configuration
12
+
13
+ ```
14
+ <source>
15
+ type dstat
16
+ tag dstat
17
+ option -c
18
+ delay 3
19
+ </source>
20
+ ```
21
+
22
+ * option:option for dstat command(default: -fcdnm)
23
+
24
+ ## Output Format
25
+
26
+ When you use option -a, you get structured output data like below.
27
+
28
+ {
29
+ "hostname":"tsukuba000",
30
+ dstat":{"total cpu usage":"usr":"0.0","sys":"0.0","idl":"100.0","wai":"0.0","hiq":"0.0","siq":"0.0"},
31
+ "dsk/total":{"read":"0.0","writ":"0.0"},"net/total":{"recv":"148.0","send":"164.0"},
32
+ "paging":{"in":"0.0","out":"0.0"},
33
+ "system":{"int":"16.333","csw":"29.0"}}
34
+ }
35
+
36
+ ## Supported options
37
+
38
+ ```
39
+ aio, cpu, cpu24, disk, epoch, fs, int, int24, io, ipc, load, lock, mem, net, page, page24, proc, raw, socket, swap, swapold, sys, tcp, udp, unix, vm, disk-util, freespace, top-bio, top-cpu,top-io, top-mem, top-oom, utmp, top-io -fc
40
+ ```
41
+
42
+ ## Copyright
43
+
44
+ Copyright (c) 2011 Shunsuke Mikami. See LICENSE.txt for
45
+ further details.
46
+
data/Rakefile CHANGED
@@ -30,14 +30,6 @@ Rake::TestTask.new(:test) do |test|
30
30
  test.verbose = true
31
31
  end
32
32
 
33
- require 'rcov/rcovtask'
34
- Rcov::RcovTask.new do |test|
35
- test.libs << 'test'
36
- test.pattern = 'test/**/test_*.rb'
37
- test.verbose = true
38
- test.rcov_opts << '--exclude "gems/*"'
39
- end
40
-
41
33
  task :default => :test
42
34
 
43
35
  require 'rdoc/task'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -5,22 +5,22 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "fluent-plugin-dstat"
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Shunsuke Mikami"]
12
- s.date = "2012-01-12"
12
+ s.date = "2012-07-29"
13
13
  s.email = "shun0102@gmail.com"
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE.txt",
16
- "README.rdoc"
16
+ "README.md"
17
17
  ]
18
18
  s.files = [
19
19
  ".document",
20
20
  "AUTHORS",
21
21
  "Gemfile",
22
22
  "LICENSE.txt",
23
- "README.rdoc",
23
+ "README.md",
24
24
  "Rakefile",
25
25
  "VERSION",
26
26
  "fluent-plugin-dstat.gemspec",
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
30
30
  ]
31
31
  s.homepage = "http://github.com/shun0102/fluent-plugin-dstat"
32
32
  s.require_paths = ["lib"]
33
- s.rubygems_version = "1.8.10"
33
+ s.rubygems_version = "1.8.23"
34
34
  s.summary = "Dstat Input plugin for Fluent event collector"
35
35
 
36
36
  if s.respond_to? :specification_version then
@@ -40,24 +40,21 @@ Gem::Specification.new do |s|
40
40
  s.add_runtime_dependency(%q<fluentd>, ["~> 0.10.7"])
41
41
  s.add_runtime_dependency(%q<rdoc>, [">= 0"])
42
42
  s.add_development_dependency(%q<shoulda>, [">= 0"])
43
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
43
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
44
44
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
45
- s.add_development_dependency(%q<rcov>, [">= 0"])
46
45
  else
47
46
  s.add_dependency(%q<fluentd>, ["~> 0.10.7"])
48
47
  s.add_dependency(%q<rdoc>, [">= 0"])
49
48
  s.add_dependency(%q<shoulda>, [">= 0"])
50
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
51
50
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
52
- s.add_dependency(%q<rcov>, [">= 0"])
53
51
  end
54
52
  else
55
53
  s.add_dependency(%q<fluentd>, ["~> 0.10.7"])
56
54
  s.add_dependency(%q<rdoc>, [">= 0"])
57
55
  s.add_dependency(%q<shoulda>, [">= 0"])
58
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
59
57
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
60
- s.add_dependency(%q<rcov>, [">= 0"])
61
58
  end
62
59
  end
63
60
 
@@ -2,123 +2,129 @@ module Fluent
2
2
 
3
3
  class DstatInput < Input
4
4
 
5
- def split_second_key(str)
6
- result = []
7
- while (str)
8
- index = /[^ ] / =~ str
9
- if index
10
- result << str[0..index]
11
- else
12
- result << str unless str == " "
13
- return result
14
- end
15
- str = str[(index + 1)..-1]
16
- end
17
-
18
- return result
19
- end
20
-
21
5
  Plugin.register_input('dstat', self)
22
6
 
23
7
  def initialize
24
8
  super
9
+ require 'csv'
25
10
  @hostname = `hostname -s`.chomp!
26
11
  @line_number = 0
27
12
  @first_keys = []
28
13
  @second_keys = []
14
+ @data_array = []
15
+ @max_lines = 100
29
16
  end
30
17
 
31
18
  config_param :tag, :string
32
19
  config_param :option, :string, :default => "-fcdnm"
33
20
  config_param :delay, :integer, :default => 1
21
+ config_param :tmp_file, :string, :default => "/tmp/dstat.csv"
34
22
 
35
23
  def configure(conf)
36
24
  super
37
- @command = "dstat #{@option} #{@delay}"
25
+ @command = "dstat #{@option} --output #{@tmp_file} #{@delay}"
38
26
  end
39
27
 
40
28
  def start
29
+ if File.exist?(@tmp_file)
30
+ File.truncate(@tmp_file, 0)
31
+ else
32
+ `touch #{@tmp_file}`
33
+ end
41
34
  @io = IO.popen(@command, "r")
42
35
  @pid = @io.pid
36
+
37
+ @loop = Coolio::Loop.new
38
+ @dw = DstatCSVWatcher.new(@tmp_file, &method(:receive_lines))
39
+ @dw.attach(@loop)
43
40
  @thread = Thread.new(&method(:run))
44
41
  end
45
42
 
46
43
  def shutdown
47
44
  Process.kill(:TERM, @pid)
48
- if @thread.join(60) # TODO wait time
49
- return
50
- end
51
- Process.kill(:KILL, @pid)
45
+ @dw.detach
46
+ @loop.stop
52
47
  @thread.join
48
+ File.delete(@tmp_file)
53
49
  end
54
50
 
55
51
  def run
56
- @io.each_line(&method(:each_line))
57
- end
58
-
59
- private
60
- def each_line(line)
61
52
  begin
62
- line.chomp!
63
- line.gsub!(/\e\[7l/, "")
53
+ @loop.run
54
+ rescue
55
+ $log.error "unexpected error", :error=>$!.to_s
56
+ $log.error_backtrace
57
+ end
58
+ end
64
59
 
60
+ def receive_lines(lines)
61
+ lines.each do |line|
62
+ next if line == ""
65
63
  case @line_number
66
- when 0
67
- @first_keys = line.split(" ")
68
- when 1
69
- index = 0
70
- @first_keys.each do |i|
71
- @second_keys << line[index..(index + i.length - 1)]
72
- index += i.length + 1
64
+ when 0..1
65
+ when 2
66
+ line.delete!("\"")
67
+ @first_keys = CSV.parse_line(line)
68
+ pre_key = ""
69
+ @first_keys.each_with_index do |key, index|
70
+ if key.nil? || key == ""
71
+ @first_keys[index] = pre_key
72
+ end
73
+ pre_key = @first_keys[index]
73
74
  end
74
- else
75
- hash = Hash.new()
76
- values = []
77
- index = 0
78
- @first_keys.each do |i|
79
- values << line[index..(index + i.length - 1)]
80
- index += i.length + 1
75
+ when 3
76
+ line.delete!("\"")
77
+ @second_keys = line.split(',')
78
+ @first_keys.each_with_index do |key, index|
79
+ @data_array[index] = {}
80
+ @data_array[index][:first] = key
81
+ @data_array[index][:second] = @second_keys[index]
81
82
  end
82
-
83
- @first_keys.each_with_index do |i, index|
84
- value_hash = Hash.new()
85
- first = i.gsub(/^-+|-+$/, "")
86
- length = i.length
87
-
88
- if first == "most-expensive"
89
- s_key = @second_keys[index].gsub(/^\s+|\s+$/, "")
90
- value_hash[s_key] = values[index]
91
- else
92
- keys = split_second_key(@second_keys[index])
93
- second_index = 0
94
-
95
- keys.each do |i|
96
- next_index = second_index + i.length - 1
97
- value = values[index][second_index..next_index]
98
- second_index += i.length + 1
99
- value = value.gsub(/^\s+|\s+$/, "") if value
100
- value_hash[i.gsub(/^\s+|\s+$/, "")] = value
101
- end
102
- end
103
-
104
- if hash[first].nil?
105
- hash[first] = value_hash
106
- else
107
- hash[first] = hash[first].merge(value_hash)
108
- end
83
+ else
84
+ values = line.split(',')
85
+ data = Hash.new { |hash,key| hash[key] = Hash.new {} }
86
+ values.each_with_index do |v, index|
87
+ data[@first_keys[index]][@second_keys[index]] = v
109
88
  end
110
-
111
89
  record = {
112
90
  'hostname' => @hostname,
113
- 'dstat' => hash
91
+ 'dstat' => data
114
92
  }
115
93
  Engine.emit(@tag, Engine.now, record)
116
94
  end
95
+
96
+ if (@line_number % @max_lines) == (@max_lines - 1)
97
+ @dw.detach
98
+ File.truncate(@tmp_file, 0)
99
+ @dw = DstatCSVWatcher.new(@tmp_file, &method(:receive_lines))
100
+ @dw.attach(@loop)
101
+ end
102
+
117
103
  @line_number += 1
104
+ end
118
105
 
119
- rescue
120
- $log.error "exec failed to emit", :error=>$!, :line=>line
121
- $log.warn_backtrace $!.backtrace
106
+ end
107
+
108
+ class DstatCSVWatcher < Cool.io::StatWatcher
109
+ INTERVAL = 0.500
110
+ attr_accessor :previous, :cur
111
+
112
+ def initialize(path, &receive_lines)
113
+ super path, INTERVAL
114
+ @path = path
115
+ @io = File.open(path)
116
+ @pos = 0
117
+ @receive_lines = receive_lines
118
+ end
119
+
120
+ def on_change(prev, cur)
121
+ buffer = @io.read(cur.size - @pos)
122
+ @pos = cur.size
123
+ lines = []
124
+ while line = buffer.slice!(/.*?\n/m)
125
+ lines << line.chomp
126
+ end
127
+ @receive_lines.call(lines)
122
128
  end
123
129
  end
124
130
  end
@@ -9,9 +9,9 @@ class DstatInputTest < Test::Unit::TestCase
9
9
  "epoch", "fs", "int", "int24", "io", "ipc", "load", "lock",
10
10
  "mem", "net", "page", "page24", "proc", "raw", "socket",
11
11
  "swap", "swapold", "sys", "tcp", "udp", "unix", "vm",
12
- "disk-tps", "disk-util", "dstat-cpu", "dstat-ctxt", "dstat-mem", "freespace",
13
- "top-bio", "top-childwait", "top-cpu","top-io",
14
- "top-mem", "top-oom", "utmp", "top-io -fc"]
12
+ "disk-util", "freespace",
13
+ "top-bio", "top-cpu","top-io",
14
+ "top-mem", "top-oom", "top-io -fc"]
15
15
 
16
16
  CONFIG = %[
17
17
  tag dstat
@@ -31,7 +31,6 @@ class DstatInputTest < Test::Unit::TestCase
31
31
  def test_emit
32
32
 
33
33
  OPTIONS.each do |op|
34
- #emit_with_conf(CONFIG)
35
34
  conf = "tag dstat\n option --#{op}\n delay 1"
36
35
  emit_with_conf(conf)
37
36
  end
@@ -46,6 +45,7 @@ class DstatInputTest < Test::Unit::TestCase
46
45
  end
47
46
 
48
47
  length = `dstat #{d.instance.option} #{d.instance.delay} 1`.split("\n")[0].split("\s").length
48
+ puts `dstat #{d.instance.option} #{d.instance.delay} 3`
49
49
 
50
50
  emits = d.emits
51
51
  assert_equal true, emits.length > 0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-dstat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-12 00:00:00.000000000Z
12
+ date: 2012-07-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
16
- requirement: &22315940 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 0.10.7
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22315940
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.10.7
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rdoc
27
- requirement: &22315460 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *22315460
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: shoulda
38
- requirement: &22314980 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,21 +53,31 @@ dependencies:
43
53
  version: '0'
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *22314980
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: bundler
49
- requirement: &22314500 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ~>
53
68
  - !ruby/object:Gem::Version
54
- version: 1.0.0
69
+ version: '1.0'
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *22314500
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.0'
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: jeweler
60
- requirement: &22314020 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ~>
@@ -65,31 +85,25 @@ dependencies:
65
85
  version: 1.6.4
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *22314020
69
- - !ruby/object:Gem::Dependency
70
- name: rcov
71
- requirement: &22313540 !ruby/object:Gem::Requirement
88
+ version_requirements: !ruby/object:Gem::Requirement
72
89
  none: false
73
90
  requirements:
74
- - - ! '>='
91
+ - - ~>
75
92
  - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
78
- prerelease: false
79
- version_requirements: *22313540
93
+ version: 1.6.4
80
94
  description:
81
95
  email: shun0102@gmail.com
82
96
  executables: []
83
97
  extensions: []
84
98
  extra_rdoc_files:
85
99
  - LICENSE.txt
86
- - README.rdoc
100
+ - README.md
87
101
  files:
88
102
  - .document
89
103
  - AUTHORS
90
104
  - Gemfile
91
105
  - LICENSE.txt
92
- - README.rdoc
106
+ - README.md
93
107
  - Rakefile
94
108
  - VERSION
95
109
  - fluent-plugin-dstat.gemspec
@@ -110,7 +124,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
124
  version: '0'
111
125
  segments:
112
126
  - 0
113
- hash: 3115706696286106192
127
+ hash: -4423186394386880393
114
128
  required_rubygems_version: !ruby/object:Gem::Requirement
115
129
  none: false
116
130
  requirements:
@@ -119,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
133
  version: '0'
120
134
  requirements: []
121
135
  rubyforge_project:
122
- rubygems_version: 1.8.10
136
+ rubygems_version: 1.8.23
123
137
  signing_key:
124
138
  specification_version: 3
125
139
  summary: Dstat Input plugin for Fluent event collector
data/README.rdoc DELETED
@@ -1,43 +0,0 @@
1
- = Dstat plugin for Fluent
2
-
3
- Description goes here.
4
-
5
- == What's Dstat?
6
-
7
- Dstat is a versatile replacement for vmstat, iostat, netstat and ifstat.
8
- If you need more detail, see here[http://dag.wieers.com/home-made/dstat]
9
- This plugin use Dstat, so you need to install Dstat before using this plugin.
10
-
11
- == Configuration
12
-
13
- <source>
14
- type dstat
15
- tag dstat
16
- option -c 3
17
- </source>
18
-
19
- * option:option for dstat command(default: -fcdnm 1)
20
-
21
- == Output Format
22
-
23
- When you use option -c, you get structured output data like below.
24
-
25
- {
26
- "hostname":"tsukuba000",
27
- "dstat":{"total-cpu-usage":{"usr":"0",
28
- "sys":"0",
29
- "idl":"100",
30
- "wai":"0",
31
- "hiq":"0",
32
- "siq":"0"}}
33
- }
34
-
35
- == Supported options
36
-
37
- aio, cpu, cpu24, disk, epoch, fs, int, int24, io, ipc, load, lock, mem, net, page, page24, proc, raw, socket, swap, swapold, sys, tcp, udp, unix, vm, disk-tps, disk-util, dstat-cpu, dstat-ctxt, dstat-mem, freespace, top-bio, top-childwait, top-cpu,top-io, top-mem, top-oom, utmp, top-io -fc
38
-
39
- == Copyright
40
-
41
- Copyright (c) 2011 Shunsuke Mikami. See LICENSE.txt for
42
- further details.
43
-