Skip to content

Commit 3913d3a

Browse files
committed
updated proc.rb to get stats on all processes
1 parent 557d92b commit 3913d3a

File tree

5 files changed

+173
-73
lines changed

5 files changed

+173
-73
lines changed

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
source 'https://rubygems.org'
2+
gem "logstash-input-proc", :path => "/home/eperry/ws-logstash/workspace/logstash-input-proc"
23
gemspec

README.md

+27-42
Original file line numberDiff line numberDiff line change
@@ -2,62 +2,43 @@
22

33
This is a plugin for [Logstash](https://github.com/elasticsearch/logstash).
44

5-
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
5+
This plugin is to read the /proc virtual file system , decode the files in it.
66

77
## Documentation
88

9-
Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elasticsearch.org/guide/en/logstash/current/).
10-
11-
- For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
12-
- For more asciidoc formatting tips, see the excellent reference here https://github.com/elasticsearch/docs#asciidoc-guide
13-
14-
## Need Help?
15-
16-
Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
17-
18-
## Developing
199

2010
### 1. Plugin Developement and Testing
2111

2212
#### Code
2313
- To get started, you'll need JRuby with the Bundler gem installed.
24-
25-
- Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
26-
27-
- Install dependencies
28-
```sh
14+
```sh
2915
bundle install
3016
```
3117

32-
#### Test
18+
- Then clone this repo
19+
- You will need to either clone the logstash repo or download the binary
3320

34-
- Update your dependencies
3521

36-
```sh
37-
bundle install
38-
```
3922

40-
- Run tests
41-
42-
```sh
43-
bundle exec rspec
44-
```
45-
46-
### 2. Running your unpublished Plugin in Logstash
23+
### 2. Running the unpublished Plugin in Logstash
4724

4825
#### 2.1 Run in a local Logstash clone
4926

5027
- Edit Logstash `Gemfile` and add the local plugin path, for example:
5128
```ruby
52-
gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
29+
gem "logstash-output-proc", :path => "/your/local/logstash-output-proc"
5330
```
5431
- Install plugin
5532
```sh
5633
bin/plugin install --no-verify
5734
```
35+
- install Ruby Debug
36+
```sh
37+
bin/plugin install logstash-codec-rubydebug
38+
```
5839
- Run Logstash with your plugin
5940
```sh
60-
bin/logstash -e 'filter {awesome {}}'
41+
bin/logstash -e 'input {proc {interval=>60}} output { stdout{ codec=>"rubydebug"}}'
6142
```
6243
At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
6344

@@ -67,20 +48,24 @@ You can use the same **2.1** method to run your plugin in an installed Logstash
6748

6849
- Build your plugin gem
6950
```sh
70-
gem build logstash-filter-awesome.gemspec
51+
gem build logstash-output-proc.gemspec
7152
```
7253
- Install the plugin from the Logstash home
7354
```sh
74-
bin/plugin install /your/local/plugin/logstash-filter-awesome.gem
55+
bin/plugin install /your/local/plugin/logstash-output-proc.gem
7556
```
7657
- Start Logstash and proceed to test the plugin
77-
78-
## Contributing
79-
80-
All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
81-
82-
Programming is not a required skill. Whatever you've seen about open source and maintainers or community members saying "send patches or die" - you will not see that here.
83-
84-
It is more important to the community that you are able to contribute.
85-
86-
For more information about contributing, see the [CONTRIBUTING](https://github.com/elasticsearch/logstash/blob/master/CONTRIBUTING.md) file.
58+
-
59+
# Example Config
60+
```ruby
61+
input {
62+
proc {
63+
interval=>60
64+
}
65+
}
66+
output {
67+
stdout{
68+
codec=>"rubydebug"
69+
}
70+
}
71+
```

lib/logstash/inputs/proc.rb

+145-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def readVmStats(queue)
3232
file = Pathname.new("/proc/vmstat")
3333
lines = file.readlines
3434
lines.each { |line|
35-
@logger.info? && @logger.info("LINE: "+line)
35+
#@logger.info? && @logger.info("LINE: "+line)
3636
m = /(\w+)\s+([\.\d]+)/.match(line)
3737
if (m && m.length >= 3 )
3838
event = LogStash::Event.new("raw"=>line, m[1] => m[2], "file" => file.to_s,"host" => @host, "type" => "vmstats" )
@@ -72,18 +72,158 @@ def readMemInfo(queue)
7272
}
7373
end
7474

75-
#discoverSearch(Pathname.new("/proc"))
75+
def readPidStats(queue)
76+
@logger.info? && @logger.info("in ReadPidStats ")
77+
process = Hash.new
78+
#Loosely based on the GEM ProcTable which was based on the Perl Module ProcTable
79+
Dir.foreach("/proc"){ |file|
80+
next if file =~ /\D/ # Skip non-numeric directories
81+
82+
# Get /proc/<pid>/cmdline information. Strip out embedded nulls.
83+
begin
84+
data = IO.read("/proc/#{file}/cmdline").tr("\000", ' ').strip
85+
process["cmdline"] = data
86+
rescue Exception => ex
87+
next # Process terminated, on to the next process
88+
end
89+
90+
# Get /proc/<pid>/cwd information
91+
process["cwd"] = File.readlink("/proc/#{file}/cwd") rescue nil
92+
93+
# Get /proc/<pid>/environ information. Environment information
94+
# is represented as a Hash, with the environment variable as the
95+
# key and its value as the hash value.
96+
process["environ"] = Hash.new
97+
98+
begin
99+
IO.read("/proc/#{file}/environ").split("\0").each{ |str|
100+
key, value = str.split('=')
101+
process["environ"][key] = value
102+
}
103+
rescue Errno::EACCES, Errno::ESRCH, Errno::ENOENT
104+
# Ignore and move on.
105+
end
106+
107+
# Get /proc/<pid>/exe information
108+
process["exe"] = File.readlink("/proc/#{file}/exe") rescue nil
109+
110+
# Get /proc/<pid>/fd information. File descriptor information
111+
# is represented as a Hash, with the fd as the key, and its
112+
# symlink as the value.
113+
process["fd"] = Hash.new
114+
115+
begin
116+
Dir["/proc/#{file}/fd/*"].foreach { |fd|
117+
process["fd"][File.basename(fd)] = File.readlink(fd) rescue nil
118+
}
119+
rescue
120+
# # Ignore and move on
121+
end
122+
123+
# Get /proc/<pid>/root information
124+
process["root"] = File.readlink("/proc/#{file}/root") rescue nil
125+
126+
# Get /proc/<pid>/stat information
127+
stat = IO.read("/proc/#{file}/stat") rescue next
128+
129+
# Get number of LWP, one directory for each in /proc/<pid>/task/
130+
# Every process has at least one thread, so if we fail to read the task directory, set nlwp to 1.
131+
process["nlwp"] = Dir.glob("/proc/#{file}/task/*").length rescue process["nlwp"] = 1
132+
133+
# Deal with spaces in comm name. Courtesy of Ara Howard.
134+
re = %r/\([^\)]+\)/
135+
comm = stat[re]
136+
comm.tr!(' ', '-')
137+
stat[re] = comm
138+
139+
stat = stat.split
140+
141+
process["pid"] = stat[0].to_i
142+
process["comm"] = stat[1].tr('()','') # Remove parens
143+
process["state"] = stat[2]
144+
process["ppid"] = stat[3].to_i
145+
process["pgrp"] = stat[4].to_i
146+
process["session"] = stat[5].to_i
147+
process["tty_nr"] = stat[6].to_i
148+
process["tpgid"] = stat[7].to_i
149+
process["flags"] = stat[8].to_i
150+
process["minflt"] = stat[9].to_i
151+
process["cminflt"] = stat[10].to_i
152+
process["majflt"] = stat[11].to_i
153+
process["cmajflt"] = stat[12].to_i
154+
process["utime"] = stat[13].to_i
155+
process["stime"] = stat[14].to_i
156+
process["cutime"] = stat[15].to_i
157+
process["cstime"] = stat[16].to_i
158+
process["priority"] = stat[17].to_i
159+
process["nice"] = stat[18].to_i
160+
# Skip 19
161+
process["itrealvalue"] = stat[20].to_i
162+
process["starttime"] = stat[21].to_i
163+
process["vsize"] = stat[22].to_i
164+
process["rss"] = stat[23].to_i
165+
process["rlim"] = stat[24].to_i
166+
process["startcode"] = stat[25].to_i
167+
process["endcode"] = stat[26].to_i
168+
process["startstack"] = stat[27].to_i
169+
process["kstkesp"] = stat[28].to_i
170+
process["kstkeip"] = stat[29].to_i
171+
process["signal"] = stat[30].to_i
172+
process["blocked"] = stat[31].to_i
173+
process["sigignore"] = stat[32].to_i
174+
process["sigcatch"] = stat[33].to_i
175+
process["wchan"] = stat[34].to_i
176+
process["nswap"] = stat[35].to_i
177+
process["cnswap"] = stat[36].to_i
178+
process["exit_signal"] = stat[37].to_i
179+
process["processor"] = stat[38].to_i
180+
process["rt_priority"] = stat[39].to_i
181+
process["policy"] = stat[40].to_i
182+
183+
# Get /proc/<pid>/status information (name, uid, euid, gid, egid)
184+
begin
185+
IO.foreach("/proc/#{file}/status") do |line|
186+
case line
187+
when /Name:\s*?(\w+)/
188+
process["name"] = $1
189+
when /Uid:\s*?(\d+)\s*?(\d+)/
190+
process["uid"] = $1.to_i
191+
process["euid"] = $2.to_i
192+
when /Gid:\s*?(\d+)\s*?(\d+)/
193+
process["gid"] = $1.to_i
194+
process["egid"] = $2.to_i
195+
end
196+
end
197+
rescue Errno::ESRCH, Errno::ENOENT
198+
next
199+
end
200+
201+
# If cmdline is empty use comm instead
202+
process["cmdline"] = process["comm"] if process["cmdline.empty?"]
203+
204+
@logger.info? && @logger.info("output ")
205+
event = LogStash::Event.new( "file" => "/proc" ,"host" => @host, "type" => "pidstats" , "process" => process);
206+
decorate(event)
207+
queue << event
208+
209+
}
210+
211+
212+
end
76213

77214
def run(queue)
78215
loop do
79216
begin
80217
start = Time.now
81218
@logger.info? && @logger.info("Reading VmStats ")
82-
readVmStats(queue)
219+
#readVmStats(queue)
83220
@logger.info? && @logger.info("Reading LoadAverage ")
84-
readLoadAverage(queue)
221+
#readLoadAverage(queue)
85222
@logger.info? && @logger.info("Reading MemInfo ")
86-
readMemInfo(queue)
223+
#readMemInfo(queue)
224+
@logger.info? && @logger.info("Getting list of PID ")
225+
readPidStats(queue);
226+
87227
duration = Time.now - start
88228
@logger.info? && @logger.info("Parsing completed",
89229
:duration => duration,

logstash-input-example.gemspec

-25
This file was deleted.

spec/inputs/example_spec.rb

-1
This file was deleted.

0 commit comments

Comments
 (0)