Skip to content

Instantly share code, notes, and snippets.

@kylebrandt
Created March 20, 2015 14:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kylebrandt/b2906d990d0e762ad87e to your computer and use it in GitHub Desktop.
Save kylebrandt/b2906d990d0e762ad87e to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/json"
"flag"
"io"
"log"
"net"
"os"
"strings"
"time"
)
type HealthCheck struct {
LogType string `json:"log_type"`
Time time.Time `json:"time"`
Message string `json:"message"`
}
// Send a health check ping to logstash via TCP
func SendCheck(h HealthCheck) error {
b, err := json.Marshal(h)
buf := bytes.NewBuffer(b)
buf.WriteRune('\n')
if err != nil {
return err
}
conn, err := net.DialTimeout("tcp", "127.0.0.1:9999", time.Second*5)
if err != nil {
return err
}
_, err = conn.Write(buf.Bytes())
if err != nil {
return err
}
return nil
}
// Tail the stdout log file, and return the latest @timestamp
func CheckLog(logfile string, offset int64) (time.Time, error) {
var t time.Time
f, err := os.Open(logfile)
if err != nil {
return t, err
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return t, err
}
s := stat.Size()
if s < offset {
offset = s
}
buf := make([]byte, offset)
if _, err := f.ReadAt(buf, s-offset); err != nil && err != io.EOF {
return t, err
}
for _, line := range strings.Split(string(buf[:]), "\n") {
if strings.Contains(line, "@timestamp") {
f := strings.Fields(line)
if len(f) != 3 {
continue
}
ts := strings.Replace(strings.Replace(f[2], `"`, "", -1), ",", "", -1)
pt, err := time.Parse(time.RFC3339Nano, ts)
if err != nil {
return t, err
}
if t.Before(pt) {
t = pt
}
}
}
return t, nil
}
var (
flagSeek = flag.Int64("s", 10000, "Number of lines to lookback in the log file.")
flagThreshold = flag.Int64("t", 30, "Threshold for the age of the most recent timestamp in number of seconds.")
flagWait = flag.Int64("w", 20, "How many seconds to wait after submitting a request.")
)
func main() {
flag.Parse()
n := HealthCheck{LogType: "health-check", Message: "vrrp health check", Time: time.Now().UTC()}
err := SendCheck(n)
if err != nil {
log.Fatal(err)
}
time.Sleep(time.Duration(*flagWait) * time.Second)
t, err := CheckLog("/var/log/logstash/logstash.stdout", *flagSeek)
if err != nil {
log.Fatal(err)
}
if time.Now().UTC().Sub(t) > time.Second*time.Duration(*flagThreshold) {
log.Fatal("No new timestamps, newest is ", t.UTC())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment