Documentation
¶
Overview ¶
Package syslog provides a slog handler for transmitting logs locally or over the network using the syslog protocol described in RFC 5424.
Example ¶
package main
import (
"bufio"
"errors"
"fmt"
"io"
"log/slog"
"net"
"net/netip"
"strconv"
"strings"
"time"
"codeberg.org/git-pages/go-syslog"
)
var currentTime = time.Unix(2524608000, 0)
func main() {
address, done := listen()
strptr := func(s string) *string { return &s }
handler, err := syslog.NewHandler(&syslog.HandlerOptions{
Address: address,
Hostname: strptr("miyuko"),
AppName: "catware",
ProcID: strptr("1"),
StructuredDataID: "catware@65535",
})
if err != nil {
panic(err)
}
l := slog.New(handler).WithGroup("cat").With("name", nil)
l = l.With(slog.Group("emotion",
"mood", "inquisitive",
"approachable", true,
))
l = l.With(slog.Group("social",
"accepts-pets", true,
))
l = l.WithGroup("wake")
l.Debug(
"cat waking up",
"waketime", currentTime,
"reason", "external-disturbance",
)
handler.Flush(1 * time.Second)
handler.Close()
<-done
}
func listen() (address string, done chan struct{}) {
laddr := netip.MustParseAddrPort("127.0.0.1:0")
listener, err := net.ListenTCP("tcp", net.TCPAddrFromAddrPort(laddr))
if err != nil {
panic(err)
}
done = make(chan struct{})
go func() {
defer func() { done <- struct{}{} }()
conn, err := listener.Accept()
if err != nil {
panic(err)
}
reader := bufio.NewReader(conn)
for {
byteCountStr, err := reader.ReadString(' ')
if errors.Is(err, io.EOF) {
return
} else if err != nil {
panic(err)
}
byteCount, err := strconv.Atoi(byteCountStr[:len(byteCountStr)-1])
if err != nil {
panic(err)
}
msgBytes := make([]byte, byteCount)
if _, err := io.ReadFull(reader, msgBytes); err != nil {
panic(err)
}
// replace the dynamic timestamp
msg := string(msgBytes)
sep1 := strings.IndexRune(msg, ' ')
sep2 := sep1 + strings.IndexRune(msg[sep1+1:], ' ')
fmt.Printf("%s %s%s\n", msg[:sep1], currentTime.Format(time.RFC3339Nano), msg[sep2+1:])
}
}()
return fmt.Sprintf("tcp://%s", listener.Addr()), done
}
Output: <7>1 2050-01-01T00:00:00Z miyuko catware 1 - [catware@65535 cat.emotion.approachable="true" cat.emotion.mood="inquisitive" cat.name="<nil>" cat.social.accepts-pets="true" cat.wake.reason="external-disturbance" cat.wake.waketime="2050-01-01 00:00:00 +0000 GMT"] cat waking up
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Handler ¶
type Handler interface {
slog.Handler
// Flush waits for all buffered messages to be sent until the passed
// duration has passed.
Flush(timeout time.Duration)
// Close terminates the connection and renders the handler (including ones
// created using WithAttrs and WithGroup) a no-op.
Close()
}
Handler transmits slog.Record values to a syslog daemon. A new value may be constructed using NewHandler.
func NewHandler ¶
func NewHandler(opts *HandlerOptions) (Handler, error)
NewHandler creates a syslog handler connected to a daemon. If the attempt to connect fails, an error is returned. If a connection is lost during the life of the handler, an automatic reconnection attempt is performed in the background. No guarantee is provided as to reliable delivery of every message should network errors occur.
type HandlerOptions ¶
type HandlerOptions struct {
// Address specifies the destination for the log handler. It can be:
//
// - an absolute path to a Unix datagram socket,
//
// - a string of the format `tcp+tls://host:port` that instructs the handler
// to connect to the specified host and port using TLS over TCP,
//
// - a string of the format `tcp://host:port` that instructs the handler
// to connect to the specified host and port using TCP, or
//
// - a string of the format `udp://host:port` that instructs the handler
// to connect to the specified host and port using UDP.
//
// If the field is empty, the default value of "/dev/log" is used.
Address string
// TLSConfig optionally specifies the TLS configuration to be used by the
// Go crypto/tls package for establishing a TLS connection.
TLSConfig *tls.Config
// Level specifies the minimum level below which log records are dropped.
//
// If the field is empty, no filtering is done.
Level slog.Leveler
// BufferSize specifies how many syslog messages should be kept in memory
// in case delivery is lagging behind. If the buffer is full, all incoming
// log records are dropped.
//
// If the field is empty, the default value of 64 is used.
BufferSize int
// Facility specifies the numerical facility value that is joined together
// with a message's severity into the priority value.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.2.1
//
// If the field is empty, the default value of 3 (corresponding to "system
// daemon") is used.
Facility int
// LevelToSeverity specifies a function for mapping slog.Level to the
// numerical severity value that is joined together with the global
// facility value into the message's priority value.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.2.1
//
// If the field is empty, the following mapping is used:
//
// - slog.LevelDebug is mapped to 7;
// - slog.LevelInfo is mapped to 6;
// - slog.LevelWarn is mapped to 4;
// - slog.LevelError is mapped to 3;
// - any other value is mapped to 0 (emergency).
LevelToSeverity func(slog.Level) int
// Hostname specifies the HOSTNAME part of every syslog message produced by
// this handler.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.2.4
//
// If the field is nil, the machine hostname is used as the value,
// otherwise the part is left blank.
Hostname *string
// AppName specifies the APP-NAME part of every syslog message produced by
// this handler. The specification places no restriction on the contents of
// this field.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.2.5
//
// If the field is empty, the part is left blank.
AppName string
// ProcID specifies the PROCID part of every syslog message produced by
// this handler. The specification places no restriction on the contents of
// this field.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.2.6
//
// If the field is nil, the ID of the current process is used as the value,
// otherwise the part is left blank.
ProcID *string
// StructuredDataID specifies the ID to use for every structured data
// element produced by this handler. The specification places certain
// restrictions on the contents of this field.
//
// https://www.rfc-editor.org/rfc/rfc5424.html#section-6.3.2
//
// If the field is empty, all attributes are dropped and no structured data
// is ever transmitted, otherwise the value is used with no validation.
StructuredDataID string
}
HandlerOptions specifies connection parameters and modifies the processing of log records by the handler.