A simple monitoring solution written in Go (work in progress)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.1 KiB

  1. package check
  2. import (
  3. "fmt"
  4. "git.binarythought.com/cdramey/alrm/check/ping"
  5. "strconv"
  6. "strings"
  7. "time"
  8. )
  9. const (
  10. TK_NONE = iota
  11. TK_COUNT
  12. TK_TIMEOUT
  13. TK_INTERVAL
  14. TK_MAXPACKETLOSS
  15. TK_MAXRTT
  16. TK_MAXAVGRTT
  17. )
  18. type CheckPing struct {
  19. Type string
  20. Address string
  21. Count int
  22. Timeout time.Duration
  23. Interval time.Duration
  24. MaxPacketLoss float64
  25. MaxRTT time.Duration
  26. MaxAvgRTT time.Duration
  27. state int
  28. }
  29. func NewCheckPing(addr string) *CheckPing {
  30. return &CheckPing{
  31. Type: "ping", Address: addr,
  32. Count: 1, Timeout: time.Second * 5,
  33. Interval: time.Second, MaxPacketLoss: 0,
  34. }
  35. }
  36. func (c *CheckPing) Check(debuglvl int) error {
  37. if debuglvl > 0 {
  38. fmt.Printf("Pinging %s .. \n", c.Address)
  39. }
  40. p, err := ping.NewPinger(c.Address)
  41. if err != nil {
  42. return err
  43. }
  44. p.Count = c.Count
  45. p.Timeout = c.Timeout
  46. p.Interval = c.Interval
  47. err = p.Run()
  48. if err != nil {
  49. return err
  50. }
  51. stats := p.Statistics()
  52. if debuglvl > 1 {
  53. for i, r := range stats.Rtts {
  54. fmt.Printf("Ping %d: %s\n", i+1, r)
  55. }
  56. }
  57. if debuglvl > 1 {
  58. fmt.Printf("Packet loss: %.f%%\n", stats.PacketLoss)
  59. fmt.Printf("Max RTT: %s\n", stats.MaxRtt.String())
  60. fmt.Printf("Max Configured RTT: %s\n", c.MaxRTT.String())
  61. fmt.Printf("Average RTT: %s\n", stats.AvgRtt.String())
  62. }
  63. if stats.PacketLoss > c.MaxPacketLoss {
  64. return fmt.Errorf("ping packet loss exceeds max")
  65. }
  66. if c.MaxRTT > 0 && stats.MaxRtt > c.MaxRTT {
  67. return fmt.Errorf("ping rtt exceeds max")
  68. }
  69. if c.MaxAvgRTT > 0 && stats.AvgRtt > c.MaxAvgRTT {
  70. return fmt.Errorf("ping average rtt exceeds max")
  71. }
  72. return nil
  73. }
  74. func (c *CheckPing) Parse(tk string) (bool, error) {
  75. var err error
  76. switch c.state {
  77. case TK_NONE:
  78. switch strings.ToLower(tk) {
  79. case "count":
  80. c.state = TK_COUNT
  81. case "timeout":
  82. c.state = TK_TIMEOUT
  83. case "interval":
  84. c.state = TK_INTERVAL
  85. case "maxpacketloss":
  86. c.state = TK_MAXPACKETLOSS
  87. case "maxrtt":
  88. c.state = TK_MAXRTT
  89. case "maxavgrtt":
  90. c.state = TK_MAXAVGRTT
  91. default:
  92. return false, nil
  93. }
  94. case TK_COUNT:
  95. c.Count, err = strconv.Atoi(tk)
  96. if err != nil {
  97. return false, fmt.Errorf("invalid count \"%s\"", tk)
  98. }
  99. c.state = TK_NONE
  100. case TK_TIMEOUT:
  101. c.Timeout, err = time.ParseDuration(tk)
  102. if err != nil {
  103. return false, fmt.Errorf("invalid timeout \"%s\"", tk)
  104. }
  105. c.state = TK_NONE
  106. case TK_INTERVAL:
  107. c.Interval, err = time.ParseDuration(tk)
  108. if err != nil {
  109. return false, fmt.Errorf("invalid interval \"%s\"", tk)
  110. }
  111. c.state = TK_NONE
  112. case TK_MAXPACKETLOSS:
  113. c.MaxPacketLoss, err = strconv.ParseFloat(tk, 64)
  114. if err != nil {
  115. return false, fmt.Errorf("invalid minpacketloss \"%s\"", tk)
  116. }
  117. c.state = TK_NONE
  118. case TK_MAXRTT:
  119. c.MaxRTT, err = time.ParseDuration(tk)
  120. if err != nil {
  121. return false, fmt.Errorf("invalid maxrtt \"%s\"", tk)
  122. }
  123. c.state = TK_NONE
  124. case TK_MAXAVGRTT:
  125. c.MaxAvgRTT, err = time.ParseDuration(tk)
  126. if err != nil {
  127. return false, fmt.Errorf("invalid maxavgrtt \"%s\"", tk)
  128. }
  129. c.state = TK_NONE
  130. default:
  131. return false, fmt.Errorf("invalid state in check_ping")
  132. }
  133. return true, nil
  134. }