maddy

Fork https://github.com/foxcpp/maddy

git clone git://git.lin.moe/go/maddy.git

 1/*
 2Maddy Mail Server - Composable all-in-one email server.
 3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors
 4
 5This program is free software: you can redistribute it and/or modify
 6it under the terms of the GNU General Public License as published by
 7the Free Software Foundation, either version 3 of the License, or
 8(at your option) any later version.
 9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19package log
20
21import (
22	"fmt"
23	"io"
24	"os"
25	"strings"
26	"time"
27)
28
29type wcOutput struct {
30	timestamps bool
31	wc         io.WriteCloser
32}
33
34func (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}
48
49func (w wcOutput) Close() error {
50	return w.wc.Close()
51}
52
53// WriteCloserOutput returns a log.Output implementation that
54// will write formatted messages to the provided io.Writer.
55//
56// Closing returned log.Output object will close the underlying
57// io.WriteCloser.
58//
59// Written messages will include timestamp formatted with millisecond
60// 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 serialization
64// so goroutine-safety depends on the io.Writer. Most operating
65// systems have atomic (read: thread-safe) implementations for
66// 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}
70
71type nopCloser struct {
72	io.Writer
73}
74
75func (nc nopCloser) Close() error {
76	return nil
77}
78
79// WriterOutput returns a log.Output implementation that
80// will write formatted messages to the provided io.Writer.
81//
82// Closing returned log.Output object will have no effect on the
83// underlying io.Writer.
84//
85// Written messages will include timestamp formatted with millisecond
86// 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 serialization
90// so goroutine-safety depends on the io.Writer. Most operating
91// systems have atomic (read: thread-safe) implementations for
92// 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}