szaydel
9/26/2019 - 5:07 AM

RFC5424 syslog server and client for testing

package main

import (
	"flag"
	"gopkg.in/mcuadros/go-syslog.v2"
	"io"
	"log"
	"os"
	"time"
)

type logServer struct {
	channel  syslog.LogPartsChannel
	handler  syslog.Handler
	msgCount int64
	config   *config
}

type config struct {
	debug          bool
	host           string
	stats          bool
	statsOnStdErr  bool
	updateInterval time.Duration
}

func main() {

	conf := &config{}
	flag.StringVar(&conf.host, "host", "0.0.0.0:5144", "Address for TCP socket listener as host:port")
	flag.BoolVar(&conf.debug, "debug", false, "Enable debugging")
	flag.BoolVar(&conf.stats, "stats", false, "Enable interval statistics")
	flag.BoolVar(&conf.statsOnStdErr, "statsOnStdErr", false, "Send stats to stderr instead of stdout")
	flag.DurationVar(&conf.updateInterval, "updateInterval", 5*time.Second, "Number of seconds between stat updates, if enabled")

	flag.Parse()

	l := &logServer{
		config: conf,
	}
	l.channel = make(syslog.LogPartsChannel)
	l.handler = syslog.NewChannelHandler(l.channel)

	server := syslog.NewServer()
	server.SetFormat(syslog.RFC5424)
	server.SetHandler(l.handler)
	server.ListenTCP(l.config.host)
	server.Boot()

	if l.config.stats {
		go func(l *logServer) {
			var delta, current, previous int64
			var output io.Writer = os.Stdout
			if l.config.statsOnStdErr {
				output = os.Stderr
			}
			slogger := log.New(output, "", log.Ldate|log.Ltime|log.Lmicroseconds)
			for {
				previous = current
				<-time.After(l.config.updateInterval)
				current = l.msgCount
				delta = current - previous
				slogger.Printf("processed %d msgs since last interval, avg. %04.2f msgs/sec\n", delta,
					float64(delta)/l.config.updateInterval.Seconds())
			}
		}(l)
	}

	go func(l *logServer) {
		for msg := range l.channel {
			if l.config.debug {
				log.Printf("%v", msg)
			}
			l.msgCount++
		}
	}(l)

	server.Wait()
}
package main

import (
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"strings"
	"time"

	"github.com/influxdata/go-syslog/rfc5424"
)

type clientConfig struct {
	appname  string
	hostname string
	msgid    string
	message  string
	host     string
	limit    int64
	forever  bool
	debug    bool
	validate bool
}

func main() {

	pid := fmt.Sprintf("%d", os.Getpid())
	conf := &clientConfig{}

	flag.StringVar(&conf.host, "host", "localhost:5144", "Syslog server address host:port")
	flag.StringVar(&conf.hostname, "hostname", "test-machine", "Hostname to use in generated log messages")
	flag.StringVar(&conf.appname, "appname", os.Args[0], "Application name to use in generated log messages")
	flag.StringVar(&conf.msgid, "msgid", pid, "Message ID field, by default current PID")
	flag.StringVar(&conf.message, "message", "syslog message generated by test client", "Message string to use in generated log messages")
	flag.Int64Var(&conf.limit, "limit", 100, "Number of messages to send if forever is false")
	flag.BoolVar(&conf.validate, "validate", false, "Only validate resulting message, do not send anything")

	flag.Parse()

	// Anything leftover is considered to be parameters, which have this form:
	// parameter_id:key=value one or multiple can be specified, space-separated
	var params = flag.Args()

	var dialer net.Dialer
	var msg = &rfc5424.SyslogMessage{}
	msg.SetTimestamp(time.Now().Format(time.RFC3339))
	msg.SetPriority(165)
	msg.SetVersion(1)
	msg.SetMsgID(conf.msgid)
	msg.SetMessage(conf.message)
	msg.SetAppname(conf.appname)
	msg.SetHostname(conf.hostname)

	if len(params) > 0 {
		for _, p := range params {
			tuple := strings.Split(p, ":")
			if len(tuple) == 2 {
				kvtuple := strings.Split(tuple[1], "=")
				if len(kvtuple) == 2 {
					msg.SetParameter(tuple[0], kvtuple[0], kvtuple[1])
				}
			}
		}
	}

	if conf.validate { // only validate, no sending happens
		msgStr, _ := msg.String()
		if !msg.Valid() {
			log.Printf("Not a valid message: %s", msgStr)
			return
		}
		log.Printf("Valid message: %s", msgStr)
		return
	}

	if conn, err := dialer.Dial("tcp", conf.host); err != nil {
		log.Fatalf("Error: %v", err)
	} else {
		defer conn.Close()
		tcpconn := conn.(*net.TCPConn)
		tcpconn.SetWriteBuffer(4096)
		s, _ := msg.String()

		if !conf.forever {
			var i int64
			for i = 0; i < conf.limit; i++ {
				if _, err := tcpconn.Write([]byte(s + "\n")); err != nil {
					log.Fatalf("Write Error: %v", err)
				}
			}
		} else {
			for {
				if _, err := tcpconn.Write([]byte(s + "\n")); err != nil {
					log.Fatalf("Write Error: %v", err)
				}
			}
		}
	}
}