]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/logger.go
Stylistic fixes
[govpn.git] / src / cypherpunks.ru / govpn / logger.go
1 // +build !windows
2
3 /*
4 GoVPN -- simple secure free software virtual private network daemon
5 Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
6               2016-2017 Bruno Clermont <bruno@robotinfra.com>
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 package govpn
23
24 import (
25         "bytes"
26         "fmt"
27         logsyslog "log/syslog"
28         "os"
29         "sort"
30         "time"
31
32         "github.com/Sirupsen/logrus"
33         "github.com/Sirupsen/logrus/hooks/syslog"
34         "github.com/pkg/errors"
35 )
36
37 // syslogFormatter is a syslog friendly formatter
38 type syslogFormatter struct{}
39
40 // Format converts a log entry into a list of bytes
41 func (sf *syslogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
42         buf := bytes.NewBuffer(nil)
43         var (
44                 err   error
45                 index int
46         )
47         keys := make([]string, len(entry.Data))
48         for k := range entry.Data {
49                 keys[index] = k
50                 index++
51         }
52         sort.Strings(keys)
53
54         for index = range keys {
55                 k := keys[index]
56                 v := entry.Data[k]
57                 if _, err = buf.WriteString(fmt.Sprintf("[%s]%+v ", k, v)); err != nil {
58                         return nil, errors.Wrapf(err, "buf.WriteString %s", k)
59                 }
60         }
61         if _, err = buf.WriteString(entry.Message); err != nil {
62                 return nil, errors.Wrap(err, "buf.WriteString message")
63         }
64         return buf.Bytes(), nil
65 }
66
67 // NewLogger returns a logger for specified level. Syslog or Windows Events can be turned on.
68 func NewLogger(level string, syslog bool) (*logrus.Logger, error) {
69         var logger *logrus.Logger
70         logLevel, err := logrus.ParseLevel(level)
71         if err != nil {
72                 return nil, errors.Wrap(err, "logrus.ParseLevel")
73         }
74
75         if syslog {
76                 syslogHook, err := logrus_syslog.NewSyslogHook("", "", logsyslog.LOG_INFO, "GoVPN")
77                 if err != nil {
78                         return nil, errors.Wrap(err, "logrus_syslog.NewSyslogHook")
79                 }
80                 logger = &logrus.Logger{
81                         Formatter: &syslogFormatter{},
82                         Hooks:     make(logrus.LevelHooks),
83                 }
84                 logger.Hooks.Add(syslogHook)
85         } else {
86                 logger = &logrus.Logger{
87                         Formatter: &logrus.TextFormatter{
88                                 ForceColors:      true,
89                                 DisableColors:    false,
90                                 DisableTimestamp: false,
91                                 FullTimestamp:    true,
92                                 TimestampFormat:  time.RFC3339Nano,
93                                 DisableSorting:   false,
94                         },
95                         Hooks: make(logrus.LevelHooks),
96                 }
97         }
98         logger.Out = os.Stderr
99         logger.Level = logLevel
100         logger.WithFields(logrus.Fields{
101                 "version": VersionGet(),
102                 "level":   logLevel.String(),
103         }).Info("Initialize logging")
104         return logger, nil
105 }
106
107 // ExtendLogFields adds batch of log Fields to existing fields ones
108 func ExtendLogFields(input *logrus.Fields, add logrus.Fields) {
109         i := *input
110         for k, v := range add {
111                 i[k] = v
112         }
113 }
114
115 // MergeLogFields combines multiple log fields into a single one
116 func MergeLogFields(fields ...logrus.Fields) (output logrus.Fields) {
117         output = logrus.Fields{}
118         for _, f := range fields {
119                 ExtendLogFields(&output, f)
120         }
121         return
122 }