1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package log2021import (22 "fmt"23 "io"24 "os"25 "strings"26 "time"27)2829type wcOutput struct {30 timestamps bool31 wc io.WriteCloser32}3334func (w wcOutput) Write(stamp time.Time, debug bool, msg string) {35 builder := strings.Builder{}36 if w.timestamps {37 builder.WriteString(stamp.UTC().Format("2006-01-02T15:04:05.000Z "))38 }39 if debug {40 builder.WriteString("[debug] ")41 }42 builder.WriteString(msg)43 builder.WriteRune('\n')44 if _, err := io.WriteString(w.wc, builder.String()); err != nil {45 fmt.Fprintf(os.Stderr, "!!! Failed to write message to log: %v\n", err)46 }47}4849func (w wcOutput) Close() error {50 return w.wc.Close()51}5253// WriteCloserOutput returns a log.Output implementation that54// will write formatted messages to the provided io.Writer.55//56// Closing returned log.Output object will close the underlying57// io.WriteCloser.58//59// Written messages will include timestamp formatted with millisecond60// precision and [debug] prefix for debug messages.61// If timestamps argument is false, timestamps will not be added.62//63// Returned log.Output does not provide its own serialization64// so goroutine-safety depends on the io.Writer. Most operating65// systems have atomic (read: thread-safe) implementations for66// stream I/O, so it should be safe to use WriterOutput with os.File.67func WriteCloserOutput(wc io.WriteCloser, timestamps bool) Output {68 return wcOutput{timestamps, wc}69}7071type nopCloser struct {72 io.Writer73}7475func (nc nopCloser) Close() error {76 return nil77}7879// WriterOutput returns a log.Output implementation that80// will write formatted messages to the provided io.Writer.81//82// Closing returned log.Output object will have no effect on the83// underlying io.Writer.84//85// Written messages will include timestamp formatted with millisecond86// precision and [debug] prefix for debug messages.87// If timestamps argument is false, timestamps will not be added.88//89// Returned log.Output does not provide its own serialization90// so goroutine-safety depends on the io.Writer. Most operating91// systems have atomic (read: thread-safe) implementations for92// stream I/O, so it should be safe to use WriterOutput with os.File.93func WriterOutput(w io.Writer, timestamps bool) Output {94 return wcOutput{timestamps, nopCloser{os.Stderr}}95}