예제 #1
0
파일: gologger.go 프로젝트: ncdc/gologger
// 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)
}
예제 #2
0
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
}
예제 #3
0
파일: syslog.go 프로젝트: nickbruun/coyote
// 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()
		}
	})
}