diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-09-13 13:13:40 +0200 |
commit | 5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch) | |
tree | c0650497e988f47be9c6f2324fa692a52dea82e1 /src/pkg/syslog | |
parent | 80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff) | |
download | golang-upstream/60.tar.gz |
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/pkg/syslog')
-rw-r--r-- | src/pkg/syslog/Makefile | 12 | ||||
-rw-r--r-- | src/pkg/syslog/syslog.go | 149 | ||||
-rw-r--r-- | src/pkg/syslog/syslog_test.go | 113 | ||||
-rw-r--r-- | src/pkg/syslog/syslog_unix.go | 31 |
4 files changed, 305 insertions, 0 deletions
diff --git a/src/pkg/syslog/Makefile b/src/pkg/syslog/Makefile new file mode 100644 index 000000000..82baf7253 --- /dev/null +++ b/src/pkg/syslog/Makefile @@ -0,0 +1,12 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include ../../Make.inc + +TARG=syslog +GOFILES=\ + syslog.go\ + syslog_unix.go\ + +include ../../Make.pkg diff --git a/src/pkg/syslog/syslog.go b/src/pkg/syslog/syslog.go new file mode 100644 index 000000000..693337212 --- /dev/null +++ b/src/pkg/syslog/syslog.go @@ -0,0 +1,149 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package syslog provides a simple interface to the system log service. It +// can send messages to the syslog daemon using UNIX domain sockets, UDP, or +// TCP connections. +package syslog + +import ( + "fmt" + "log" + "net" + "os" +) + +type Priority int + +const ( + // From /usr/include/sys/syslog.h. + // These are the same on Linux, BSD, and OS X. + LOG_EMERG Priority = iota + LOG_ALERT + LOG_CRIT + LOG_ERR + LOG_WARNING + LOG_NOTICE + LOG_INFO + LOG_DEBUG +) + +// A Writer is a connection to a syslog server. +type Writer struct { + priority Priority + prefix string + conn serverConn +} + +type serverConn interface { + writeBytes(p Priority, prefix string, b []byte) (int, os.Error) + writeString(p Priority, prefix string, s string) (int, os.Error) + close() os.Error +} + +type netConn struct { + conn net.Conn +} + +// New establishes a new connection to the system log daemon. +// Each write to the returned writer sends a log message with +// the given priority and prefix. +func New(priority Priority, prefix string) (w *Writer, err os.Error) { + return Dial("", "", priority, prefix) +} + +// Dial establishes a connection to a log daemon by connecting +// to address raddr on the network net. +// Each write to the returned writer sends a log message with +// the given priority and prefix. +func Dial(network, raddr string, priority Priority, prefix string) (w *Writer, err os.Error) { + if prefix == "" { + prefix = os.Args[0] + } + var conn serverConn + if network == "" { + conn, err = unixSyslog() + } else { + var c net.Conn + c, err = net.Dial(network, raddr) + conn = netConn{c} + } + return &Writer{priority, prefix, conn}, err +} + +// Write sends a log message to the syslog daemon. +func (w *Writer) Write(b []byte) (int, os.Error) { + if w.priority > LOG_DEBUG || w.priority < LOG_EMERG { + return 0, os.EINVAL + } + return w.conn.writeBytes(w.priority, w.prefix, b) +} + +func (w *Writer) writeString(p Priority, s string) (int, os.Error) { + return w.conn.writeString(p, w.prefix, s) +} + +func (w *Writer) Close() os.Error { return w.conn.close() } + +// Emerg logs a message using the LOG_EMERG priority. +func (w *Writer) Emerg(m string) (err os.Error) { + _, err = w.writeString(LOG_EMERG, m) + return err +} +// Crit logs a message using the LOG_CRIT priority. +func (w *Writer) Crit(m string) (err os.Error) { + _, err = w.writeString(LOG_CRIT, m) + return err +} +// ERR logs a message using the LOG_ERR priority. +func (w *Writer) Err(m string) (err os.Error) { + _, err = w.writeString(LOG_ERR, m) + return err +} + +// Warning logs a message using the LOG_WARNING priority. +func (w *Writer) Warning(m string) (err os.Error) { + _, err = w.writeString(LOG_WARNING, m) + return err +} + +// Notice logs a message using the LOG_NOTICE priority. +func (w *Writer) Notice(m string) (err os.Error) { + _, err = w.writeString(LOG_NOTICE, m) + return err +} +// Info logs a message using the LOG_INFO priority. +func (w *Writer) Info(m string) (err os.Error) { + _, err = w.writeString(LOG_INFO, m) + return err +} +// Debug logs a message using the LOG_DEBUG priority. +func (w *Writer) Debug(m string) (err os.Error) { + _, err = w.writeString(LOG_DEBUG, m) + return err +} + +func (n netConn) writeBytes(p Priority, prefix string, b []byte) (int, os.Error) { + return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, b) +} + +func (n netConn) writeString(p Priority, prefix string, s string) (int, os.Error) { + return fmt.Fprintf(n.conn, "<%d>%s: %s\n", p, prefix, s) +} + +func (n netConn) close() os.Error { + return n.conn.Close() +} + +// NewLogger provides an object that implements the full log.Logger interface, +// but sends messages to Syslog instead; flag is passed as is to Logger; +// priority will be used for all messages sent using this interface. +// All messages are logged with priority p. +func NewLogger(p Priority, flag int) *log.Logger { + s, err := New(p, "") + if err != nil { + return nil + } + return log.New(s, "", flag) +} diff --git a/src/pkg/syslog/syslog_test.go b/src/pkg/syslog/syslog_test.go new file mode 100644 index 000000000..5c0b3e0c4 --- /dev/null +++ b/src/pkg/syslog/syslog_test.go @@ -0,0 +1,113 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +package syslog + +import ( + "io" + "log" + "net" + "testing" +) + +var serverAddr string + +func runSyslog(c net.PacketConn, done chan<- string) { + var buf [4096]byte + var rcvd string = "" + for { + n, _, err := c.ReadFrom(buf[0:]) + if err != nil || n == 0 { + break + } + rcvd += string(buf[0:n]) + } + done <- rcvd +} + +func startServer(done chan<- string) { + c, e := net.ListenPacket("udp", "127.0.0.1:0") + if e != nil { + log.Fatalf("net.ListenPacket failed udp :0 %v", e) + } + serverAddr = c.LocalAddr().String() + c.SetReadTimeout(100e6) // 100ms + go runSyslog(c, done) +} + +func skipNetTest(t *testing.T) bool { + if testing.Short() { + // Depends on syslog daemon running, and sometimes it's not. + t.Logf("skipping syslog test during -short") + return true + } + return false +} + +func TestNew(t *testing.T) { + if skipNetTest(t) { + return + } + s, err := New(LOG_INFO, "") + if err != nil { + t.Fatalf("New() failed: %s", err) + } + // Don't send any messages. + s.Close() +} + +func TestNewLogger(t *testing.T) { + if skipNetTest(t) { + return + } + f := NewLogger(LOG_INFO, 0) + if f == nil { + t.Error("NewLogger() failed") + } +} + +func TestDial(t *testing.T) { + if skipNetTest(t) { + return + } + l, err := Dial("", "", LOG_ERR, "syslog_test") + if err != nil { + t.Fatalf("Dial() failed: %s", err) + } + l.Close() +} + +func TestUDPDial(t *testing.T) { + done := make(chan string) + startServer(done) + l, err := Dial("udp", serverAddr, LOG_INFO, "syslog_test") + if err != nil { + t.Fatalf("syslog.Dial() failed: %s", err) + } + msg := "udp test" + l.Info(msg) + expected := "<6>syslog_test: udp test\n" + rcvd := <-done + if rcvd != expected { + t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected) + } +} + +func TestWrite(t *testing.T) { + done := make(chan string) + startServer(done) + l, err := Dial("udp", serverAddr, LOG_ERR, "syslog_test") + if err != nil { + t.Fatalf("syslog.Dial() failed: %s", err) + } + msg := "write test" + _, err = io.WriteString(l, msg) + if err != nil { + t.Fatalf("WriteString() failed: %s", err) + } + expected := "<3>syslog_test: write test\n" + rcvd := <-done + if rcvd != expected { + t.Fatalf("s.Info() = '%q', but wanted '%q'", rcvd, expected) + } +} diff --git a/src/pkg/syslog/syslog_unix.go b/src/pkg/syslog/syslog_unix.go new file mode 100644 index 000000000..b1516715b --- /dev/null +++ b/src/pkg/syslog/syslog_unix.go @@ -0,0 +1,31 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package syslog + +import ( + "net" + "os" +) + +// unixSyslog opens a connection to the syslog daemon running on the +// local machine using a Unix domain socket. + +func unixSyslog() (conn serverConn, err os.Error) { + logTypes := []string{"unixgram", "unix"} + logPaths := []string{"/dev/log", "/var/run/syslog"} + var raddr string + for _, network := range logTypes { + for _, path := range logPaths { + raddr = path + conn, err := net.Dial(network, raddr) + if err != nil { + continue + } else { + return netConn{conn}, nil + } + } + } + return nil, os.NewError("Unix syslog delivery error") +} |