This commit is contained in:
insanity 2017-10-24 16:09:17 +09:00
parent 2e31ae10eb
commit 806f406ee0
11 changed files with 311 additions and 163 deletions

View File

@ -2,6 +2,7 @@ package crawler
import (
"bytes"
"encoding/json"
"git.loafle.net/overflow/ssh_crawler/ssh"
"git.loafle.net/overflow/ssh_crawler/stat"
)
@ -29,33 +30,43 @@ func (c *Crawler) connectSSH(ip, port, user, pw string) error {
return nil
}
func (c *Crawler) CPUStat(ch chan interface{}) {
func (c *Crawler) CPUStat(ch chan interface{}, keys []string) {
go func() {
cpu := &stat.CPUStat{}
b, err := c.sshCli.RunCommand(cpu.Command())
if err != nil {
ch <- err
}
res, err := cpu.Parse(bytes.NewReader(b))
res, err := cpu.Read(bytes.NewReader(b), keys)
if err != nil {
ch <- err
}
ch <- res
jsonData, err := json.Marshal(res)
if err != nil {
ch <- err
}
ch <- string(jsonData)
close(ch)
}()
}
func (c *Crawler) MemStat(ch chan interface{}) {
func (c *Crawler) MemStat(ch chan interface{}, keys []string) {
go func() {
mem := &stat.MemStat{}
b, err := c.sshCli.RunCommand(mem.Command())
if err != nil {
ch <- err
}
res, err := mem.Parse(bytes.NewReader(b))
res, err := mem.Read(bytes.NewReader(b), keys)
if err != nil {
ch <- err
}
ch <- res
jsonData, err := json.Marshal(res)
if err != nil {
ch <- err
}
ch <- string(jsonData)
close(ch)
}()
}
@ -73,6 +84,7 @@ func (c *Crawler) DiskIOStat(ch chan interface{}) {
ch <- err
}
ch <- res
close(ch)
}()
}
@ -88,6 +100,7 @@ func (c *Crawler) DiskFreeStat(ch chan interface{}) {
ch <- err
}
ch <- res
close(ch)
}()
}

93
main.go
View File

@ -3,11 +3,9 @@ package main
import (
"fmt"
"git.loafle.net/overflow/ssh_crawler/crawler"
"runtime"
)
func main() {
runtime.GOMAXPROCS(4)
const ip = "192.168.1.15"
const port = "22"
@ -19,45 +17,70 @@ func main() {
fmt.Println(err)
}
//CPU
//사용자가 cpu.usage.total을 선택했을 때의 수집항목들 (..출력 항목도 포함시켜서 계산결과 리턴해야하나?)
cpukeys := []string{
"cpu.usage.sum",
"cpu.usage.user",
"cpu.usage.system",
"cpu.usage.nice",
"cpu.usage.idle",
"cpu.usage.iowait",
"cpu.usage.irq",
"cpu.usage.softirq",
"cpu.usage.steal",
"cpu.usage.guest",
"cpu.usage.guestNice",
}
cpuCh := make(chan interface{})
cr.CPUStat(cpuCh)
cr.CPUStat(cpuCh, cpukeys)
fmt.Println(<-cpuCh)
close(cpuCh)
//Memory
memkeys := []string {
"mem.usage.total",
"mem.usage.free",
"mem.usage.available",
"mem.usage.buffers",
"mem.usage.cached",
"mem.swap.usage.total",
"mem.swap.usage.free",
"mem.swap.usage.cached",
}
memCh := make(chan interface{})
cr.MemStat(memCh)
cr.MemStat(memCh, memkeys)
fmt.Println(<-memCh)
close(memCh)
//Disk IO
diskioCh := make(chan interface{})
cr.DiskIOStat(diskioCh)
fmt.Println(<-diskioCh)
close(diskioCh)
//memCh := make(chan interface{})
//cr.MemStat(memCh, keys)
//fmt.Println(<-memCh)
//Disk Free
diskFreeCh := make(chan interface{})
cr.DiskFreeStat(diskFreeCh)
fmt.Println(<-diskFreeCh)
close(diskFreeCh)
//Network
netCh := make(chan interface{})
cr.NetworkStat(netCh)
fmt.Println(<-netCh)
close(netCh)
//Load Avg.
loadCh := make(chan interface{})
cr.LoadAvgStat(loadCh)
fmt.Println(<-loadCh)
close(loadCh)
//Process
psCh := make(chan interface{})
cr.ProcessStat(psCh)
fmt.Println(<-psCh)
close(psCh)
////Memory
//memCh := make(chan interface{})
//cr.MemStat(memCh)
//fmt.Println(<-memCh)
//
////Disk IO
//diskioCh := make(chan interface{})
//cr.DiskIOStat(diskioCh)
//fmt.Println(<-diskioCh)
//
////Disk Free
//diskFreeCh := make(chan interface{})
//cr.DiskFreeStat(diskFreeCh)
//fmt.Println(<-diskFreeCh)
//
////Network
//netCh := make(chan interface{})
//cr.NetworkStat(netCh)
//fmt.Println(<-netCh)
//
////Load Avg.
//loadCh := make(chan interface{})
//cr.LoadAvgStat(loadCh)
//fmt.Println(<-loadCh)
//
////Process
//psCh := make(chan interface{})
//cr.ProcessStat(psCh)
//fmt.Println(<-psCh)
}

View File

@ -4,29 +4,31 @@ import (
"bufio"
"io"
"strings"
"git.loafle.net/overflow/ssh_crawler/util"
)
type CPUStat struct {
device,
user,
nice,
system,
idle,
iowait,
irq,
softIrq,
steal, // (over 2.6.11)
guest, // (over 2.6.24)
guestNice string //(over 2.6.33)
Device,
User,
Nice,
System,
Idle,
Iowait,
Irq,
SoftIrq,
Steal, // (over 2.6.11)
Guest, // (over 2.6.24)
GuestNice, //(over 2.6.33)
Sum float64
}
func (cpu CPUStat) Command() string {
return "cat /proc/stat"
}
func (cpu CPUStat) Parse(r io.Reader) (*[]CPUStat, error) {
func (cpu CPUStat) Read(r io.Reader, keys []string) (*map[string]string, error) {
var (
CPUStats = []CPUStat{}
stats = []CPUStat{}
scanner = bufio.NewScanner(r)
)
@ -37,31 +39,79 @@ func (cpu CPUStat) Parse(r io.Reader) (*[]CPUStat, error) {
continue
}
steal, guest, guestNice := "", "", ""
var steal, guest, guestNice float64
if len(parts) > 8 {
steal = parts[8]
steal = util.StringToFloat64(parts[8])
}
if len(parts) > 9 {
guest = parts[9]
guest = util.StringToFloat64(parts[9])
}
if len(parts) > 10 {
guestNice = parts[10]
guestNice = util.StringToFloat64(parts[10])
}
CPUStats = append(CPUStats, CPUStat{
device: parts[0],
user: parts[1],
nice: parts[2],
system: parts[3],
idle: parts[4],
iowait: parts[5],
irq: parts[6],
softIrq: parts[7],
steal: steal,
guest: guest,
guestNice: guestNice,
stats = append(stats, CPUStat{
Device: util.StringToFloat64(parts[0]),
User: util.StringToFloat64(parts[1]),
Nice: util.StringToFloat64(parts[2]),
System: util.StringToFloat64(parts[3]),
Idle: util.StringToFloat64(parts[4]),
Iowait: util.StringToFloat64(parts[5]),
Irq: util.StringToFloat64(parts[6]),
SoftIrq: util.StringToFloat64(parts[7]),
Steal: steal,
Guest: guest,
GuestNice: guestNice,
})
}
return &CPUStats, scanner.Err()
res, err :=cpu.parse(keys, stats)
if err != nil {
return nil, err
}
return &res, scanner.Err()
}
func (cpu CPUStat) parse(keys []string, data []CPUStat) (map[string]string, error) {
resMap := make(map[string]string)
for _, key := range keys {
resMap[key] = cpu.calc(key, data[0])
}
return resMap, nil
}
func (cpu CPUStat) calc(key string, d CPUStat) string {
var value float64 = 0
sum := d.User + d.Nice + d.System + d.Idle + d.Iowait + d.Irq + d.SoftIrq + d.Steal + d.Guest + d.GuestNice
switch key {
case "cpu.usage.sum":
value = sum
case "cpu.usage.user":
value = d.User / sum * 100
case "cpu.usage.nice":
value = d.Nice / sum * 100
case "cpu.usage.system":
value = d.System / sum * 100
case "cpu.usage.idle":
value = d.Idle / sum * 100
case "cpu.usage.iowait":
value = d.Iowait / sum * 100
case "cpu.usage.irq":
value = d.Irq / sum * 100
case "cpu.usage.softirq":
value = d.SoftIrq / sum * 100
case "cpu.usage.steal":
value = d.Steal / sum * 100
case "cpu.usage.guest":
value = d.Guest / sum * 100
case "cpu.usage.gnice":
value = d.GuestNice / sum * 100
default:
}
return util.Float64ToString(value)
}

View File

@ -7,12 +7,12 @@ import (
)
type DiskFreeStat struct {
filesystem,
size,
used,
available,
usePerc,
mountedOn string
Filesystem,
Size,
Used,
Available,
UsePerc,
MountedOn string
}
func (diskFree DiskFreeStat) Command() string {
@ -28,12 +28,12 @@ func (diskio DiskFreeStat) Parse(r io.Reader) (*[]DiskFreeStat, error) {
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
stats = append(stats, DiskFreeStat{
filesystem: parts[0],
size: parts[1],
used: parts[2],
available: parts[3],
usePerc: removePercUnit(parts[4]),
mountedOn: parts[5],
Filesystem: parts[0],
Size: parts[1],
Used: parts[2],
Available: parts[3],
UsePerc: removePercUnit(parts[4]),
MountedOn: parts[5],
})
}

View File

@ -8,18 +8,18 @@ import (
)
type DiskIOStat struct {
device,
readCompleted,
readMerged,
sectorRead,
timeSpentReading,
writesCompleted,
writesMerged,
sectorsWritten,
timeSpentWriting,
ioInProg,
timeSpentIO,
weightedTimeSpentIO string
Device,
ReadCompleted,
ReadMerged,
SectorRead,
TimeSpentReading,
WritesCompleted,
WritesMerged,
SectorsWritten,
TimeSpentWriting,
IoInProg,
TimeSpentIO,
WeightedTimeSpentIO string
}
func (diskio DiskIOStat) Command() string {
@ -42,18 +42,18 @@ func (diskio DiskIOStat) Parse(r io.Reader) (*[]DiskIOStat, error) {
continue
}
stats = append(stats, DiskIOStat{
device: deviceName,
readCompleted: parts[3],
readMerged: parts[4],
sectorRead: parts[5],
timeSpentReading: parts[6],
writesCompleted: parts[7],
writesMerged: parts[8],
sectorsWritten: parts[9],
timeSpentWriting: parts[10],
ioInProg: parts[11],
timeSpentIO: parts[12],
weightedTimeSpentIO: parts[13],
Device: deviceName,
ReadCompleted: parts[3],
ReadMerged: parts[4],
SectorRead: parts[5],
TimeSpentReading: parts[6],
WritesCompleted: parts[7],
WritesMerged: parts[8],
SectorsWritten: parts[9],
TimeSpentWriting: parts[10],
IoInProg: parts[11],
TimeSpentIO: parts[12],
WeightedTimeSpentIO: parts[13],
})
}

View File

@ -7,9 +7,9 @@ import (
)
type LoadAvg struct {
min1,
min5,
min15 string
Min1,
Min5,
Min15 string
}
func (loadavg LoadAvg) Command() string {
@ -25,9 +25,9 @@ func (loadavg LoadAvg) Parse(r io.Reader) (*LoadAvg, error) {
for scanner.Scan() {
line := scanner.Text()
parts := strings.Fields(line)
load.min1 = parts[0]
load.min5 = parts[1]
load.min15 = parts[2]
load.Min1 = parts[0]
load.Min5 = parts[1]
load.Min15 = parts[2]
}
return &load, scanner.Err()
}

View File

@ -13,9 +13,9 @@ func (mem MemStat) Command() string {
return "cat /proc/meminfo"
}
func (mem MemStat) Parse(r io.Reader) (*map[string]string, error) {
func (mem MemStat) Read(r io.Reader, keys []string) (*map[string]string, error) {
var (
memInfo = map[string]string{}
stats = map[string]string{}
scanner = bufio.NewScanner(r)
)
@ -23,8 +23,43 @@ func (mem MemStat) Parse(r io.Reader) (*map[string]string, error) {
line := scanner.Text()
parts := strings.Fields(line)
key := parts[0][:len(parts[0])-1]
memInfo[key] = parts[1]
stats[key] = parts[1]
}
return &memInfo, scanner.Err()
res, err := mem.parse(keys, stats)
if err != nil {
return nil, err
}
return &res, scanner.Err()
}
func (mem MemStat) parse(keys []string, data map[string]string) (map[string]string, error) {
resMap := make(map[string]string)
for _, key := range keys {
switch key {
case "mem.usage.total":
resMap[key] = data["MemTotal"]
case "mem.usage.free":
resMap[key] = data["MemFree"]
case "mem.usage.available":
resMap[key] = data["MemAvailable"]
case "mem.usage.buffers":
resMap[key] = data["Buffers"]
case "mem.usage.cached":
resMap[key] = data["Cached"]
case "mem.swap.usage.total":
resMap[key] = data["SwapTotal"]
case "mem.swap.usage.free":
resMap[key] = data["SwapFree"]
case "mem.swap.usage.cached":
resMap[key] = data["SwapCached"]
default:
}
}
return resMap, nil
}

View File

@ -9,23 +9,23 @@ import (
)
type NetDevStat struct {
iface,
recvByte,
recvPacket,
recvErr,
recvDrop,
recvFifo,
recvFrame,
recvCompressed,
recvMulticast,
transByte,
transPacket,
transErr,
transDrop,
transFifo,
transFrame,
transCompressed,
transMulticast string
Iface,
RecvByte,
RecvPacket,
RecvErr,
RecvDrop,
RecvFifo,
RecvFrame,
RecvCompressed,
RecvMulticast,
TransByte,
TransPacket,
TransErr,
TransDrop,
TransFifo,
TransFrame,
TransCompressed,
TransMulticast string
}
func (net *NetDevStat) Command() string {
@ -56,23 +56,23 @@ func (net *NetDevStat) Parse(r io.Reader) (*[]NetDevStat, error) {
dev := parts[0][:len(parts[0])]
netDevStats = append(netDevStats, NetDevStat{
iface: dev,
recvByte: parts[1],
recvPacket: parts[2],
recvErr: parts[3],
recvDrop: parts[4],
recvFifo: parts[5],
recvFrame: parts[6],
recvCompressed: parts[7],
recvMulticast: parts[8],
transByte: parts[9],
transPacket: parts[10],
transErr: parts[11],
transDrop: parts[12],
transFifo: parts[13],
transFrame: parts[14],
transCompressed: parts[15],
transMulticast: parts[16],
Iface: dev,
RecvByte: parts[1],
RecvPacket: parts[2],
RecvErr: parts[3],
RecvDrop: parts[4],
RecvFifo: parts[5],
RecvFrame: parts[6],
RecvCompressed: parts[7],
RecvMulticast: parts[8],
TransByte: parts[9],
TransPacket: parts[10],
TransErr: parts[11],
TransDrop: parts[12],
TransFifo: parts[13],
TransFrame: parts[14],
TransCompressed: parts[15],
TransMulticast: parts[16],
})
}
return &netDevStats, scanner.Err()

View File

@ -7,12 +7,12 @@ import (
)
type ProcessStat struct {
user,
pid,
size,
pcpu,
pmem,
cmd string
User,
Pid,
Size,
Pcpu,
Pmem,
Cmd string
}
func (ps *ProcessStat) Command() string {
@ -29,12 +29,12 @@ func (ps *ProcessStat) Parse(r io.Reader) (*[]ProcessStat, error) {
line := scanner.Text()
parts := strings.Fields(line)
psStats = append(psStats, ProcessStat{
user: parts[0],
pid: parts[1],
size: parts[2],
pcpu: parts[3],
pmem: parts[4],
cmd: parts[5],
User: parts[0],
Pid: parts[1],
Size: parts[2],
Pcpu: parts[3],
Pmem: parts[4],
Cmd: parts[5],
})
}
return &psStats, scanner.Err()

1
stat/uptime.go Normal file
View File

@ -0,0 +1 @@
package stat

26
util/util.go Normal file
View File

@ -0,0 +1,26 @@
package util
import (
"fmt"
"math"
"strconv"
)
func StringToFloat64(str string) float64 {
n, _ := strconv.ParseFloat(str, 64)
return n
}
func Float64ToString(num float64) string {
return fmt.Sprintf("%v", toFixed(num, 2))
}
func round(num float64) int {
return int(num + math.Copysign(0.5, num))
}
func toFixed(num float64, precision int) float64 {
output := math.Pow(10, float64(precision))
return float64(round(num*output)) / output
}