package main import ( "flag" "fmt" "log" "net" "net/url" "os" "os/signal" "strconv" "time" "git.lattuga.net/boyska/circolog/formatter" "github.com/gorilla/websocket" "gopkg.in/mcuadros/go-syslog.v2/format" "gopkg.in/mgo.v2/bson" ) func main() { addr := flag.String("addr", "localhost:9080", "http service address") querySocket := flag.String("socket", "", "Path to a unix domain socket for the HTTP server") backlogLimit := flag.Int("n", -1, "Limit the backlog length, defaults to no limit (-1)") flag.Parse() interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) var d *websocket.Dialer u := url.URL{Scheme: "ws", Host: *addr, // ignored in case of -socket; see the Dialer below Path: "/ws", } q := u.Query() q.Set("fmt", "bson") if *backlogLimit >= 0 { q.Set("l", strconv.Itoa(*backlogLimit)) } u.RawQuery = q.Encode() if *querySocket != "" { d = &websocket.Dialer{ NetDial: func(network, addr string) (net.Conn, error) { return net.Dial("unix", *querySocket) }, HandshakeTimeout: 45 * time.Second, // same as DefaultDialer } log.Printf("connecting to %s", *querySocket) } else { d = websocket.DefaultDialer log.Printf("connecting to %s", *addr) } c, _, err := d.Dial(u.String(), nil) if err != nil { log.Fatal("dial:", err) } defer c.Close() log.Println("connected!", u.String()) done := make(chan struct{}) go func() { defer close(done) for { _, serialized, err := c.ReadMessage() if err != nil { log.Println("close:", err) return } var parsed format.LogParts if err := bson.Unmarshal(serialized, &parsed); err != nil { log.Println("invalid YAML", err) continue } if err := formatter.WriteFormatted(os.Stdout, formatter.FormatSyslog, parsed); err != nil { log.Println("error printing", err) } fmt.Println() } }() for { select { case <-done: return case <-interrupt: log.Println("interrupt") // Cleanly close the connection by sending a close message and then waiting (with timeout) for the // server to close the connection. err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) if err != nil { log.Println("write close:", err) return } select { case <-done: log.Println("Successfully close") case <-time.After(1 * time.Second): log.Println("Forced close") } return } } }