From 3b1bdfbd2687e81bef85260f9cdfbf617ece3527 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 18 Dec 2016 03:20:47 -0500 Subject: Implement almost all of sd-daemon. BREAKING CHANGES. This does not include the sd_is_* utility functions. BREAKING CHANGES: - The import name is now "sd_daemon" instead of "sd". - The logger interface is now entirely different. - Notify now takes more arguments. --- sd_daemon/log.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 sd_daemon/log.go (limited to 'sd_daemon/log.go') diff --git a/sd_daemon/log.go b/sd_daemon/log.go new file mode 100644 index 0000000..76a735f --- /dev/null +++ b/sd_daemon/log.go @@ -0,0 +1,87 @@ +// Copyright 2015-2016 Luke Shumaker +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:generate make + +package sd_daemon + +import ( + "io" + "os" + "strings" + "sync" + "fmt" + "log/syslog" +) + +// Logger writes ""-prefixed lines to an io.Writer, where N is a +// syslog priority number. It implements mostly the same interface as +// "log/syslog".Writer. +// +// You probably don't need any instance of this other than the +// constant "Log", which uses os.Stderr as the writer. It is +// implemented as a struct rather than a set of functions so that it +// can be passed around as an implementation of an interface. +type Logger struct{ + mu sync.Mutex + out io.Writer +} + +func NewLogger(w io.Writer) Logger { + return Logger{out: w} +} + +// Log is a Logger that use used very similarly to +// "log/syslog".Writer, but writes to os.Stderr under the assumption +// that stderr is forwarded to syslog/journald. +// +// You are encouraged to use stderr unless you have a good reason to +// talk to syslog or journald directly. +var Log = Logger{out: os.Stderr} + +// WriteString writes a message with the specified priority to the +// log. +func (l Logger) WriteBytes(level syslog.Priority, msg []byte) (n int, err error) { + return l.WriteString(level, string(msg)) +} + +// WriteString writes a message with the specified priority to the +// log. +func (l Logger) WriteString(level syslog.Priority, msg string) (n int, err error) { + l.mu.Lock() + defer l.mu.Unlock() + + // BUG(lukeshu): Logger uses high-level string functions that + // do many small allocations, making it insuitable for in + // tight loops; it should use a buffer property to be + // essentially zero-allocation. + prefix := fmt.Sprintf("<%d>", level) + buf := prefix + strings.Replace(strings.TrimSuffix(msg, "\n"), "\n", "\n"+prefix, -1) + return io.WriteString(l.out, buf) +} + +type loggerWriter struct { + log Logger + level syslog.Priority +} + +func (lw loggerWriter) Write(p []byte) (n int, err error) { + return lw.log.WriteBytes(lw.level, p) +} + +// Writer returns an io.Writer that writes messages with the specified +// priority to the log. +func (l Logger) Writer(level syslog.Priority) io.Writer { + return loggerWriter{log: l, level: level} +} -- cgit v1.2.3