Beispiel #1
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
}
Beispiel #2
0
// 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()
		}
	})
}
Beispiel #3
0
func main() {
	flag.Parse()

	// Set logTarget
	if *logTarget == "" {
		logger = log.New(os.Stdout, "LOG   ", log.LstdFlags)
		debugLogger = log.New(os.Stdout, "DEBUG ", log.LstdFlags)
	} else {
		u, err := url.Parse(*logTarget)
		if err != nil {
			log.Fatalln("fatal: unable to parse logtarget url", err)
		}
		query, _ := url.ParseQuery(u.RawQuery)

		switch {
		case (u.Scheme == "" || u.Scheme == "file") && u.Path != "":

			var logFile *os.File
			fileMode := os.FileMode(*logPermission)
			_, err = os.Stat(u.Path)
			if os.IsNotExist(err) {
				logFile, err = os.Create(u.Path)
				if err != nil {
					log.Fatalln("fatal: unable to create log target", err)
				}

				err = os.Chmod(u.Path, fileMode)
				if err != nil {
					log.Fatalln("fatal: unable to set file permissions", err)
				}
			} else {
				logFile, err = os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND, fileMode)
				if err != nil {
					log.Fatalln("fatal: unable to open log target", err)
				}
			}
			defer logFile.Close()
			logTargetWriter = io.Writer(logFile)

			// Check if logTarget is writable
			_, err = logTargetWriter.Write([]byte(""))
			if err != nil {
				log.Fatalln("fatal: unable to write to log target")
			}

		case strings.HasPrefix(u.Scheme, "syslog"):
			var syslogLogger *syslog.Writer
			var tag string
			priority := int(syslog.LOG_NOTICE | syslog.LOG_LOCAL0)

			if query["priority"][0] != "" {
				priority, err = strconv.Atoi(query["priority"][0])
				if err != nil {
					log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err)
				}
			}

			if query["tag"][0] != "" {
				tag = query["tag"][0]
			}

			if u.Host == "" {
				syslogLogger, err = syslog.New(syslog.Priority(priority), tag)
				if err != nil {
					log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err)
				}
			} else {
				schemeParts := strings.Split(u.Scheme, "+")
				network := "tcp"
				if len(schemeParts) > 1 {
					network = schemeParts[1]
				}

				_, _, err := net.SplitHostPort(u.Host)
				if err != nil {
					u.Host = u.Host + ":514"
				}

				syslogLogger, err = syslog.Dial(network, u.Host, syslog.Priority(priority), tag)
				if err != nil {
					log.Fatalln("fatal: unable to connect to syslog", *logTarget, "err:", err)
				}
			}
			defer syslogLogger.Close()
			logTargetWriter = io.Writer(syslogLogger)

		default:
			log.Fatalln("fatal: no valid schema:", *logTarget)
		}

		logger = log.New(logTargetWriter, "LOG   ", log.LstdFlags)
		debugLogger = log.New(logTargetWriter, "DEBUG ", log.LstdFlags)
	}

	// Set log-function based on log level
	switch *logLevel {
	case 0:
		logf = emptyLogf
	case 2:
		debugf = debugLogf
	default:
	}

	// Write example log lines
	logf("log output %s, %d", "string1", 10)
	debugf("debug output %s, %d", "string1", 10)
}