procfs-stats
get detailed information about running process and threads on linux machines from node. more than ps/top/iostat alone
var procfs = ;var ps = ; ps
this only works on linux right now i expect. some things may work on other systems that have some support for procfs.
hope
it would be so cool to have a higher level module that unifies system monitoring scripts in such a way as each os specific implementation can export a common interface like this and we can have xplatform monitoring helpers!! does windows have any external process introspection api?!
API
- procfs(pid)
- ps.io(cb)
- ps.stat(cb)
- ps.statm(cb)
- ps.status(cb)
- ps.env(cb)
- ps.cwd(cb)
- ps.argv(cb)
- ps.fds(cb)
- ps.threads(cb)
- ps.thread(tid)
- procfs.cpu(cb)
- procfs.meminfo(cb)
- procfs.fd(cb)
- procfs.tcp(cb)
- procfs.udp(cb)
- procfs.unix(cb)
- procfs.net(cb)
- procfs.disk(cb)
- procfs.wifi(cb)
- procfs.works()
procfs(pid)
- returns PidStats ps
- PidStats is an object with methods documented blelow with the prefix "ps."
var ps = console;
ps.io(cb)
- from /proc/pid/io
- disk io stats
rchar: '84167' wchar: '15978' syscr: '107' syscw: '47' read_bytes: '0' write_bytes: '12288' cancelled_write_bytes: '0'
ps.stat(cb)
- from /proc/pid/stat
- mixed detailed process stats
- calls back with
pid: '8157' comm: '(node)' state: 'R' ppid: '8156' pgrp: '8150' session: '1703' tty_nr: '34822' tpgid: '8150' flags: '4202496' minflt: '3788' cminflt: '0' majflt: '0' cmajflt: '0' utime: '8' stime: '1' cutime: '0' cstime: '0' priority: '20' nice: '0' num_threads: '6' itrealvalue: '0' starttime: '62912348' vsize: '910020608' rss: '3277' rsslim: '18446744073709551615' startcode: '4194304' endcode: '12964340' startstack: '140736757717536' kstkesp: '140736757701400' kstkeip: '140541704641018' signal: '0' blocked: '0' sigignore: '4096' sigcatch: '16898' wchan: '18446744073709551615' nswap: '0' cnswap: '0' exit_signal: '17' processor: '0' rt_priority: '0' policy: '0' delayacct_blkio_ticks: '0' guest_time: '0' cguest_time: '0'
ps.statm(cb)
- from /proc/pid/statm
- memory stats
- calls back with an object of mem stats
size: '222173' resident: '3342' share: '1284' text: '2142' lib: '0' data: '215399' dt: '0'
ps.status(cb)
- from /proc/pid/status
- mixed process stats with more human friendly formatting
Name: 'node' State: 'S (sleeping)' Tgid: '8157' Pid: '8157' PPid: '8156' TracerPid: '0' Uid: '1000\t1000\t1000\t1000' Gid: '1000\t1000\t1000\t1000' FDSize: '64' Groups: '4 20 24 27 30 46 109 121 1000 ' VmPeak: '954740 kB' VmSize: '888692 kB' VmLck: '0 kB' VmPin: '0 kB' VmHWM: '13464 kB' VmRSS: '13368 kB' VmData: '861452 kB' VmStk: '144 kB' VmExe: '8568 kB' VmLib: '4084 kB' VmPTE: '172 kB' VmSwap: '0 kB' Threads: '6' SigQ: '2/63628' SigPnd: '0000000000000000' ShdPnd: '0000000000000000' SigBlk: '0000000000000000' SigIgn: '0000000000001000' SigCgt: '0000000180004202' CapInh: '0000000000000000' CapPrm: '0000000000000000' CapEff: '0000000000000000' CapBnd: 'ffffffffffffffff' Cpus_allowed: 'ff' Cpus_allowed_list: '0-7' Mems_allowed: '00000000,00000001' Mems_allowed_list: '0' voluntary_ctxt_switches: '39' nonvoluntary_ctxt_switches: '29'
ps.env(cb)
- from /proc/pid/environ
- calls back with the array of environment variables as they were defined when the process started.
... 'MANPATH=:/usr/local/avr/man:/usr/local/avr/man' 'LS_OPTIONS=--color=auto' 'npm_config_git=git' 'npm_config_optional=true' 'EDITOR=vim' 'npm_config_email=soldair@' 'npm_config_json='
ps.cwd(cb)
- from /proc/pid/cwd
- calls back with the working directory of the process when it was started
"/home/soldair/opensource/node-procfs-stats"
ps.argv(cb)
- from /proc/pid/cmdline
- calls back with an array of command line arguments used to run the target process
these are the args for the command node test/pid_argv.js --example
'node' 'test/pid_argv.js' '--example'
ps.fds(cb)
- from /proc/pid/fds
- returns an array of paths to file descriptors in the procfs fds directory for this process.
'/proc/8157/fd/0' '/proc/8157/fd/1' '/proc/8157/fd/10' '/proc/8157/fd/2' '/proc/8157/fd/9'
ps.threads(cb)
- from /proc/pid/tasks
- calls back with an array of the ids/names of each task in the procfs task dir for that pid.
'10299' '10300' '10301' '10302' '10303' '10304'
ps.thread(tid)
- returns PidStats object for taskid
the exported function also has these "static" methods.
var thread = ps;
procfs.cpu(cb)
- from /proc/stat
- calls back with an object like this
cpu: user: '22865094' nice: '8419' system: '41080741' idle: '120838211' iowait: '31250' irq: '13' softirq: '38550' steal: '0' guest: '0' guest_nice: '0' cpu0: user: '5417204' nice: '1535' system: '8517931' idle: '32167970' iowait: '13554' irq: '10' softirq: '33485' steal: '0' guest: '0' guest_nice: '0' ... more cpus intr: '779069953 10 0 0 ... so many zeros ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0' ctxt: '1272813489' btime: '1389119192' processes: '104169' procs_running: '2' procs_blocked: '0' softirq: '387055666 39 219612430 63769 2305517 2468782 39 16208198 61170901 82217 85143774'
procfs.meminfo(cb)
- from /proc/meminfo
- calls back with an object like this
MemTotal: '1019452' MemFree: '44328' MemAvailable: '438588' Buffers: '110444' Cached: '233468' SwapCached: '0' Active: '745748' Inactive: '136524' 'Active(anon)': '538432' 'Inactive(anon)': '64' 'Active(file)': '207316' 'Inactive(file)': '136460' Unevictable: '0' Mlocked: '0' SwapTotal: '0' SwapFree: '0' Dirty: '25788' Writeback: '0' AnonPages: '538432' Mapped: '76296' Shmem: '136' Slab: '75952' SReclaimable: '65052' SUnreclaim: '10900' KernelStack: '2880' PageTables: '5264' NFS_Unstable: '0' Bounce: '0' WritebackTmp: '0' CommitLimit: '509724' Committed_AS: '1070328' VmallocTotal: '34359738367' VmallocUsed: '2528' VmallocChunk: '34359729003' AnonHugePages: '0' HugePages_Total: '0' HugePages_Free: '0' HugePages_Rsvd: '0' HugePages_Surp: '0' Hugepagesize: '2048' DirectMap4k: '22528' DirectMap2M: '1026048'
procfs.fd(fdPath,cb)
- from /proc/pid/fds/fd and /proc/pid/fdinfo
- fdPath is the full path
- calls back with an object
- stat is an fs.Stats object
- full path to file.
- in the case of a socket a string "socket[inode]" or some such will be returned. you can lookup the inode in the net.tcp||udp||unix table for even more info!
fd: '/proc/8306/fd/2' path: '/dev/pts/6' info: pos: '0' flags: '02100002' stat: dev: 11 mode: 8576 nlink: 1 uid: 1000 gid: 5 rdev: 34822 blksize: 1024 ino: 9 size: 0 blocks: 0 atime: Tue Jan 14 2014 17:19:04 GMT- mtime: Tue Jan 14 2014 17:19:04 GMT- ctime: Thu Jan 09 2014 14:28:29 GMT- // if its not a regular file path supported by stat stat is false. path: 'pipe:[19705393]' info: pos: '0' flags: '02000000' stat: false path: 'anon_inode:[eventfd]' info: pos: '0' flags: '02004002' stat: false
procfs.tcp(cb)
- from /proc/net/tcp
- the tcp connection table as an array
- used to count connections/servers and get throughput per active connection
- note "extra" fields that appear after inode in the text file for tcp connections are placed under the _ key which is an object keyed off of the field offset of the value
... sl: '10:' local_address: '127.0.0.1:24599' rem_address: '0.0.0.0:0' st: '0A' tx_queue: '00000000' rx_queue: '00000000' tr: '00' 'tm->when': '00000000' retrnsmt: '00000000' uid: '118' timeout: '0' inode: '12881' _: '12': '1' '13': '0000000000000000' '14': '100' '15': '0' '16': '0' '17': '10' '18': '-1'
procfs.udp(cb)
- from /proc/net/udp
- the udp connection table as an array
- used to count listeners/server and get throughput
sl: '1186:' local_address: '127.0.0.1:52011' rem_address: '0.0.0.0:0' st: '07' tx_queue: '00000000' rx_queue: '00000000' tr: '00' 'tm->when': '00000000' retrnsmt: '00000000' uid: '116' timeout: '0' inode: '12576' ref: '2' pointer: '0000000000000000' drops: '0' ...
procfs.unix(cb)
- from /proc/net/unix
- the unix socket table as an array
Num: '0000000000000000:' RefCount: '00000002' Protocol: '00000000' Flags: '00010000' Type: '0001' St: '01' Inode: '12597' Path: '/var/run/mysqld/mysqld.sock' ...
procfs.net(cb)
- from /proc/net/dev
- calls back with and array of all network devices along with stats
Interface: 'wlan0:' bytes: Receive: '301155854' Transmit: '75294312' packets: Receive: '910966' Transmit: '372927' errs: Receive: '0' Transmit: '0' drop: Receive: '0' Transmit: '0' fifo: Receive: '0' Transmit: '0' frame: Receive: '0' compressed: Receive: '0' Transmit: '0' multicast: Receive: '0' colls: Transmit: '0' carrier: Transmit: '0' Interface: 'eth0:' bytes: Receive: '1202562365' Transmit: '111732378' packets: Receive: '1868620' Transmit: '608933' errs: Receive: '0' Transmit: '0' drop: Receive: '0' Transmit: '0' fifo: Receive: '0' Transmit: '0' frame: Receive: '0' compressed: Receive: '0' Transmit: '0' multicast: Receive: '102222' colls: Transmit: '0' carrier: Transmit: '0'
procfs.disk(cb)
- from /proc/diskstats
- call back format: cb(false, data, buf), where data looks like below
device_number: '1' device_number_minor: '5' device: 'ram5' reads_completed: '0' reads_merged: '0' sectors_read: '0' ms_reading: '0' writes_completed: '0' writes_merged: '0' sectors_written: '0' ms_writing: '0' ios_pending: '0' ms_io: '0' ms_weighted_io: '0' ... many disks or disk like things... device_number: '8' device_number_minor: '0' device: 'sda' reads_completed: '255428' reads_merged: '208748' sectors_read: '9462489' ms_reading: '368008' writes_completed: '1604578' writes_merged: '735675' sectors_written: '36575515' ms_writing: '1680932' ios_pending: '0' ms_io: '410844' ms_weighted_io: '2101936'
procfs.wifi(cb)
- from /proc/net/wireless
- calls back with wifi defices and stats
Interface: 'wlan0:' status: '0000' link: Quality: '51.' level: Quality: '-59.' noise: Quality: '-256' nwid: 'Discarded packets': '0' crypt: 'Discarded packets': '0' frag: 'Discarded packets': '0' retry: 'Discarded packets': '40' misc: 'Discarded packets': '54' beacon: Missed: '0'
procfs.works === true||false
- fs.exists on /proc
- if the procfs can be accessed this value is true
if!procfsworks process