// Reads from a queue and writes to writer until the queue channel // is closed. Signals to a WaitGroup when done. func write(queue chan []byte, writer *syslog.Writer, wg *sync.WaitGroup) { defer wg.Done() fmt.Println("writer started") var totalWrites int64 = 0 var cumuWriteDuration int64 = 0 for line := range queue { start := time.Now() writer.Write(line) //var _ = line totalWrites++ cumuWriteDuration += time.Now().Sub(start).Nanoseconds() / 1000 } fmt.Println("writer shutting down") avgWriteDuration := float64(cumuWriteDuration) / float64(totalWrites) fmt.Println("total lines written: ", totalWrites) fmt.Printf("avg write duration (us): %.3v\n", avgWriteDuration) }
func (this *Server) StartDrainer(address string, filter EntryFilter) *Drainer { c := make(chan Entry) listener := &Listener{ Channel: c, Filter: filter, LastEntry: time.Now(), } this.AddListener <- listener drainer := &Drainer{ Address: address, Filter: filter, server: this, listener: listener, terminate: make(chan bool, 1), } go func() { var w *syslog.Writer var err error for entry := range Throttle(c, 100) { for { // If we terminated give up select { case <-drainer.terminate: return default: } // Connect if w == nil { log.Printf("connecting to syslog://%v\n", address) w, err = syslog.Dial("tcp", address, syslog.LOG_INFO, "") if err != nil { w = nil time.Sleep(time.Second * 5) continue } } // Send the message _, err = w.Write(entry.Line()) if err != nil { w.Close() w = nil time.Sleep(time.Second * 5) continue } // Successfully sent the message so break break } } }() return drainer }
// New syslog TCP output. // // If the network is empty, the local syslog daemon will be used. func NewSyslogOutput(network, raddr string, priority syslog.Priority, tag string) (Output, error) { desc := "syslog" if network != "" { desc = fmt.Sprintf("syslog at %s://%s", network, raddr) } failing := false var w *syslog.Writer dial := func() error { var err error w, err = syslog.Dial(network, raddr, priority, tag) if err != nil { if !failing { failing = true fmt.Fprintf(os.Stderr, "Failed to connect to %s: %s\n", desc, err) } w = nil return err } else if failing { fmt.Fprintf(os.Stderr, "Connected to %s\n", desc) failing = false } return nil } return newDrainingOutput(10240, func(lines [][]byte) error { // Connect if a connection does not already exist. if w == nil { if err := dial(); err != nil { return err } } // Send data. first := true for _, l := range lines { if len(l) == 0 { continue } n, err := w.Write(l) // If the first send fails without sending any data, let's attempt // to reconnect. if first { first = false if n == 0 && err != nil { fmt.Fprintf(os.Stderr, "Failed to send data to %s: %s - reconnecting...\n", desc, err) if err = dial(); err != nil { return err } } } // Update the payload and handle any errors. if err != nil { fmt.Fprintf(os.Stderr, "Failed to send data to %s: %s\n", desc, err) failing = true w.Close() w = nil return err } } return nil }, func() { if w != nil { w.Close() } }) }